Nie wszytko jeszcze działa jak należy (wersja robocza), ale potestować można. Wywołanie (poprzednie nie działało, bo trzeba użyć nawiasów kwadratowych):
Kod: Zaznacz cały
; EH_killed.sqs, wersja 1.1 (Event Handler Killed - uniwersalny: CYWIL/EAST)
; Nazwa skryptu "EH_killed.sqs" jest używana wewnątrz, jeśli skrypt został zapisany pod inną nazwą - trzeba odpowiednio zmodyfikować nazwę dla EH:
; w dwóch miejscach: blok "assignEHkilled" oraz "assignEHanimdone".
; aszek, 2009
; Skrypt wprowadza do gry zasady RoE:
; 1. Nie wolno zabijać cywili graczą po stronie WEST.
; 2. Zabicie cywila skutkuje ostrzeżeniem gracza i członków drużyny (aby dowódca odziału wiedział).
; 3. Zabicie trzech cywili skutkuje niepowodzeniem całej misji.
; Skrypt arbitralnie osądza czy zabity cywil zginoł z winy WEST, czy aby śmierć cywila nie była spowodzowana przypadkiem, lub
; była z winy innej strony EAST/GUER/CIVIL - za co WEST nie ponosi odpowiedzialności.
; Skrypt wprowadza do gry ryzyko detonacji ładunku wybuchowego, który może zostać jednorazowo aktywowany podczas przeszukiwania zwłok,
; 4. TYLKO zabitego terrorysty (strona EAST)
; Przeszukiwanie zwłok terrorysty (strona EAST) może zakończyć się:
; 6. Detonacją bardzo silnej bomby, natychmiast (10%)
; 7. Detonacją granatu z opuźnionym zapłonem, w 10 sekund (40%)
; 8. Detonacją nieszkodliwej flary, natychmiast (70%)
; Składnia wywołania:
; [_unit] exec "EH_killed.sqs";
; np: [this] exec "EH_killed.sqs";
; np: [cywil1] exec "EH_killed.sqs";
; np: [terrorysta1] exec "EH_killed.sqs";
; Parametry wywołania:
; <_unit>
; POJEDNCZA i TYLKO jedna jednostka CIVILIAN lub EAST, podana w tablicy [...] dla exec !
; Dla wszystkich jednostek CIVILIAN, które zostały zaopatrzone w skrypt, skrypt liczy straty wśród nich.
; Dla każdej jednostki EAST, które zostały zaopatrzone w skrypt, skrypt wprowadza ryzyko detonacji ładunku podczas przeszukiwania zwłok.
; Skrypt odrzuci jednostkę WEST - zabezpiecznie przed pomyłkowym użyciem.
; debugowanie skryptu, dla misji: _debugLevel = _debugLevelNone, inaczej skrypt rzuca hintami !
_debugLevelNone = 0;
_debugLevelAll = 255;
_debugLevelExec = 1;
_debugLevelBlock = 2;
_debugLevelEH = 4;
_debugLevelEHIndex = 8;
_debugLevel = _debugLevelNone;
? (_debugLevel >= _debugLevelExec) : hint format ["Exec\nParam: %1 (%2)", _this, count _this];
;~(count _this)
; jeśli wywołanie skryptu jest z jednym parametrem (jednostka), skrypt założy EH "killed"
? (count _this == 1) : goto "assignEHkilled";
; jeśli wywołanie skryptu jest z większą ilością parametrów (mechanizm AUTOMATYCZNY), skrypt uruchamia się jako EH
? (count _this < 2) : goto "end";
; dla konkretnego EH skrypt wybiera odpowiedni blok w kodzie skryptu
_executereason = _this select 2;
? (_executereason == "Killed") : goto "killed";
? (_executereason == "AnimDone") : goto "animdone";
; Kiedy skrypt wywoływany jest (manualnie, pierwszy raz) z parametrem jednostki, zakłada w bloku 'assignEHkilled' EH "killed",
; aby wykryć śmierć danej jednostki kiedy dana jednostka zginie (optymalne dla CPU),
; Dla EH "killed" skrypt zostanie wywołany automatycznie (przez ten event) i sterowanie skryptu trafi już bezpośrednio do bloku 'killed'
; Dla EH "animdone" skrypt wywoła blok 'animdoneDone'.
#assignEHkilled
_unit = _this select 0;
; dla jednostek WEST skrypt nie działa (zabezpiecznie logiki gry)
? (side _unit == WEST) : hint format ["EH_killed.sqs wywolany z niepoprawnym parametrem: %1.\nStrona nie może byc: %2.", _unit, side _unit]; goto "end";
; dla jednostek CIVIL skrypt zlicza (narazie zeruje) ilość strat i zakłada EH "killed"
? (side _unit == CIVILIAN) : victimCount = 0; PublicVariable "victimCount"; "6" objStatus "ACTIVE"; goto "assignEHkilledNow";
; dla jednostek EAST skrypt zakłada tylko EH "killed", linia ma być nieaktywna - jeśli strona GUER nie występuje w misji
;? (side _unit == EAST) : goto "assignEHkilledNow";
; po sprawdzeniu, czas na założenie EH
#assignEHkilledNow
? (_debugLevel >= _debugLevelBlock) : hint format ["Block assignEHkilled\nUnit: %1 (%2)", _unit, side _unit];
; do parametrów EH dodaje string "Killed", aby kiedy skrypt się automatycznie (ponownie i SAM) uruchomi mógł rozpozać jaki event to spowodował
_EHindex = _unit addEventHandler ["Killed", {_this + ["Killed"] exec "EH_killed.sqs"}];
; aktualizacja tablicy eventów dodanych przez skrypt
_EHparam = [_unit, "Killed", _EHindex, ObjNull];
EHIndexArray = EHIndexArray + [_EHparam];
PublicVariable "EHIndexArray";
;? (_debugLevel == _debugLevelEHIndex) : hint format ["EH killed\nParam: %1", _EHparam];
goto "end";
; Kiedy jednostka zginie, a jest stroną EAST (terrorystów), to blok 'assignEHanimdone' zakłada EH "animdone",
; aby mieć szanse wykrycia próby przeszukania zwłok przez WEST i ew. detonacji bomby terrorysty.
; Blok jest wywoływany tylko z bloku 'killed' dla JUŻ zabitych jednostek EAST, dlatego
; '_unit' wskazuje na zabitą jednostkę (terrorystę)
#assignEHanimdone
; Do parametrów EH dodaje string "AnimDone", aby kiedy skrypt się automatycznie uruchomi mógł rozpozać jaki event to spowodował, oraz
; '_unit' z bloku 'killed', jako terrorystę zabitego przez WEST, mającą być pułapką w EH "animdone" (tam będzie zmienną _trap)
; cała grupa '_killer' (z bloku 'killed') dostaje EH "animdone", aby wykrywać co dana jednostka robi (z osobna)
_index = 0;
_killerGroup = units group _killer;
? (_debugLevel >= _debugLevelBlock) : hint format ["Block assignEHanimdone\nUnits: %1\nTrap: %2 (%3)", _killerGroup, _unit, side _unit];
#assignEHtoKillerGroup
_killerUnit = _killerGroup select _index;
_index = _index + 1;
; dodanie EH "animdone"
EHdeadunit = _unit;
_EHindex = _killerUnit addEventHandler ["AnimDone", {_this + ["AnimDone", EHdeadunit] exec "EH_killed.sqs"}];
; aktualizacja tablicy eventów dodanych przez skrypt
_EHparam = [_killerUnit, "AnimDone", _EHindex, _unit];
EHIndexArray = EHIndexArray + [_EHparam];
; dodanie EH dla całej grupy:
? (_index <= count _killerGroup) : goto "assignEHtoKillerGroup";
; na końcu tablicę eventów rozgłaszamy
PublicVariable "EHIndexArray";
goto "end";
; Blok 'removeEH' nadzoruje tablicą 'EHIndexArray' która przechowuje eventy dodane przez skrypt
; Każdy event jest podtablicą zagnieżdzoną EHparam [_EHparamUnit, _EHparamEvent, _EHparamIndex, _EHparamTrap];
; _EHparamUnit - jednostka dla której skrypt dodał EH
; _EHparamEvent - typ EH: "Killed"/"AnimDone"
; _EHparamIndex - index EH dla jednostki
; _EHparamTrap - zabita jednostka terrorysta
; tablica EHIndexArray to kolejne podtablice EHparam, według schematu:
; EHIndexArray = [ [EHparam_1], [EHparam_2], [EHparam_3]...[EHparam_N] ]
; Blok jest wywoływany automatycznie, wymaga jednak aby punkt wejścia najpierw zdefiniował:
; '_unit' był przypisany (szukana jednostka)
; '_event' był przypisany (szukany typ EH)
; '_EHExitPoint' był przypisany (punkt powrotu z bloku), blok uniwersalnie zwróci sterowanie skryptu do żądanego miejsca
; '_trap' był przypisany jeśli blok obsługuje EH "animdone"
; Blok nie może ingerować w wartość żadnej zmiennej (ma własne zmienne), poza korektą '_EHExitPoint' - jeśli potrzeba.
#removeEH
; standardowo sterowanie jest zwracane do bloku 'killed'->'killedDone' po usunięciu EH (zabezpiecznie jeśli nie określono '_EHExitPoint')
? (isNull _EHExitPoint) : _EHExitPoint = "killedDone";
? (isNull _event) : goto _EHExitPoint;
? (isNull _unit) : goto _EHExitPoint;
; tablica 'EHIndexArray' pusta ? Nie ma co czyścić, blok zwraca sterowanie
? (isNull EHIndexArray) : goto _EHExitPoint;
? (count EHIndexArray == 0) : goto _EHExitPoint;
; podblok przeszukujemy tablice 'EHIndexArray'
? (_debugLevel >= _debugLevelBlock) : hint format ["Block removeEH\nUnit: %1\nEvent: %2\nTrap: %3", _unit, _event, _trap];
_index = 0;
#selectEH
; z tablicy 'EHIndexArray' pobieramy podtablicę '_EHparam'
_EHparam = EHIndexArray select _index;
_index = _index + 1;
; każda podtablica '_EHparam' jest czteroelementowa, przechowuje dane na temat: kto ma EH, jaki typ EH, index EH, ew. ciało terrorysty
_EHparamUnit = _EHparam select 0;
_EHparamEvent = _EHparam select 1;
_EHparamIndex = _EHparam select 2;
_EHparamTrap = _EHparam select 3;
; szukamy konkretnej jednostki z konkretnym EH, '_unit' i '_event' muszą być zdefiniowane przed wywołaniem bloku 'removeEH', '_trap' jest opcjonalne.
? (_EHparamUnit == _unit) and (_EHparamEvent == _event) and (_EHparamTrap == _trap): goto "removeEHbyIndex";
; jeśli jeszcze nie znaleziono właściwego wpisu, to do końca tablicy 'EHIndexArray' go szukamy
? (_index <= count EHIndexArray) : goto "selectEH";
; podblok robi porządek z EH i usuwa wpis z 'EHIndexArray'
#removeEHbyIndex
_EHparamUnit removeEventHandler [_EHparamEvent, _EHparamIndex];
EHIndexArray = EHIndexArray - [_EHparam];
PublicVariable "EHIndexArray";
; podblok zwraca sterowanie do żądanego miejsca '_EHExitPoint', blok wywłujący 'removeEH' określa gdzie sterowanie ma wrócić
goto _EHExitPoint;
; Dla EH "killed" '_this' jest tablicą dwuelementową: [_unit (ofiara), _killer (zabójca)]
; Poza zmienną '_this' mój EH "killed" ma dodatkowo zmienną "Killed", która jednak skryptu TU nie interesuje.
; Blok 'killed' obsługuje scenariusze dla jednostki zabitej, będącą CIVIL (ofiara) lub EAST (terrorysta z bombą)
; Blok 'killed' steruje blokami:
; dla strony CIVIL: 'killed' -> 'civilkilled' -> 'missionDown'
; dla strony EAST: 'killed' -> 'assignEHanimdone' -> 'animdone'
; Blok jest wywoływany tylko kiedy EH "killed" (EH założony w bloku 'assignEHkilled').
#killed
_unit = _this select 0;
_killer = _this select 1;
? (_debugLevel >= _debugLevelBlock) : hint format ["Block killed\nVictim: %1 (%2)\nKiller: %3 (%4) ", _unit, side _unit, _killer, side _killer];
; oszczędzamy CPU:
; _unit jest już określone, więc definije resztę potrzebnych parametrów dla bloku 'removeEH' (usuń Event Handler):
_event = "Killed";
_EHExitPoint = "killedDone";
_trap = ObjNull;
? (_unit in EHIndexArray) : goto "removeEH";
; punk powrotu z 'removeEH'
#killedDone
; jeśli jednostka CIVIL/EAST nie zgineła na skutek WEST, to skrypt nie ma tu nic do roboty
? (_killer != player) or (side _killer != WEST) : goto "end";
; jeśli ofiarą jest CIVIL to skrypt liczy straty
? (side _unit == CIVILIAN) : goto "civilkilled";
; jeśli ofiarą jest EAST to skrypt zakłada EH "animdone", aby śledzić co robi grupa WEST i wykryć próbę przeszukania zwłok EAST
? (side _unit == EAST) : goto "assignEHanimdone";
goto "end";
; blok 'civilkilled' liczy straty wśród CIVIL i steruje niepowodeniem misji w przypadku zbyt dużej ilości ofiar
; blok jest wywoływany tylko z bloku 'killed', kiedy ofiarą jest CIVIL
#civilkilled
victimCount = victimCount + 1;
PublicVariable "victimCount";
? (_debugLevel >= _debugLevelBlock) : hint format ["Block civilkilled\nVictim: %1\nKiller: %2\nTotal victims: %3", _unit, _killer, victimCount];
_killer addScore -1000;
; jeśli liczba ofiar wśród CIVIL osiągneła 3, to misja kończy się natychmiast niepowodzeniem
? (victimCount >= 3) : goto "missionDown";
; ofiar wśród CIVIL jest jeszcze niewystarczająca ilość, grupa dostaje ostrzeżenie
_killer GroupChat format ["Breaked ROE. %1 more dead civilians and the mission is failure", 3 - victimCount];
goto "end";
; blok 'missionDown' zakańcza misję spowodowaną zbyt dużą ilością ofiar CIVIL
; blok jest wywoływany tylko z bloku 'civilkilled', kiedy liczba ofiar przekroczyła dopuszczalną ilość
#missionDown
? (_debugLevel >= _debugLevelBlock) : hint "Block missionDown";
_killer GroupChat "Last breaked ROE. Too much dead civilians - the mission is down";
"6" objStatus "FAILED";
ForceEnd;
goto "end";
; Dla EH "animdone" '_this' jest tablicą dwuelementową: [_unit (jednostka), _anim (zakończona animacja)]
; Poza zmienną '_this' mój EH "animdone" ma dodatkowo zmienną "AnimDone", która jednak skryptu TU nie interesuje, oraz
; EH ma dodatkowo zmienną '_trap' będącą zwłokami zabitego terrorysty.
; Zmienne są dodane przez blok 'assignEHanimdone', i '_trap' służy do sprawdzania odległości, detonacji, zwalniania EH, oraz oszczędności zasobów CPU.
; Po próbie przeszukania zwlok EH "animdone" jest zwalniany - dla już przeszukanych zwłok (oszczędność CPU).
; Blok śledzi co robią jednostki grupy WEST (dla każdej z osobna działa ten EH), która zabiła EAST (terrorystę).
; Blok jest wywoływany tylko kiedy EH "animdone" (założony w bloku 'assignEHanimdone').
#animdone
_unit = _this select 0;
_anim = _this select 1;
_trap = _this select 3;
; jak daleko jest jednostka WEST od trupa EAST ? Jeśli za daleko, to WEST nie może przeszukiwać TEGO trupa,
; albo pobiera uzbrojenie w innym miejscu - co skryptu nie interesuje
? (_unit distance _trap > 1.5) : goto "end";
? (_debugLevel >= _debugLevelBlock) : hint format ["Block animdone\nUnit: %1\nTrap: %2\nAnim: %3", _unit, _trap, _anim];
; WEST jest dostatecznie blisko. Co robi WEST ? Jeśli grzebie w inventory to skrypt interpretuje to jako przeszukanie zwłok EAST
? (_anim != "amovpercmstpsraswrfldnon_ainvpknlmstpslaywrfldnon") : goto "end";
; hint "!";
; Przeszukanie ma miejsce, od razu usuwam EH "animdone":
; _unit i _trap są już określone, więc:
_event = "AnimDone";
_EHExitPoint = "animdoneDone";
? (_unit in EHIndexArray) : goto "removeEH";
; punk powrotu z 'removeEH'
#animdoneDone
; Pozostaje jeszcze tylko ewentualnie wysadzić martwego terrorystę
; Szansa na wybuch pułapki terrorysty
_arm = objNull;
_traparmed = random (1);
; 30% szans, że nic się nie stanie (pułapka rozbrojona)
? (_traparmed < 0.3) : goto "end";
; detonacja pułapki losowa (różne typy uzbrojenia) - można zamienić klase createVehicle na co kto potrzebuje
; najpierw jednak odsiewamy bomby o najmniejszym (warunek: _traparmed > x) prawdopodobieństwie wybuchu - ważna kolejność !
; dla x bliskiego 1 - prawdopodobieństwo detonacji najmniejsze (tego typu amunicji)
; dla x bliskiego 0 - prawdopodobieństwo detonacji największe
? (_traparmed > 0.9) : _arm = "Bo_GBU12_LGB" createVehicle position _unit; goto "end";
? (_traparmed > 0.6) : _arm = "GrenadeHandTimed" createVehicle position _unit; goto "traparmed";
? (_traparmed > 0.3) : _arm = "SmokeShellRed" createVehicle position _unit; goto "traparmed";
goto "end";
; Efekty specjalne dla (lekkiego) ładunku wybuchowego (który mógł się wymsknąć z rąk WEST)
; Blok wywoływany tylko z bloku 'animdone'.
#traparmed
? not (isNull _arm) : _arm setVelocity [random(3), random(3), 3 + random (3)];
goto "end";
; końcowy punkt wyjścia ze skryptu
#end
exit;
Moża to już testować.