[Skrypt] Airborn Warning and Control System (AWACS)

Moderator: Inkwizytor

ODPOWIEDZ
Awatar użytkownika
aszek
Posty: 133
Rejestracja: 11 lipca 2008, 06:17
ID Steam:
Numer GG: 8568774
ID gracza: 0

[Skrypt] Airborn Warning and Control System (AWACS)

Post autor: aszek »

Po długiej przerwie robie następną misję, wkrótce będzie gotowa. Narazie napisałem taki skrypcik (a'la AWACS), może się komuś przyda:

edit:

Nowa, ulepszona wersja. Dla wygody działa już z jedym parametrem (objekt/jednostka):

Kod: Zaznacz cały

[westRadar] exec "radar.sqs";
Dla wymagających pełna swoboda (składnia opisana w skrypcie):

Kod: Zaznacz cały

[westRadar, westRadarTigger, WEST, 2000, 60, 0] exec "radar.sqs";
Dla potrzebujących i ciekawskich radar może rzucać hintami lub nadawać w eter (łatwa możliwość przeróbki hinta na SideChat), opcja:

Kod: Zaznacz cały

_debugLevel = _debugLevelShowRadarStatus;

radar.sqs

Kod: Zaznacz cały

; radar.sqs, wersja 1.2

; Skrypt zbiera informację o jednostkach będących w zasięgu i rozgłasza ich obecność wszystkim jednostką sprzymierzonym.
; aszek, 2009


; Składnia wywołania: 
; [_Radar, _Sensor, _FriendlySide, _SensorRange, _SensorRefreshTime, _SensorIdleTime] exec "radar.sqs"
; np: [westRadar, westRadarTigger, WEST, 2000, 60, 0] exec "radar.sqs";

; Parametry wywołania:
; <_Radar>
; Objekt/jednostka mająca udawać radar i symulować zbieranie informacj o wrogich jednostkach.
; Jeśli parametr jest jednostką, to skrypt na bieżąco będzie aktualizował pozycję skojarzonego wyzwalacza.
; Jeśli parametr zostanie zniszczony, to skrypt nie będzie dłużej aktualizował informacji i zakończy działanie.
; Parametr powinien być podany jako jawna nazwa obiektu/jednostki (nie używać 'this').

; <_Sensor>
; Wyzwalacz odpowiedzialny za wykrywanie wroga (aktywacja = ktokolwiek, raz, obecny).
; Parametr powinien być podany jako nazwa wyzwalacza (nie używać 'this'/'thislist', bo skrypt głupieje).

; <_FriendlySide>
; Strona konfliktu na rzecz której radar pracuje, wartość używana do ustalenia sojuszniczych jednostek.
; Parametr powinien przyjmować jedną z wartości stron konfliktu: WEST/EAST/GUER/CIVILIAN (bez cudzysłowów).

; <_SensorRange>
; Dystans do jakiego radar pracuje, jakiekolwiek jednostki z poza dystansu nie będą brane pod uwagę.
; Jeśli parametr ma wartość '0' to żadna z wykrytych przez '_Sensor' jednostek nie będzie pomijana (odsiewana).
; Jeśli parametr ma wartość większą niż promień działania wyzwalacza '_Sensor', 
; to siłą rzeczy radar nie będzie wiedział o istnieniu takiej jednostki.
; Parametr służy do zawężania obszaru wykrywania wrogich jednostek.
; Parametr nie wyklucza powiadamienia sprzymierzonych jednostek, z poza zasięgu _SensorRange.

; <_SensorRefreshTime>
; Czas w sekundach pomiędzy kolejnymi aktualizacjami.
; Jeśli parametr ma wartość 0, _Radar po jednorazowym zebraniu informacji i rozgłoszeniu ich - kończy pracę (opcja dla wyzwalaczy wielokrotnych, lub zwiadu na żądanie).
; Wartość '0' pozwala jednokrotnie zebrać informację z pola walki (np: w WP, albo np: przez kanał Alfa), 
; po czym radar się natychmiast automatycznie wyłacza.
; Dla ciągłej, nieprzerwanej pracy parametr musi być > '0'. Czas między całkowitym zaniknięciem informacji, wynosi 40-60s.

; <_SensorIdleTime>
; Jeśli przez pewien okres czasu wyrażony wzorem: _SensorIdleTime x _SensorRefreshTime [s], radar nie znajdzie żadnej jednostki, którą zidentyfikował, 
; ani nie znajdzie żadnej jedostki sojuszniczej, której mógłby przekazać aktualizację - to po zdefiniowanym tu czasie nastąpi
; automatyczna dezaktywacja radaru. Ma to na celu zapobiegnięciu marnowania zasobów CPU, gdy w strefie działania wyzwalacza nie zostały
; żadne jedostki, które czerpały by korzyść z jego pracy. Wartość _SensorIdleTime powinna być jednak na tyle duża, 
; aby skrypt nie wyłączył się zbyt wcześniej (zależy od rozmachu misji).
; Parametr jest opcjonalny (może nie wystąpić). Jeśli parametr nie wystąpi w tablicy parametrów podczas uruchamiania skryptu, 
; to skrypt będzie działał poprawnie tak jakby parametr miał wartość '0'.
; Jeśli tu parametr ma wartość '0' automatyczna dezaktywacja skryptu nigdy nie nastąpi (za wyjątkiem sytuacji, gdy '_SensorRefreshTime' == 0).

; Aby skrypt działał poprawnie i wedle wytycznych należy:
; - na mapie umieścić obiekt lub jednostkę mający być radarem, nazwać go.
; - na mapie umieścić wyzwalacz obejmujący swym promieniem cały obszar w którym rozmieszczone są jednostki, np: 1000, nazwać go.
; - podać stronę konfliktu która z radaru korzysta, np: WEST (zachód).
; - podać dystans na jaki wrogie jednostki będą wykrywane, np: 800 [m].
; - podać czas co jaki radar uaktualni swoje działanie, np: 60 [s]. 
; - podać czas jak długo radar ma pracować, np: 0 [s] jeśli bezprzerwy.

; Jednak skrypt będzie działał poprawnie nawet jeśli nie wszystkie parametry zostały podane.
; Absolutnie wymaganym parametrem jest objekt <_Radar>, reszta jest opcjonalna i jeśli nie została podana, to
; skrypt nada im wartości domyślne, oraz samodzielnie utworzy wyzwalacz niezbedny do swojego działania.
; Domyślnie parametry przyjmują wartości tak jakby skrypt został wywołany jako:

; [_Radar, <jakiś wyzwalacz>, WEST, 2000, 60, 0] exec "radar.sqs"

; Skrypt jest wyposażony w mechanizm obsługi błędów sterowany zmienną '_debugLevel'.
; Dla testów i monitorowania aktywności skryptu, można podnieść poziom informacji jakie podaje skrypt podczas pracy.
; Im wyższa wartość tym informację są bardziej szczegółowe. Jako pierwsze pojawiają się informację o błedach, 
; a następnie o tym co robi radar. Dla gotowej misji '_debugLevel' powinien mieć wartość '_debugLevelNone' (0).



private ["_Radar", "_Sensor", "_FriendlySide", "_SensorRange", "_SensorRefreshTime", "_SensorIdleTime", "_SensorIdleScans", "_RadarPos", "_distance"];
private ["_allUnits", "_friendlyUnits", "_knownUnits"];
private ["_allUnitsCount", "_friendlyUnitsCount", "_knownUnitsCount"];
private ["_unit", "_unitPos", "_friendlyUnit", "_knownUnit"];
private ["_index", "_friendlyUnitIndex", "_knownUnitIndex", "_visibleFactor", "_visibleAltitude", "_unitAltitude", "_radarAltitude"];
private ["_gotoBlock", "_ExecError"];



_debugLevelNone = 0;
_debugLevelExecParamErrorCritical = 1;
_debugLevelExecParamErrorWarning = 2;
_debugLevelExecParamErrorHint = 4;
_debugLevelExecParamErrorAll = 8;
_debugLevelShowRadarStatus = 16;
_debugLevel = _debugLevelNone;


#RadarReset
_SensorIdleScans = 0;
_gotoBlock = "getExecParam";
_Radar = objNull;
_Sensor = objNull;
_FriendlySide = NONE;
_SensorRange = 0;
_SensorRefreshTime = 0;
_SensorIdleTime = 0;
_ExecError = 0;

RadarActive = false;
publicVariable "RadarActive";
goto _gotoBlock;



#getExecParam
_paramCount = count _this;
? (_paramCount < 1) : _ExecError = 1; _gotoBlock = "end"; goto "error";
? (_paramCount < 2) : _Radar = _this select 0; _RadarPos = Getpos _Radar; goto "setDefaultParam_Sensor";
? (_paramCount < 3) : _Sensor = _this select 1; goto "setDefaultParam_Side";
? (_paramCount < 4) : _FriendlySide = _this select 2; goto "setDefaultParam_SensorRange";
? (_paramCount < 5) : _SensorRange = _this select 3; goto "setDefaultParam_SensorRefreshTime";
? (_paramCount < 6) : _SensorRefreshTime = _this select 4; goto "setDefaultParam_SensorIdleTime";
? (_paramCount < 7) : _SensorIdleTime = _this select 5;
goto "RadarStart";



#setDefaultParam_Sensor
_Sensor = createTrigger ["EmptyDetector", _RadarPos];
_Sensor setTriggerType "NONE";
_Sensor setTriggerStatements ["this", "", ""];
_Sensor triggerAttachVehicle [_Radar];
_ExecError = 2; 
_gotoBlock = "setDefaultParam_Side";
goto "error";

#setDefaultParam_Side
_FriendlySide = WEST;
_ExecError = 3; 
_gotoBlock = "setDefaultParam_SensorRange";
goto "error";

#setDefaultParam_SensorRange
_SensorRange = 2000;
_Sensor setTriggerArea [_SensorRange, _SensorRange, 0, false];
_ExecError = 4; 
_gotoBlock = "setDefaultParam_SensorRefreshTime";
goto "error";

#setDefaultParam_SensorRefreshTime
_SensorRefreshTime = 30;
_Sensor setTriggerTimeout [_SensorRefreshTime, _SensorRefreshTime, _SensorRefreshTime, false];
_ExecError = 5; 
_gotoBlock = "setDefaultParam_SensorIdleTime";
goto "error";

#setDefaultParam_SensorIdleTime
_SensorIdleTime = 0;
_ExecError = 6; 
_gotoBlock = "RadarStart";
goto "error";



#RadarIdle
? (_SensorIdleTime > 0) : _SensorIdleScans = _SensorIdleScans + 1;
~1
goto "RadarScan";



#RadarStart
_Sensor setTriggerActivation ["ANY", "PRESENT", (_SensorRefreshTime == 0)];
? (CanMove _Radar) : _Radar SetGroupID ["November", "GroupColor4"];

RadarActive = true;
publicVariable "RadarActive";

_ExecError = 7; 
_gotoBlock = "RadarScan";
goto "error";



#RadarScan
? (_SensorIdleScans > _SensorIdleTime) : _ExecError = 10; goto "RadarStop";
? not RadarActive : _ExecError = 11; goto "RadarStop";
? not (Alive _Radar) : _ExecError = 13; goto "RadarStop";

~_SensorRefreshTime

? (CanMove _Radar) : _RadarPos = Getpos _Radar; _Sensor SetPos _RadarPos; "RadarMarker" SetMarkerPos _RadarPos;

_allUnits = list _Sensor;
? (_Radar in _allUnits) : _allUnits = _allUnits - [_Radar];
_allUnitsCount = count _allUnits;
? (_allUnitsCount == 0) : goto "RadarIdle";



_index = 0;
#removeDeadUnits
_unit = _allUnits select _index;
? (not Alive _unit) : {_allUnits = _allUnits - [_unit]; _allUnitsCount = _allUnitsCount - 1; _index = _index - 1};
_index = _index + 1;
? (_index <= _allUnitsCount) : goto "removeDeadUnits";
? (_allUnitsCount == 0) : goto "RadarIdle";



_friendlyUnits = [];
_friendlyUnitsCount = 0;
_knownUnits = [];
_knownUnitsCount = 0;

_index = 0;
#sortUnits
_unit = _allUnits select _index;
_unitPos = GetPos _unit;

? (side _unit == _FriendlySide) : _friendlyUnits = _friendlyUnits + [_unit];

? (_SensorRange == 0) : _distance = 0; 
? (_SensorRange != 0) : _distance = _RadarPos distance _unitPos;
? (_SensorRange < _distance) : goto "nextUnit";
? (_SensorRange == 0) : goto "skipcheckvisiblecone";

_visibleFactor = 70 / _SensorRange; 
_visibleAltitude = _visibleFactor * _distance;
_unitAltitude = _unitPos select 2;
_radarAltitude = _RadarPos select 2;

? (_unitAltitude > _visibleAltitude - _radarAltitude) : goto "nextUnit";
? (_unitAltitude < -_visibleAltitude + _radarAltitude) : goto "nextUnit";

#skipcheckvisiblecone
? (side _unit == civilian) : goto "nextUnit";
? not (_unit in _knownUnits) : _knownUnits = _knownUnits + [_unit];
goto "nextUnit";



#nextUnit
_index = _index + 1;
? (_index <= _allUnitsCount) : goto "sortUnits";

_friendlyUnitsCount = count _friendlyUnits;
_knownUnitsCount = count _knownUnits;


? (_friendlyUnitsCount == 0) : goto "RadarIdle";
? (_knownUnitsCount == 0) : goto "RadarIdle";

_SensorIdleScans = 0;
_knownUnitIndex = 0;
#selectKnownUnit
_knownUnit = _knownUnits select _knownUnitIndex;
_knownUnitIndex = _knownUnitIndex + 1;

_friendlyUnitIndex = 0;
#selectFriendlyUnit
_friendlyUnit = _friendlyUnits select _friendlyUnitIndex;
_friendlyUnitIndex = _friendlyUnitIndex + 1;

? (_friendlyUnit knowsAbout _knownUnit < 4) : _friendlyUnit reveal _knownUnit;
? (_friendlyUnitIndex <= _friendlyUnitsCount) : goto "selectFriendlyUnit";
? (_knownUnitIndex <= _knownUnitsCount) : goto "selectKnownUnit";

? (_SensorRefreshTime == 0) : _ExecError = 12; goto "RadarStop";
? (_debugLevel < _debugLevelShowRadarStatus) : goto "RadarScan";

_ExecError = 9;
_gotoBlock = "RadarScan";
goto "error";



#error
_errorMessage = "";

? (_debugLevel == _debugLevelNone) : goto "errorReset";
? (_debugLevel < _debugLevelExecParamErrorCritical) : goto "errorReset";

? (_ExecError == 0) : _errorMessage = "Radar.sqs: Nieznany blad"; goto "errorShow";
? (_ExecError == 1) : _errorMessage = "Radar.sqs: Blad krytyczny, objekt _Radar (1) jest wymagany !"; goto "errorShow";

? (_debugLevel < _debugLevelExecParamErrorWarning) : goto "errorReset";

? (_ExecError == 2) : _errorMessage = "Radar.sqs: Ostrzezenie, parametr _Sensor (2) nieobecny - utworzono domyslny wyzwalacz."; goto "errorShow";
? (_ExecError == 3) : _errorMessage = format ["Radar.sqs: Ostrzezenie, parametr _FriendlySide (3) nieobecny - wartosc domyslna: %1", _FriendlySide]; goto "errorShow";

? (_debugLevel < _debugLevelExecParamErrorHint) : goto "errorReset";

? (_ExecError == 4) : _errorMessage = format ["Radar.sqs: Uwaga, parametr _SensorRange (4) nieobecny - wartosc domyslna: %1", _SensorRange]; goto "errorShow";
? (_ExecError == 5) : _errorMessage = format ["Radar.sqs: Uwaga, parametr _SensorRefreshTime (5) nieobecny - wartosc domyslna: %1", _SensorRefreshTime]; goto "errorShow";

? (_debugLevel < _debugLevelExecParamErrorAll) : goto "errorReset";

? (_ExecError == 6) : _errorMessage = format ["Radar.sqs: Uwaga, parametr _SensorIdleTime (6) nieobecny - wartosc domyslna: %1", _SensorIdleTime]; goto "errorShow";

? (_debugLevel < _debugLevelShowRadarStatus) : goto "errorReset";

? (_ExecError == 7) : _errorMessage = "Radar aktywny."; goto "errorShow";
? (_ExecError == 8) : _errorMessage = "Radar dezaktywowany (przyczyna nieokreslona)."; goto "errorShow";
? (_ExecError == 9) : _errorMessage = "Radar skanuje."; goto "errorShow";
? (_ExecError == 10) : _errorMessage = "Radar przekroczyl czas pracy i zostal zdezaktywowany."; goto "errorShow";
? (_ExecError == 11) : _errorMessage = "Radar dezaktywowany zdalnie."; goto "errorShow";
? (_ExecError == 12) : _errorMessage = "Radar jednoprzebiegowy zostal dezaktywowany automatycznie."; goto "errorShow";
? (_ExecError == 13) : _errorMessage = "Radar zostal zniszczony."; goto "errorShow";
goto "errorReset"; 

#errorShow
? (_errorMessage == "") : goto "errorReset";

hint _errorMessage;
_errorMessage = "";
~5
hint "";
goto "errorReset";

#errorReset
? (_ExecError == 1) : _gotoBlock = "end";
_ExecError = 0;
goto _gotoBlock;



#RadarStop
_gotoBlock = "end";
? (_ExecError == 0) : _ExecError = 8;
goto "error";



#end
RadarActive = false;
publicVariable "RadarActive";
exit;
Ostatnio zmieniony 03 marca 2009, 12:32 przez aszek, łącznie zmieniany 3 razy.
Awatar użytkownika
klamacz
Posty: 818
Rejestracja: 23 listopada 2006, 09:54
ID Steam:
Numer GG: 2019934
ID gracza: 2320644
Lokalizacja: Szczytno
Kontakt:

Re: Airborn Warning and Control System (AWACS)

Post autor: klamacz »

skrypt wyglada bardzo dobrze, swietnie skomentowany i czytelny. Gratulacje :)
Obrazek Obrazek Obrazek Obrazek Obrazek
Obrazek
Awatar użytkownika
SaS TrooP
Posty: 1586
Rejestracja: 30 października 2008, 17:30
ID Steam:
ID gracza: 0
Lokalizacja: Wodzisław Śl.
Kontakt:

Re: Airborn Warning and Control System (AWACS)

Post autor: SaS TrooP »

Ja też kcem tak umieć!
Mistrzostwo!
Awatar użytkownika
aszek
Posty: 133
Rejestracja: 11 lipca 2008, 06:17
ID Steam:
Numer GG: 8568774
ID gracza: 0

Re: Airborn Warning and Control System (AWACS)

Post autor: aszek »

Dziękuje :)

Jednak i tak musiałem poprawić kilka rzeczy w AWACS'ie (post zedytowany) i dopisałem kolejny skrypt uzupełniający, który sprawia, że funkcjonalność radaru można teraz naprawdę skutecznie wykorzystać, zaś sama misja (do której te skrypty) będzie (mam nadzieje) nareszcie wyzwaniem taktycznym w walce z AI. Narazie tylko dodam, że te skrypty obsłużą reakacje wroga...

Tymczasem, choć jeszcze nie gotowy (daleko do tego) to skrypt pościgu za wrogiem wykorzystujący informację płynące z radaru. Narazie skrypt współpracuje tylko z pojedynczym Heli (najlepiej z AH1Z). Spróbujcie sami jak się rozprawia z T72 ;)) Podpiąć skrypt i można popatrzeć. Heli potrzebuje lądowiska, jednego waypointa z rozkazem straż/warta na lądowisku, a jak w pobliżu będzie stał wóz (wozy) wsparcia (ammo, paliwo) to już załoga całkiem happy będzie. Gdzieś tam niech lata neutralny heli (gwardii, aby go nie zestrzelili) z podpiętym "radar.sqm", albo niech za górki podjeżdzają T72 w odstępach minutowych (bo inaczej wszystkie będą atakowane do skutku) i też będzie na co patrzeć.

Kod: Zaznacz cały

; "chase.sqm", wersja 1
; Skrypt namierza najbliższą, wrogą jednostkę i wysyła pościg mający na celu jej neutralizację.
; Aktualnie: zaimplementowane tylko dla heli.
; Dorobić: zaopatrzenie w bazie, transport (dla jednostek lądowych)
; aszek, 2009

; Składnia wywołania: 
; [_chaseUnit, _restTime] exec "chase.sqm"
; np: [eastMi17, 60] exec "chase.sqm";

; Parametry wywołania:
; <_chaseUnit>
; Jednostka do dyspozycji skryptu.

; <_restTime>
; Czas na odpoczynek pomiędzy kolejnymi zadaniami.

; Sugestię:
; Najwygodniej jest stworzyć jednostkę/grupę (dowodzący grupą zostanie automatycznie znaleziony) i pojedynczy waypoint,
; w którym jednostka będzie czakała na zadanie i do którego wróci (jeśli przeżyje) po wykonaniu zadania (lub ciągu zadań).
; W okolicy waypointa można ustawić jakieś zaopatrzenie (skrzynie, ciężarówke), a grupa sama się dozbroii podczas _restTime.
; Aby wsparcie nam nie odjechało na front, to dajmy waypoint typu warta/straż (w pewnym promieniu aby i śmigłowiec mógł skorzystać).
; W połączeniu ze zwiadem AWACS (radar.sqm) jednostka/grupa pościgowa dysponuje informacjami gdzie szukać wroga.

;effectiveCommander - funkcja nie działa jak nalaży gdy w grupie jest Player (gracz), bo zwykle Player robi co chce, więc efektywnie sam dowodzi, a dowodzącemu rozkazu wydać się nie da ;), dlatego:
_chaseUnit = leader group (_this select 0);
_restTime = _this select 1;

~5
#loop
; _chaseUnit w skrypcie stara się być na bieżąco ze statusem dowodzącego jednostką (grupą) i wydawać rozkazy zgodnie z łańcuchem dowodzenia,
; tak aby AI nie mogło ich zmienić; Dopuki istnieje Heli (narazie tylko Heli).

_chaseUnit = leader group (_this select 0);

? ChaseActiveFlag : goto "end";
? not (Alive _chaseUnit) : goto "end";
? not (canFire vehicle _chaseUnit) : goto "end";
? not (canMove vehicle _chaseUnit) : goto "end";

_knownTargetUnit = _chaseUnit findNearestEnemy getpos _chaseUnit;
? (isNull _knownTargetUnit) : goto "loop";

hint format [" Grupa poscigowa. \n Dowodzi: %1 \n Nowy cel: %2", _chaseUnit, _knownTargetUnit];

; rozkaz 'Move' wydaje się najlepszy, bo _chaseUnit zawsze dotrze na wskazane miejsce (dostaje waypoint)
_chaseUnit Move getpos _knownTargetUnit;
_chaseUnit doFire _knownTargetUnit;

@(not alive _knownTargetUnit) or (not alive _chaseUnit);
@(moveToCompleted _chaseUnit) or (moveToFailed _chaseUnit) or (UnitReady _chaseUnit);
? not (alive _knownTargetUnit) : _knownTargetUnit = nil;

; po zniszczeniu celu głownego, _chaseUnit mogł coś jeszcze namierzyć, niech skończy robotę, 
; w przeciwnym razie powrót do bazy (szkoda paliwa).
_knownTargetUnit = _chaseUnit findNearestEnemy getpos _chaseUnit;
? (isNull _knownTargetUnit) : goto "rebase";

goto "loop";

#rebase

hint " Grupa poscigowa. \n Zadanie wykonane. \n Brak aktywnych celow, powrot do bazy..."

_chaseUnit Move getWPPos [_chaseUnit, 0];
@(moveToCompleted _chaseUnit) or (moveToFailed _chaseUnit) or (UnitReady _chaseUnit);
hint " Grupa pościgowa. \n Baza, podchodze do lądowania...";

_driver = leader vehicle _chaseUnit;

unassignVehicle _driver;
vehicle _chaseUnit action ["LAND", _driver];
@((moveToCompleted _chaseUnit) or (moveToFailed _chaseUnit)) and (UnitReady _chaseUnit);

hint " Grupa poscigowa. \n Baza, lądowanie wykonane";

_driver assignAsCommander _chaseUnit;
_driver action ["getin driver", _chaseUnit];
@(_driver in _chaseUnit) and (UnitReady _chaseUnit);

; czas na zatrzymanie silnika, aby wirnik nie pocharatał wsparacia...
~10

hint " Grupa poscigowa. \n Baza, dozbrajanie w toku...";

driver _chaseUnit action ["rearm", vehicle _chaseUnit];
@((moveToCompleted _chaseUnit) or (moveToFailed _chaseUnit)) and (UnitReady _chaseUnit);

~_restTime
hint " Grupa poscigowa. \n Baza, Gotowa do następnego zadania !";

goto "loop";

#end

hint " Grupa poscigowa. \n Baza, koniec akcji.";
exit;
Tylko nie ustawiać flyInHeight < 30, bo kobra potrzebuje trochę miejsca na manewrowanie. Pewnie z akceleracją czasu też się rozbije. Mam jeszcze problem z tym "rearm", ale mam nadzieje, że w końcu skłonie ciężarówki do obsługi heli.
"True glory consists in doing what deserves to be written, in writing what deserves to be read." - Pliny The Elder
Awatar użytkownika
aszek
Posty: 133
Rejestracja: 11 lipca 2008, 06:17
ID Steam:
Numer GG: 8568774
ID gracza: 0

Re: Airborn Warning and Control System (AWACS)

Post autor: aszek »

Jako, że mam problem z poprawnym działaniem funkcji: isNil(), isNull() dla jednostek,
przypisaniem typu: (_unit = ObjNull), (_unit = nil)
testowaniem tego: (_unit == ObjNull), (isNull(_unit)), (isNil(_unit)),

Jak widze jednostka po śmierci nie jest usuwana z pamięci (w końcu ciała i wraki pozostają), tyle, że nie wiem jak w kodzie odrzucić jednostkę której daje _unit = ObjNull. Nawet: (ObjNull == ObjNull) => false, zawracane są jakieś skalary, więc lekko przerobiłem "chase.sqm".

Tym razem obyło się już bez 'unassignVehicle'. U mnie jednostka poprawnie startuje, leci gdzie trzeba i grzecznie wraca na lądowisko. Może to ktoś sprawdzić u siebie ?

Kod: Zaznacz cały

; chase.sqm, wersja 1.2

; Skrypt namierza najbliższą, wrogą jednostkę i wysyła pościg mający na celu jej neutralizację - wielokrotnie.
; Aktualnie: zaimplementowane tylko dla heli.
; aszek, 2009

; Składnia wywołania: 
; [_chaseUnit, _restTime] exec "chase.sqm"
; np: [eastMi17, 60] exec "chase.sqm";

; Parametry wywołania:
; <_chaseUnit>
; Jednostka do dyspozycji skryptu.

; <_restTime>
; Czas na odpoczynek pomiędzy kolejnymi zadaniami.

_chaseUnit = leader group (_this select 0);
_restTime = _this select 1;

ChaseActiveFlag = false;

; StatusIdle, StatusEngage, StatusRebase
_chaseStatus = "StatusIdle";
_knownTargetUnit = ObjNull;
_isAssignedTargetUnit = false;

vehicle _chaseUnit setGroupId ["Kilo", "GroupColor4"];

goto "loop";

; pętla idle szuka celu i kiedy go znajdzie wysyła _chaseUnit na akcję
#idle
~1

hint " Grupa poscigowa oczekuje na rozkazy ";

; _chaseUnit w skrypcie stara się być na bieżąco ze statusem dowodzącego jednostką (grupą) i wydawać rozkazy zgodnie z łańcuchem dowodzenia, tak aby AI nie mogło ich zmienić.
_chaseUnit = leader group (_this select 0);

; jeśli międzyczasie coś się jej przydarzy, to skypt zwalnia CPU
? not (Alive _chaseUnit) : goto "end";
? not (canFire vehicle _chaseUnit) : goto "end";
? not (canMove vehicle _chaseUnit) : goto "end";

_knownTargetUnit = _chaseUnit findNearestEnemy getpos _chaseUnit;
_isAssignedTargetUnit = alive _knownTargetUnit;

; zdalne wyłaczenie skryptu tylko w przypadku kiedy _chaseUnit jest 'bezpieczna' (nic nie robi)
? ChaseActiveFlag : goto "end";

? (not _isAssignedTargetUnit) : goto "idle";

_chaseStatus = "StatusEngage";
goto "loop";


; pętla engage kieruje _chaseUnit do celu, kieruje atakiem, po ataku sprawdza czy jest kolejny cel
; jeśli natychmiast nie ma innego celu, to _chaseUnit jest kierowana z powrotem do bazy
#engage
~0.1
hint " Alarm dla grupy poscigowej !";

; jeśli _chaseUnit dopiero startuje z lądowiska to żeby się sama nie ostrzelała, 
; czekamy, aż nabierze wysokości i zacznie się przemieszczać.

_chaseUnit LockWP false;
_chaseUnit setSpeedMode "FULL";
_chaseUnit setCombatMode "BLUE";

;_chaseUnit Move (getpos _knownTargetUnit);
;(vehicle _chaseUnit) setDestination [(getpos _knownTargetUnit), "LeaderDirect", true];

_lowerSafeAltitude = ((getpos vehicle _chaseUnit) select 2) + 10;
_lowerSafeSpeed = 1;
@((getpos vehicle _chaseUnit select 2) > _lowerSafeAltitude) and (speed vehicle _chaseUnit > _lowerSafeSpeed);

; priorytetem jest zniszczenie celu, więc _chaseUnit nie powinna atakować wszystkiego 'co się rusza'...
(vehicle _chaseUnit) setSpeedMode "NORMAL";
(vehicle _chaseUnit) setCombatMode "YELLOW";

#engageNext
hint format [" Dowodzi: %1 \n Aktywny cel: %2 ", _chaseUnit, _knownTargetUnit];

_chaseUnit Move (getpos _knownTargetUnit);
_chaseUnit doFire _knownTargetUnit;

; _chaseUnit atakuje do skutku, ale aby skrypt nie utknoł w miejscu, kiedy _chaseUnit nie jest już zdolna do walki to:
@(someAmmo vehicle _chaseUnit) and (CanFire vehicle _chaseUnit) and (alive vehicle _chaseUnit) and (alive _knownTargetUnit);

_knownTargetUnit = _chaseUnit findNearestEnemy getpos _chaseUnit;
_isAssignedTargetUnit = alive _knownTargetUnit;

? ((_isAssignedTargetUnit) and (SomeAmmo vehicle _chaseUnit) and (CanFire vehicle _chaseUnit)) : goto "engageNext";

_isAssignedTargetUnit = false;
_chaseStatus = "StatusRebase";
goto "loop";



; pętla rebase sprowadza _chaseUnit do bazy i przezbraja, po wykonaniu odsyła _chaseUnit w stan poszukiwania celów
#rebase
~0.1

hint " Brak aktywnych celow, powrot do bazy...";

; _chaseUnit wraca do swojego, pierwszego waypointa
; przetwarzanie skryptu jest zatrzymane do momentu wykonania/niemożliwości wykonania ruchu, i wykonania pośrednich rozkazów AI (przemieszczanie niskopoziomowe)
_chaseUnit Move getWPPos [_chaseUnit, 0];
@(moveToCompleted _chaseUnit) or (moveToFailed _chaseUnit) or (UnitReady _chaseUnit);

? not (Alive _chaseUnit) : goto "end";
? not (canMove vehicle _chaseUnit) : goto "end";

hint " Ladowanie... ";
; jednostka ląduje, skrypt czeka na koniec tego procesu
vehicle _chaseUnit land "LAND";
@(UnitReady vehicle _chaseUnit);

? not (Alive _chaseUnit) : goto "end";
? not (canMove vehicle _chaseUnit) : goto "end";

; jednostka wyłącza silnik, skrypt czeka na koniec tego procesu
leader vehicle _chaseUnit action ["ENGINEOFF", vehicle _chaseUnit];
@(UnitReady vehicle _chaseUnit);

? not (Alive _chaseUnit) : goto "end";
? not (canMove vehicle _chaseUnit) : goto "end";

; jednostka stara się pobrać uzbrojenie (często nie działa bo support nie podjeższa dostatecznie blisko)
; o ile jednostki naziemne nie mają z tym problemów to niestety jednostki latające tak, muszę napisać kolejny skrypt...

;_rearmNeedFactor = needReload vehicle _chaseUnit;
;hint format ["%1", _rearmNeedFactor];

;? not (someAmmo _chaseUnit) : 
;leader vehicle _chaseUnit action ["REARM", vehicle _chaseUnit];
; @[_chaseUnit, _supportUnit] exec "rearm.sqm";
;@(UnitReady vehicle _chaseUnit);


? not (canFire vehicle _chaseUnit) : goto "end";
? not (someAmmo vehicle _chaseUnit) : goto "end";


~_restTime

; jeśli _chaseUnit jest nawet mocno uszkodzona, to dla skryptu zachowuje wartość bojową, pod warunkiem że ma czym strzelać
; jeśli nie, to skrypt zostawia ją na lądowisku (z wyłąconym silnikiem) i kończy pracę

_chaseStatus = "StatusIdle";
goto "loop";


; pętla sterująca
; schemat działania: "idle" -> "engage" -> "rebase" -> "idle" -> ... 
#loop
; jeśli brak celu a _chaseUnit nie podjeło jeszcze (ciągle) działań, to do skutku czeka w petli "idle" (najczęściej)
; "StatusIdle" może nadać tylko pętla "rebase"
? (_chaseStatus == "StatusIdle") : goto "idle";

; jeśli jest cel, lub _chaseUnit jest aktualnie na akcji, to do zlikwidowania celu/ów jest w pętli "engage"
; "StatusEngage" może nadać tylko pętla "idle"
? (_chaseStatus == "StatusEngage") : goto "engage";

; jeśli cel został wyeliminowany i w danym momencie (natychmiast) nie ma następnego, 
; to _chaseUnit jest kierowana do bazy w pętli "rebase"
; "StatusRebase" może nadać tylko pętla "engage"
? (_chaseStatus == "StatusRebase") : goto "rebase";

goto "loop";

; punkt wyjścia ze skryptu (_chaseUnit zneutralizowana, ChaseActiveFlag = true)
#end

; żeby załoga nie siedziała w bezbronnym heli jak idioci, to niech mogą przynajmniej zrobić użytek ze swojej broni osobistej 
; a jeśli już przypadkiem są w górze to ich przyziemimy:

vehicle _chaseUnit land "LAND";
@(UnitReady vehicle _chaseUnit);
leader _chaseUnit action ["ENGINEOFF", vehicle _chaseUnit];
@(UnitReady vehicle _chaseUnit);

_chaseUnitCrew = crew (vehicle _chaseUnit); 
[_chaseUnitCrew] allowGetIn false;
{unassignVehicle _x; _x setCombatMode "YELLOW"; _x leaveVehicle (vehicle _chaseUnit)} forEach _chaseUnitCrew;

hint " Grupa poscigowa. \n Baza, koniec akcji.";
exit;
"True glory consists in doing what deserves to be written, in writing what deserves to be read." - Pliny The Elder
Awatar użytkownika
aszek
Posty: 133
Rejestracja: 11 lipca 2008, 06:17
ID Steam:
Numer GG: 8568774
ID gracza: 0

Re: [Skrypt] Airborn Warning and Control System (AWACS)

Post autor: aszek »

Aktualizacja skryptu AWACSa - jeśli ktoś zainteresowany :)
"True glory consists in doing what deserves to be written, in writing what deserves to be read." - Pliny The Elder
ODPOWIEDZ

Wróć do „Edytor - tworzenie misji, skrypty oraz programowanie”