168 lines
6.2 KiB
C
168 lines
6.2 KiB
C
[ComponentEditorProps(category: "GameScripted/", description: "Voice Range Controller (Per Meter)")]
|
|
class SCR_VoiceRangeControllerClass: ScriptComponentClass {}
|
|
|
|
class SCR_VoiceRangeController: ScriptComponent {
|
|
|
|
[Attribute("25", UIWidgets.Slider, "Start-Reichweite in Metern", "1 100 1")]
|
|
protected int m_iCurrentRange;
|
|
|
|
[Attribute("1", UIWidgets.Slider, "Minimale Reichweite", "1 100 1")]
|
|
protected int m_iMinRange;
|
|
|
|
[Attribute("100", UIWidgets.Slider, "Maximale Reichweite", "1 100 1")]
|
|
protected int m_iMaxRange;
|
|
|
|
[Attribute("1", UIWidgets.Slider, "Schrittgroesse (Meter pro Tastendruck)", "1 50 1")]
|
|
protected int m_iStepSize;
|
|
|
|
protected IEntity m_RangeRingEntity;
|
|
protected int m_iLastInputTime = 0;
|
|
|
|
static SCR_VoiceRangeController GetInstance() {
|
|
if (!GetGame().GetPlayerController()) return null;
|
|
return SCR_VoiceRangeController.Cast(GetGame().GetPlayerController().FindComponent(SCR_VoiceRangeController));
|
|
}
|
|
|
|
override void OnPostInit(IEntity owner) {
|
|
super.OnPostInit(owner);
|
|
SetEventMask(owner, EntityEvent.INIT);
|
|
}
|
|
|
|
protected override void EOnInit(IEntity owner) {
|
|
// Wir warten 1 Sekunde (1000ms), bevor wir die Tasten registrieren,
|
|
// damit der PlayerController garantiert vollständig geladen ist.
|
|
GetGame().GetCallqueue().CallLater(RegisterInputs, 1000, false, owner);
|
|
}
|
|
|
|
void RegisterInputs(IEntity owner) {
|
|
PlayerController pc = PlayerController.Cast(owner);
|
|
if (!pc) return;
|
|
|
|
// Sind wir der lokale Spieler an diesem PC?
|
|
if (pc != GetGame().GetPlayerController()) {
|
|
return;
|
|
}
|
|
|
|
InputManager inputManager = GetGame().GetInputManager();
|
|
if (!inputManager) {
|
|
Print("GTG Voice: FEHLER - Kein InputManager gefunden!", LogLevel.ERROR);
|
|
return;
|
|
}
|
|
|
|
// Tasten registrieren
|
|
inputManager.AddActionListener("GTG_RangeUp", EActionTrigger.DOWN, IncreaseRange);
|
|
inputManager.AddActionListener("GTG_RangeDown", EActionTrigger.DOWN, DecreaseRange);
|
|
|
|
Print("GTG Voice: ERFOLG - Tasten registriert und bereit!", LogLevel.WARNING);
|
|
}
|
|
|
|
void IncreaseRange() {
|
|
if (System.GetTickCount() < m_iLastInputTime + 250) return;
|
|
m_iLastInputTime = System.GetTickCount();
|
|
ChangeRange(1);
|
|
}
|
|
|
|
void DecreaseRange() {
|
|
if (System.GetTickCount() < m_iLastInputTime + 250) return;
|
|
m_iLastInputTime = System.GetTickCount();
|
|
ChangeRange(-1);
|
|
}
|
|
|
|
void ChangeRange(int direction) {
|
|
int newRange = Math.ClampInt(m_iCurrentRange + (direction * m_iStepSize), m_iMinRange, m_iMaxRange);
|
|
if (m_iCurrentRange == newRange) return;
|
|
|
|
// Wir loggen immer, damit du siehst, ob das Skript arbeitet
|
|
Print("GTG Voice: Taste erkannt. Neue Reichweite: " + newRange.ToString(), LogLevel.WARNING);
|
|
|
|
m_iCurrentRange = newRange;
|
|
|
|
ApplyRangeToVON();
|
|
UpdateUI();
|
|
DrawRangeCircle();
|
|
}
|
|
|
|
protected void ApplyRangeToVON() {
|
|
PlayerController pc = PlayerController.Cast(GetOwner());
|
|
if (!pc) return;
|
|
IEntity player = pc.GetControlledEntity();
|
|
if (!player) return;
|
|
|
|
SCR_VONController vonContr = SCR_VONController.Cast(GetOwner().FindComponent(SCR_VONController));
|
|
if (!vonContr) return;
|
|
|
|
// Finde heraus, welche Komponente wir basierend auf den Metern brauchen
|
|
typename compType = SCR_VoNNormal;
|
|
if (m_iCurrentRange <= 15) compType = SCR_VoNWhispering;
|
|
else if (m_iCurrentRange >= 50) compType = SCR_VoNLoud;
|
|
|
|
SCR_VoNComponent newVonComp = SCR_VoNComponent.Cast(player.FindComponent(compType));
|
|
if (newVonComp) {
|
|
// Nur wechseln, wenn sich die Stufe WIRKLICH ändert (verhindert unnötige Updates)
|
|
if (vonContr.GetVONComponent() == newVonComp) return;
|
|
|
|
// Komponente sanft wechseln OHNE den Toggle (behält Push-to-Talk und Mute-Status bei!)
|
|
vonContr.SetVONComponent(newVonComp);
|
|
|
|
Print("GTG Voice: VON-Stufe gewechselt zu: " + compType.ToString(), LogLevel.WARNING);
|
|
}
|
|
}
|
|
|
|
void UpdateUI() {
|
|
SCR_HUDManagerComponent hud = SCR_HUDManagerComponent.Cast(GetOwner().FindComponent(SCR_HUDManagerComponent));
|
|
if (!hud) return;
|
|
|
|
SCR_VoiceRangeDisplay display = SCR_VoiceRangeDisplay.Cast(hud.FindInfoDisplay(SCR_VoiceRangeDisplay));
|
|
if (display) display.UpdateRangeText(m_iCurrentRange);
|
|
}
|
|
|
|
void DrawRangeCircle()
|
|
{
|
|
PlayerController pc = PlayerController.Cast(GetOwner());
|
|
// Sicherheitscheck: Nur beim lokalen Spieler zeichnen
|
|
if (!pc || pc != GetGame().GetPlayerController()) return;
|
|
|
|
IEntity player = pc.GetControlledEntity();
|
|
if (!player) return;
|
|
|
|
if (m_RangeRingEntity)
|
|
{
|
|
SCR_EntityHelper.DeleteEntityAndChildren(m_RangeRingEntity);
|
|
m_RangeRingEntity = null;
|
|
}
|
|
|
|
vector playerPos = player.GetOrigin();
|
|
playerPos[1] = playerPos[1] + 0.1;
|
|
|
|
EntitySpawnParams params = new EntitySpawnParams();
|
|
params.TransformMode = ETransformMode.WORLD;
|
|
params.Transform[3] = playerPos;
|
|
|
|
ResourceName ringPrefab = "{E95CB8F4C4B2C210}Prefabs/Decals/Markings/Runway/Decal_Helipad_01.et";
|
|
Resource res = Resource.Load(ringPrefab);
|
|
|
|
if (res && res.IsValid())
|
|
{
|
|
m_RangeRingEntity = GetGame().SpawnEntityPrefab(res, GetGame().GetWorld(), params);
|
|
|
|
if (m_RangeRingEntity)
|
|
{
|
|
float baseSize = 5.0;
|
|
float finalScale = m_iCurrentRange / baseSize;
|
|
m_RangeRingEntity.SetScale(finalScale);
|
|
Print(string.Format("GTG Voice: Meter %1 -> Scale gesetzt auf %2", m_iCurrentRange, finalScale), LogLevel.WARNING);
|
|
}
|
|
}
|
|
|
|
GetGame().GetCallqueue().Remove(HideRangeCircle);
|
|
GetGame().GetCallqueue().CallLater(HideRangeCircle, 2000, false);
|
|
}
|
|
|
|
// DIESE FUNKTION HAT GEFEHLT:
|
|
void HideRangeCircle() {
|
|
if (m_RangeRingEntity) {
|
|
SCR_EntityHelper.DeleteEntityAndChildren(m_RangeRingEntity);
|
|
m_RangeRingEntity = null;
|
|
}
|
|
}
|
|
} |