ACRE Event Handler

  • Mit folgendem Code gewährleiste ich, dass Feinde auf TFAR Gespräche und TFAR Funk reagieren. Ich nutze also den OnSpeak bzw. OnTangent Event Handler von TFAR.

    Code
    1. if (SCHMITT_TFAR_IST_VERFUEGBAR) then{ // reagiere auf TFAR Sprachkommunikation (ausgehend vom aktiven Spieler, nicht von anderen hörend, sondern was der aktive Spieler selbst sagt) ["BeliebigeID1", "OnSpeak", { [_this select 0, _this select 1] spawn schmitt_fnc_lasseFeindAufTFARGespraecheReagierenTeil1; }, player] call TFAR_fnc_addEventHandler;
    2. // reagiere auf TFAR Funkkommunikation (ausgehend vom aktiven Spieler, nicht von anderen empfangend/hörend, sondern was der aktive Spieler selbst funkt) ["BeliebigeID2", "OnTangent", { [_this select 0, _this select 4] spawn schmitt_fnc_lasseFeindAufTFARGespraecheReagierenTeil1; }, player] call TFAR_fnc_addEventHandler;};


    Wie sieht nun der entsprechende ACRE basierte Code aus? Wie lautet die ACRE Event Handler für Gespräche und Funk?

    Code
    1. if (SCHMITT_ACRE_IST_VERFUEGBAR) then{ // TODO lasse Feind auf ACRE Gespräche reagieren ... // TODO lasse Feind auf ACRE Funk reagieren ...};


    Der Vollständigkeit halber sei erwähnt, dass ich mit folgendem Skript prüfe, ob ACRE oder TFAR im Repo enthalten ist:

    Code
    1. SCHMITT_ACRE_IST_VERFUEGBAR = isClass(configFile >> "cfgPatches" >> "acre_api");
    2. if (SCHMITT_ACRE_IST_VERFUEGBAR) then { diag_log "ACRE ist im Repo enthalten und daher für diese Mission mitgeladen worden."; };
    3. SCHMITT_TFAR_IST_VERFUEGBAR = isClass(configFile >> "cfgPatches" >> "task_force_radio");
    4. if (SCHMITT_TFAR_IST_VERFUEGBAR) then { diag_log "TFAR ist im Repo enthalten und daher für diese Mission mitgeladen worden."; };
  • Gut zu wissen, dass man bei ACRE durch Sprechen für den Feind "aufgedeckt" (reveal) wird. Aber das heißt ja noch nicht zwangsläufig, dass der Feind auch sofort losrennt und den Sprecher angreift (?) Genau das will ich aber bewerkstelligen. Daher noch einmal die Frage: Gibt es ACRE Event Handler analog zu TFAR, welche mir skriptseitig die Chance geben auf ACRE Gespräche/Funk zu reagieren?

  • Falls du mit den Macros nichts anfangen kannst, kopier dir die compilierte Version ingame in den Zwischenspeicher.

    Da ich es in der Tat sehr mühsam finde, die Macros in lesbaren Code umzuwandeln (sofern ich mich erinnern kann muss ich dazu gedanklich zwischen der HPP Datei und dem makro-basierten Code hin und her wechseln bis ich die Makros entschlüsselt habe) würde ich gern deinem Tipp folgen.


    Wie kann ich die kompilierte Version ingame in den Zwischenspeicher kopieren? Code in eine globale Variable packen und dann über Debug Konsole auslesen in etwas so


    meineglobalevariable = { [QGVAR(onRevealUnit), [acre_player, _curUnit, ACRE_REVEAL_AMOUNT ] ] call CALLSTACK(CBA_fnc_globalEvent); };


    ? Oder was meinst du?

  • Also die Funktion acre_sys_core_fnc_enableRevealAI hab ich überprüft. Darin wird via


    Code
    1. ["acre_sys_core_onRevealUnit", [acre_player, _curUnit, 1.6 ] ] call CBA_fnc_globalEvent ;


    der aktuelle Spieler gegenüber der feindlichen Einheit aufgedeckt in dem in der verlinkten acre_sys_core_onRevealUnit via


    Code
    1. _unit reveal [_player, _revealAmount];


    der eigentliche reveal Code ausgeführt wird.


    Die große Frage, die sich mir nun stellt ist, wie mische ich mich ein in den Code ohne das die @acre2 PBO modifizieren zu müssen.


    Gehe ich Recht in der Annahme, dass ich die Code-Variable acre_sys_core_fnc_enableRevealAI in meiner init.sqf (oder reicht initPlayerLocal.sqf?) mit meinem modifizierten Code austauschen muss?


    Der originale Code in der Variablen acre_sys_core_fnc_enableRevealAI ist wie folgt aufgebaut:



    Ich nehme also an ich muss zunächst den FrameHandler entfernen via

    Code
    1. [acre_sys_core_monitorAIHandle] call CBA_fnc_removePerFrameHandler;

    Im Anschluss überschreib ich dann die globale Variable acre_sys_core_fnc_enableRevealAI mit meinem eigenen Code. Oder hab ich einen Denkfehler?

  • Gehe ich Recht in der Annahme, dass ich die Code-Variable acre_sys_core_fnc_enableRevealAI in meiner init.sqf (oder reicht initPlayerLocal.sqf?) mit meinem modifizierten Code austauschen muss?

    CBA compiliert standardmäßig mit compileFinal. Somit klappt das nicht (CBA_Cachedisable einmal außenvorgelassen).


    Eine mögliche Lösung hast du allerdings schon genannt:
    1. Du entfernst den ACRE PFH
    2. Du erstellst einen modifizierten PFH

  • Code
    1. // init.sqf
    2. ["acre_sys_core_onRevealUnit", {
    3. params ["_player", "_unit", "_revealAmount"];
    4. systemChat format ["%1 revealed for %2", _player, _unit];
    5. }] call CBA_fnc_addEventHandler;

    Man kann beliebig viele weitere Eventfunktionen zu dem Event hinzufügen und die werden dann immer aufgerufen, wenn ACRE einen Spieler für die KI aufdecken soll.
    Was genau soll denn erreicht werden?

  • Ich will einen sehr aggresiven Feind erzeugen, der sofort angreift, wenn er in unmittelbarer Nähe Feinde hört. Es stört mich, wenn man sich unterhalten kann und der Feind einfach vorbeiläuft obwohl er einen 5 Meter hinter sich locker hören müsste.


    Für TFAR hab ich dazu 2 Funktionen geschrieben. Eine prüft, ob der Gegner den Spieler hätte hören müssen. Wenn ja, wird die zweite Funktion wie folgt ausgelöst.


    [[player, _feindEinheit], "schmitt_fnc_lasseFeindAufZuLautenSpielerReagieren", "AN_SERVER"] spawn schmitt_fnc_mpPaketSenden;


    Die Funktion funktioniert auch wunderbar im TFAR Umfeld. Jetzt muss ich eben umprogrammieren, sodass die Mission auch im ACRE Umfeld funktioniert. Dazu möchte ich meine Funktion im ACRE Code verstecken:

    Code
    1. if (_lastRevealed + 15 < time) then
    2. {
    3. _curUnit setVariable ["acre_sys_core_lastRevealed", time, false];
    4. ["acre_sys_core_onRevealUnit", [acre_player, _curUnit, 1.6 ] ] call CBA_fnc_globalEvent;
    5. // Es folgt die neue Schmitt-spezifische Zeile
    6. [[acre_player, _curUnit], "schmitt_fnc_lasseFeindAufZuLautenSpielerReagieren", "AN_SERVER"] spawn schmitt_fnc_mpPaketSenden;
    7. };


    Mein erster Versuch dazu lautete gerade



    Code
    1. // Zunächst den originalen ACRE Handler entfernen:
    2. [acre_sys_core_monitorAIHandle] call CBA_fnc_removePerFrameHandler;
    3. // Dann den modifizierten ACRE Handler starten:
    4. acre_sys_core_fnc_enableRevealAI =
    5. { ...

    Aber das klappt nicht. Wie ihr geschrieben habt, liegt das an der finalen Kompilierung von acre_sys_core_fnc_enableRevealAI. Schade ^^



    Code
    1. => 18:07:52 Attempt to override final function - acre_sys_core_fnc_enablerevealai



    Ich werde nun commy2s Ansatz verfolgen und das bedeutet konkret in meiner init.sqf (da müsste doch die initPlayerLocal.sqf der bessere Platz sein weil die Funktion den Server nicht interessiert?):



    Code
    1. ["acre_sys_core_onRevealUnit",
    2. {
    3. params ["_player", "_unit", "_revealAmount"];
    4. systemChat format ["%1 revealed for %2", _player, _unit];
    5. [[_player, _unit], "schmitt_fnc_lasseFeindAufZuLautenSpielerReagieren", "AN_SERVER"] spawn schmitt_fnc_mpPaketSenden;
    6. }
    7. ] call CBA_fnc_addEventHandler;

    ... Trommelwirbel ...


    Juhu!! Funktioniert wunderbar! https://steamuserimages-a.akam…B81862687928F10AE9FFEF76/



    Besten Dank an die Runde!

  • Freut mich, dass es funktioniert. Der Sinn von diesen Eventhandlern ist ja gerade, modularen Code aufzubauen der Überschreibungen von Funktionen nicht benötigt. Die Distanz kann man mit _player distance _unit berücksichtigen.

  • Auf lautester ACRE Einstellung hören mich die Feinde sogar aus 150 Meter. Krass. Wie dem auch sei, wie komm ich an die aktuelle Sprechlautstärke ran?


    Die Sprechlautstärke (-2, -1, 0, +1, +2) ist gespeichert in einer globalen Variable "PRÄFIX_VolumeControl_Level". Nur kenn ich den Präfix nicht.


    https://github.com/IDI-Systems…VolumeControl_Level&type=


    Wer kann mir den GVAR(VolumeControl_Level) auflösen in den tatsächlichen globalen Variablennamen?


    Hab das gefunden im ACRE Code:



    Code
    1. MAINPREFIX = "idi"
    2. PREFIX = "acre"

    Hab daraus zusammengereimt, die gesuchte Variable müsste idi_acre_sys_core_VolumeControl_Level heißen. Kein Glück :-(


    Komme mit GVAR nicht klar... https://cbateam.github.io/CBA_…cros_common-hpp.html#GVAR

  • So. Endlich gefunden: acre_sys_gui_VolumeControl_Level


  • Jo, passt prinzipiell.
    Jetzt musst du dir nur noch einmal Gedanken über die Lokalitäten der einzelnen Variablen und Einheiten machen :-)

    Meine Funktion meldet lediglich clientseitig an den Server "Hallo ich bin so laut, dass Feind neben mir mich vermutlich gehört hat". Um den Rest kümmern sich ausschließlich serverseitige Skripte. Da "player" clientseitig eindeutig ist, und Feindeinheiten clientseitig bzgl. Position zumindest bekannt sind, hab ich kein Problem mit den Lokalitäten :-)

  • acre_sys_core_onRevealUnit is ein globales Event. Somit wird dieses Script überall ausgeführt.
    acre_sys_gui_VolumeControl_Level is eine lokale Variable zu jedem einzelnen Spieler.


    Das Event wird zeitgleich auf allen Clients ausgeführt. Somit prüfen alle Clients, ob die Spielereinheit in Reichweite von dem Gegner ist. Jedoch gleichen sie die Entfernung mit ihrer eigenen lokalen Variable ab.
    Das heist, sobald nur ein einziger Spieler auf dem Server am schreien ist, werden alle Spieler schneller aufgeklärt.
    Auch wird dein Server-Event dadurch viel zu häufig ausgeführt.


    Da ist schon ein Problem mit den Lokalitäten vorhanden, falls du es so nutzt, wie oben gezeigt.