diff options
| author | hybrid <hybrid@hybridlabs.pro> | 2026-06-11 19:58:31 +0300 |
|---|---|---|
| committer | hybrid <hybrid@hybridlabs.pro> | 2026-06-11 19:58:31 +0300 |
| commit | e670b4ed55c459a21090bd0178ceaaaf12d87989 (patch) | |
| tree | b6833d5e842475f0ee27f5f617096445fdd4e4a1 /Server/Module | |
| download | a2wf_fallujah-e670b4ed55c459a21090bd0178ceaaaf12d87989.tar.gz a2wf_fallujah-e670b4ed55c459a21090bd0178ceaaaf12d87989.tar.bz2 a2wf_fallujah-e670b4ed55c459a21090bd0178ceaaaf12d87989.zip | |
init
Diffstat (limited to '')
| -rw-r--r-- | Server/Module/NEURO/NEURO.sqf | 240 | ||||
| -rw-r--r-- | Server/Module/UPSMON/Init_UPSMON.sqf | 576 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON.sqf | 2575 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/!R/R_functions.sqf | 343 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/!R/markerAlpha.sqf | 14 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/MON_artillery_add.sqf | 64 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/MON_spawn.sqf | 115 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/MON_surrended.sqf | 23 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/actions/followme.sqf | 93 | ||||
| -rw-r--r-- | Server/Module/UPSMON/UPSMON/common/MON_functions.sqf | 2204 |
10 files changed, 6247 insertions, 0 deletions
diff --git a/Server/Module/NEURO/NEURO.sqf b/Server/Module/NEURO/NEURO.sqf new file mode 100644 index 0000000..53f7ad2 --- /dev/null +++ b/Server/Module/NEURO/NEURO.sqf @@ -0,0 +1,240 @@ +/*
+ * Neuro Taxi System by Benny.
+ * Use the missionNamspace to set a condition for boarding the vehicle (NEURO_TAXI_CONDITION), _x define the vehicle.
+ * i.e: missionNamespace setVariable["NEURO_TAXI_CONDITION", "isNil {_x getVariable 'WFBE_Taxi_Prohib'}"];
+ */
+
+NEURO_BE_ClearVehiclePositions = {
+ {
+ if (!alive _x || _x distance _this > 900) then {unassignVehicle _x};
+ } forEach (assignedCargo _this);
+
+ {
+ if !(isNull _x) then {if (!alive _x || _x distance _this > 900) then {unassignVehicle _x}};
+ } forEach [assignedDriver _this, assignedGunner _this, assignedCommander _this];
+};
+
+NEURO_BE_GetVehicleEmptiness = {
+ Private ["_cargo","_commander","_driver","_gunner","_hasCommander","_hasDriver","_hasGunner","_isFull","_isEmpty","_vehicleCargo"];
+ //--- Update the ETAT.
+ (_this) Call NEURO_BE_ClearVehiclePositions;
+
+ _driver = _this emptyPositions "driver";
+ _gunner = _this emptyPositions "gunner";
+ _commander = _this emptyPositions "commander";
+ _cargo = _this emptyPositions "cargo";
+
+ _hasDriver = false;
+ _hasGunner = false;
+ _hasCommander = false;
+ _vehicleCargo = count (assignedCargo _this);
+ if !(isNull(assignedDriver _this)) then {_driver = 0;_hasDriver = true;};
+ if !(isNull(assignedGunner _this)) then {_gunner = 0;_hasGunner = true;};
+ if !(isNull(assignedCommander _this)) then {_commander = 0;_hasCommander = true;};
+
+ _cargo = abs (_cargo - _vehicleCargo);
+
+ _isFull = if (_driver == 0 && _gunner == 0 && _commander == 0 && _cargo == 0) then {true} else {false};
+ _isEmpty = if (!_hasDriver && !_hasGunner && !_hasCommander) then {true} else {false};
+
+ [_driver,_gunner,_commander,_cargo,_isFull,_isEmpty]
+};
+
+NEURO_BE_GetNonAssignedUnits = {
+ Private ["_list"];
+ _list = [];
+
+ {
+ if (isNull(assignedVehicle _x)) then {_list = _list + [_x]};
+ } forEach _this;
+
+ _list
+};
+
+NEURO_BE_GetSuitableVehicles = {
+ Private ["_list","_nearest","_process","_side"];
+ _nearest = _this select 0;
+ _side = _this select 1;
+
+ _list = [];
+ {
+ if (canMove _x && fuel _x > 0.2 && (side _x) in [civilian, _side]) then {
+ _process = true;
+ if !(isNull(driver _x)) then {if (!local(driver _x) || (side driver _x) != _side) then {_process = false}};
+ if (!(isNull(assignedDriver _x)) && _process) then {if (!local(assignedDriver _x) || (side assignedDriver _x) != _side) then {_process = false}};
+
+ if (_process) then {
+ if (Call Compile (missionNamespace getVariable 'NEURO_TAXI_CONDITION')) then {
+ _list = _list + [_x];
+ };
+ };
+
+ };
+ } forEach _nearest;
+
+ _list
+};
+
+NEURO_BE_GetGroupWPDestination = {
+ Private ["_destination"];
+ _destination = [0,0,0];
+
+ if (isNull _this) exitWith {_destination};
+
+ if (count waypoints _this > 0) then {
+ _destination = waypointPosition [_this, currentWaypoint _this];
+ };
+
+ _destination
+};
+
+NEURO_BE_GetVehicleZOffset = {
+ (getPos _this) select 2
+};
+
+NEURO_BE_HandleArrivalCargo = {
+ Private ["_vehicle"];
+ _vehicle = vehicle _this;
+
+ //--- Paradrop or unload.
+ if ((_vehicle) Call NEURO_BE_GetVehicleZOffset > 25) then {
+ {
+ if !(surfaceIsWater(getPos _vehicle)) then {
+ if (alive _x && _vehicle == vehicle _x && local _x) then {
+ unassignVehicle _x;
+ [_x] orderGetIn false;
+ _x action ["EJECT", _vehicle];
+ sleep 1.2;
+ };
+ } else {
+ unassignVehicle _x;
+ [_x] orderGetIn false;
+ };
+ } forEach (assignedCargo _vehicle);
+ } else {
+ {
+ if (alive _x && _vehicle == vehicle _x && local _x) then {
+ unassignVehicle _x;
+ [_x] orderGetIn false;
+ sleep 0.4;
+ };
+ } forEach (assignedCargo _vehicle);
+ };
+};
+
+NEURO_BE_UpdateTeamDestination = {
+ Private ["_assignedVehicle","_destinationDriver","_forceOut","_group","_groupDestination"];
+ _group = _this;
+ _forceOut = [];
+
+ _groupDestination = (_group) Call NEURO_BE_GetGroupWPDestination;
+
+ {
+ _assignedVehicle = assignedVehicle _x;
+
+ if !(isNull _assignedVehicle) then {
+ if (isNull(driver _assignedVehicle) && isNull(assignedDriver _assignedVehicle) || isPlayer(_assignedVehicle)) then {
+ _forceOut = _forceOut + [_x];
+ } else {
+ _destinationDriver = (group (driver _assignedVehicle)) Call NEURO_BE_GetGroupWPDestination;
+ if (_groupDestination distance _destinationDriver > 600) then {
+ if (_x in (assignedCargo _assignedVehicle)) then {_forceOut = _forceOut + [_x]};
+ };
+ };
+ };
+ } forEach (units _group);
+
+ if (count _forceOut > 0) then {
+ {unassignVehicle _x} forEach _forceOut;
+ _forceOut orderGetIn false;
+ };
+};
+
+NEURO_BE_AssignToVehicle = {
+ Private ["_assignedUnits","_cargoEmptiness","_emptiness","_group","_isEmpty","_isFull","_isPlayerVehicle","_near","_position","_process","_range","_unit","_units","_vehicle"];
+ _group = _this select 0;
+ _position = _this select 1;
+ _range = 500;
+
+ _groupUnits = units _group;
+ _units = (_groupUnits) Call NEURO_BE_GetNonAssignedUnits;
+ if (count _units == 0) exitWith {};
+
+ _near = _position nearEntities [["Motorcycle","Car","Tank","Helicopter"], _range];
+ _near = [_near, side _group] Call NEURO_BE_GetSuitableVehicles;
+ if (count _near == 0) exitWith {};
+
+ _assignedUnits = [];
+
+ {
+ _vehicle = _x;
+ _emptiness = (_vehicle) Call NEURO_BE_GetVehicleEmptiness;
+ _cargoEmptiness = _emptiness select 3;
+
+ _isFull = if (_emptiness select 4) then {true} else {false};
+ _isEmpty = if (_emptiness select 5) then {true} else {false};
+ _isPlayerVehicle = if (isPlayer(_vehicle)) then {true} else {false};
+
+ //--- Vehicle is not full.
+ if (!_isFull && !_isPlayerVehicle) then {
+ //--- Driver, Gunner, Commander.
+ if (_isEmpty || (effectiveCommander _vehicle) in _groupUnits) then {
+ //--- Driver
+ if ((_emptiness select 0) > 0) then {
+ (_units select 0) assignAsDriver _vehicle;
+ _assignedUnits = _assignedUnits + [_units select 0];
+ _units = _units - [_units select 0];
+ };
+
+ //--- Gunner.
+ if ((_emptiness select 1) > 0 && count _units > 0) then {
+ (_units select 0) assignAsGunner _vehicle;
+ _assignedUnits = _assignedUnits + [_units select 0];
+ _units = _units - [_units select 0];
+ };
+
+ //--- Commander.
+ if ((_emptiness select 2) > 0 && count _units > 0) then {
+ (_units select 0) assignAsCommander _vehicle;
+ _assignedUnits = _assignedUnits + [_units select 0];
+ _units = _units - [_units select 0];
+ };
+ };
+
+ //--- Cargo.
+ if (_cargoEmptiness > 0 && count _units > 0) then {
+ _count = count _units;
+
+ //--- Make sure that the vehicle is going around the squad's destination.
+ _process = true;
+ if !(isNull(driver _vehicle)) then {
+ _driverMoveTo = (group driver _vehicle) Call NEURO_BE_GetGroupWPDestination;
+ _distance = _driverMoveTo distance ((_group) Call NEURO_BE_GetGroupWPDestination);
+
+ if (_distance > 600 || (_driverMoveTo select 0 == 0 && _driverMoveTo select 1 == 0)) then {_process = false};
+ };
+
+ //--- All condition are met, the ai may be able to board the vehicle.
+ if (_process) then {
+ for '_i' from 0 to _count-1 do {
+ _unit = _units select _i;
+
+ if (_unit distance _vehicle < 500) then {
+ _unit assignAsCargo _vehicle;
+ _assignedUnits = _assignedUnits + [_unit];
+ _cargoEmptiness = _cargoEmptiness - 1;
+ };
+
+ if (_cargoEmptiness <= 0) exitWith {};
+ };
+ };
+ };
+
+ _units = _units - _assignedUnits;
+ };
+
+ if (count _units == 0) exitWith {};
+ } forEach _near;
+
+ if (count _assignedUnits > 0) then {_assignedUnits orderGetIn true};
+};
\ No newline at end of file diff --git a/Server/Module/UPSMON/Init_UPSMON.sqf b/Server/Module/UPSMON/Init_UPSMON.sqf new file mode 100644 index 0000000..b1929a8 --- /dev/null +++ b/Server/Module/UPSMON/Init_UPSMON.sqf @@ -0,0 +1,576 @@ +// =========================================================================================================
+// UPSMON - Urban Patrol Script Mon
+// Version: 5.1.0
+// Author: Monsada (chs.monsada@gmail.com)
+//
+// Wiki: http://dev-heaven.net/projects/upsmon/wiki
+// Forum: http://forums.bistudio.com/showthread.php?t=91696
+// Share your missions with upsmon: http://dev-heaven.net/projects/upsmon/boards/86
+// ---------------------------------------------------------------------------------------------------------
+// Based on Urban Patrol Script
+// Version: 2.0.3
+// Author: Kronzky (www.kronzky.info / kronzky@gmail.com)
+// ---------------------------------------------------------------------------------------------------------
+// Some little fixes: !Rafalsky (v5.0.8 - 5.0.9)
+// ---------------------------------------------------------------------------------------------------------
+
+//Adding eventhandlers
+ "KRON_UPS_EAST_SURRENDED" addPublicVariableEventHandler { if (_this select 1) then { nul=[east] execvm "Server\Module\UPSMON\UPSMON\MON_surrended.sqf";};};
+ "KRON_UPS_WEST_SURRENDED" addPublicVariableEventHandler { if (_this select 1) then { nul=[west] execvm "Server\Module\UPSMON\UPSMON\MON_surrended.sqf";};};
+ "KRON_UPS_GUER_SURRENDED" addPublicVariableEventHandler { if (_this select 1) then { nul=[resistance] execvm "Server\Module\UPSMON\UPSMON\MON_surrended.sqf";};};
+ "MON_LOCAL_EXEC" addPublicVariableEventHandler { if (local ((_this select 1)select 0)) then {
+ call ( compile format[(_this select 1)select 1,(_this select 1)select 0] );
+ };
+ };
+
+
+if (!isServer) exitWith {};
+
+//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+// These Variables should be checked and set as required, to make the mission runs properly.
+//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+// ACE Wounds System for AI (set TRUE to On, set FALSE to Off) !
+ace_sys_wounds_noai = false; // set it as required
+
+//1=Enable or 0=disable debug. In debug could see a mark positioning de leader and another mark of the destination of movement, very useful for editing mission
+KRON_UPS_Debug = 0;
+
+//1=Enable or 0=disable. In game display global chat info about who just killed a civilian.
+//numbers of Civilians killed by players could be read from array 'KILLED_CIV_COUNTER' -> [Total,by West,by East,by Res]
+R_WHO_IS_CIV_KILLER_INFO = 1;
+
+
+// if you are spotted by AI group, how close the other AI group have to be to You , to be informed about your present position. over this, will lose target
+KRON_UPS_sharedist = 600;
+
+// If enabled IA communication between them with radio defined sharedist distance, 0/2
+// (must be set to 2 in order to use reinforcement !R)
+KRON_UPS_comradio = 2;
+
+//Sides that are enemies of resistance
+KRON_UPS_Res_enemy = [east];
+
+// Distance from destination for searching vehicles. (Search area is about 200m),
+// If your destination point is further than KRON_UPS_searchVehicledist, AI will try to find a vehicle to go there.
+KRON_UPS_searchVehicledist = 600; // 700, 900
+
+//Enables or disables AI to use static weapons
+KRON_UPS_useStatics = true;
+
+//Enables or disables AI to put mines if armoured enemies near
+KRON_UPS_useMines = true;
+
+//------------------------------------------------------------------------------------------------------------------------------
+// These Variables can be changed if needed but it is not necessary.
+//------------------------------------------------------------------------------------------------------------------------------
+
+//% of chanse to use smoke by team members when someone wounded or killed in the group in %(default 13 & 35).
+// set both to 0 -> to switch off this function
+R_USE_SMOKE_wounded = 13;
+R_USE_SMOKE_killed = 35;
+
+//Height that heli will fly this input will be randomised in a 10%
+KRON_UPS_flyInHeight = 80;
+
+//Percentage of units to surrender.
+KRON_UPS_EAST_SURRENDER = 0; // 10
+KRON_UPS_WEST_SURRENDER = 0; // 10
+KRON_UPS_GUER_SURRENDER = 0; // 10
+
+// knowsAbout 1.03 , 1.49 to add this enemy to "target list" (1-4) the higher number the less detect ability (original in 5.0.7 was 0.5)
+// it does not mean the AI will not shoot at you. This mean what must be knowsAbout you to AI start asking by radio for help other groups in KRON_UPS_sharedist from you
+R_knowsAboutEnemy = 1.49;
+
+// units will react (change the beahaviour) when dead bodies found
+R_deadBodiesReact = false; // true OR flase
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Better do not change these variables if you aren't sure !R
+// ---------------------------------------------------------------------------------------------------------------------
+
+//Efective distance for doing perfect ambush (max distance is this x2)
+KRON_UPS_ambushdist = 70;
+
+//Max distance to target for doing para-drop, will be randomised between 0 and 100% of this value.
+KRON_UPS_paradropdist = 250;
+
+//Frequency for doing calculations for each squad.
+KRON_UPS_Cycle = 10; //org 20
+
+//Time that lider wait until doing another movement, this time reduced dynamically under fire, and on new targets
+KRON_UPS_react = 60;
+
+//Min time to wait for doing another reaction
+KRON_UPS_minreact = 20; // org 30
+
+//Max waiting is the maximum time patrol groups will wait when arrived to target for doing another target.
+KRON_UPS_maxwaiting = 30;
+
+// how long AI units should be in alert mode after initially spotting an enemy
+KRON_UPS_alerttime = 90;
+
+// how far opfors should move away if they're under attack
+KRON_UPS_safedist = 250; //org 300
+
+// how close unit has to be to target to generate a new one target or to enter stealth mode
+KRON_UPS_closeenough = 300; //org 300
+
+//Enable it to send reinforcements, better done it in a trigger inside your mission.
+KRON_UPS_reinforcement = false;
+
+//Artillery support, better control if set in trigger
+KRON_UPS_ARTILLERY_EAST_FIRE = false; //set to true for doing east to fire
+KRON_UPS_ARTILLERY_WEST_FIRE = false; //set to true for doing west to fire
+KRON_UPS_ARTILLERY_GUER_FIRE = false; //set to true for doing resistance to fire
+
+//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+// Do not touch these variables !!!! !R
+//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ R_GOTHIT_ARRAY =[0];
+ AcePresent = isClass(configFile/"CfgPatches"/"ace_main");
+ UPSMON_Version = "UPSMON 5.1.0 beta1";
+ KILLED_CIV_COUNTER = [0,0,0,0,0];
+ KRON_UPS_flankAngle = 45; //Angulo de flanqueo
+ KRON_UPS_INIT = 0; //Variable que indica que ha sido inicializado
+ KRON_UPS_EAST_SURRENDED = false;
+ KRON_UPS_WEST_SURRENDED = false;
+ KRON_UPS_GUER_SURRENDED = false;
+ KRON_AllWest=[]; //All west AI
+ KRON_AllEast=[]; //All east AI
+ KRON_AllRes=[]; //All resistance AI
+ KRON_UPS_East_enemies = [];
+ KRON_UPS_West_enemies = [];
+ KRON_UPS_Guer_enemies = [];
+ KRON_UPS_East_friends = [];
+ KRON_UPS_West_friends = [];
+ KRON_UPS_Guer_friends = [];
+ KRON_targets0 =[];//objetivos west
+ KRON_targets1 =[];//objetivos east
+ KRON_targets2 =[];//resistence
+ KRON_targetsPos =[];//Posiciones de destino actuales.
+ KRON_NPCs = []; //Lideres de los grupos actuales
+ KRON_UPS_Instances=0;
+ KRON_UPS_Total=0;
+ KRON_UPS_Exited=0;
+ KRON_UPS_East_Total = 0;
+ KRON_UPS_West_Total = 0;
+ KRON_UPS_Guer_Total = 0;
+ KRON_UPS_ARTILLERY_UNITS = [];
+ KRON_UPS_ARTILLERY_WEST_TARGET = objnull;
+ KRON_UPS_ARTILLERY_EAST_TARGET = objnull;
+ KRON_UPS_ARTILLERY_GUER_TARGET = objnull;
+ KRON_UPS_TEMPLATES = [];
+ KRON_UPS_MG_WEAPONS = ["MG36","M249","M240","MK_48","PK","PKm","Pecheneg","M249 Para","M249 Para M145","M240G M145","M60"];
+
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ // ***************************************** SERVER INITIALIZATION *****************************************
+ if (isNil("KRON_UPS_INIT") || KRON_UPS_INIT == 0) then {
+
+ //Init library function, Required Version: 5.0 of mon_functions
+ call compile preprocessFileLineNumbers "Server\Module\UPSMON\UPSMON\common\MON_functions.sqf";
+
+ //init !R functions
+ call compile preprocessFileLineNumbers "Server\Module\UPSMON\UPSMON\!R\R_functions.sqf";
+
+ if (isNil "RE") then {[] execVM "\ca\Modules\MP\data\scripts\MPframework.sqf"};
+
+ //scripts initialization
+ UPSMON = compile preprocessFile "Server\Module\UPSMON\UPSMON.sqf";
+ UPSMON_surrended = compile preprocessFile "Server\Module\UPSMON\UPSMON\MON_surrended.sqf";
+
+ // declaración de variables privadas
+ private["_obj","_trg","_l","_pos"];
+
+ // global functions
+ KRON_randomPos = {private["_cx","_cy","_rx","_ry","_cd","_sd","_ad","_tx","_ty","_xout","_yout"];_cx=_this select 0; _cy=_this select 1; _rx=_this select 2; _ry=_this select 3; _cd=_this select 4; _sd=_this select 5; _ad=_this select 6; _tx=random (_rx*2)-_rx; _ty=random (_ry*2)-_ry; _xout=if (_ad!=0) then {_cx+ (_cd*_tx - _sd*_ty)} else {_cx+_tx}; _yout=if (_ad!=0) then {_cy+ (_sd*_tx + _cd*_ty)} else {_cy+_ty}; [_xout,_yout]};
+ KRON_PosInfo = {private["_pos","_lst","_bld","_bldpos"];_pos=_this select 0; _lst=_pos nearObjects ["House",12]; if (count _lst==0) then {_bld=0;_bldpos=0} else {_bld=_lst select 0; _bldpos=[_bld] call KRON_BldPos}; [_bld,_bldpos]};
+ KRON_PosInfo3 = {private["_pos","_lst","_bld","_bldpos"];_pos=_this select 0; _lst= nearestObjects [_pos, [], 3];
+ if (count _lst==0) then {_bld=objnull;_bldpos=0} else {_bld = nearestbuilding (_lst select 0);
+ _bldpos=[_bld] call KRON_BldPos2}; [_bld,_bldpos]};
+ KRON_BldPos = {private ["_bld","_bldpos","_posZ","_maxZ"];_bld=_this select 0;_maxZ=0;_bi=0;_bldpos=0;while {_bi>=0} do {if (((_bld BuildingPos _bi) select 0)==0) then {_bi=-99} else {_bz=((_bld BuildingPos _bi) select 2); if (((_bz)>4) && ((_bz>_maxZ) || ((_bz==_maxZ) && (random 1>.8)))) then {_maxZ=_bz; _bldpos=_bi}};_bi=_bi+1};_bldpos};
+ KRON_BldPos2 = {private ["_bld","_bldpos"];
+ _bld=_this select 0; _bldpos = 1;
+ while {format ["%1", _bld buildingPos _bldpos] != "[0,0,0]"} do {_bldpos = _bldpos + 1;};
+ _bldpos = _bldpos - 1; _bldpos;};
+
+
+ KRON_getDirPos = {private["_a","_b","_from","_to","_return"]; _from = _this select 0; _to = _this select 1; _return = 0; _a = ((_to select 0) - (_from select 0)); _b = ((_to select 1) - (_from select 1)); if (_a != 0 || _b != 0) then {_return = _a atan2 _b}; if ( _return < 0 ) then { _return = _return + 360 }; _return};
+ KRON_distancePosSqr = {round(((((_this select 0) select 0)-((_this select 1) select 0))^2 + (((_this select 0) select 1)-((_this select 1) select 1))^2)^0.5)};
+ KRON_relPos = {private["_p","_d","_a","_x","_y","_xout","_yout"];_p=_this select 0; _x=_p select 0; _y=_p select 1; _d=_this select 1; _a=_this select 2; _xout=_x + sin(_a)*_d; _yout=_y + cos(_a)*_d;[_xout,_yout,0]};
+ KRON_rotpoint = {private["_cp","_a","_tx","_ty","_cd","_sd","_cx","_cy","_xout","_yout"];_cp=_this select 0; _cx=_cp select 0; _cy=_cp select 1; _a=_this select 1; _cd=cos(_a*-1); _sd=sin(_a*-1); _tx=_this select 2; _ty=_this select 3; _xout=if (_a!=0) then {_cx+ (_cd*_tx - _sd*_ty)} else {_cx+_tx}; _yout=if (_a!=0) then {_cy+ (_sd*_tx + _cd*_ty)} else {_cy+_ty}; [_xout,_yout,0]};
+ KRON_stayInside = {
+ private["_np","_nx","_ny","_cp","_cx","_cy","_rx","_ry","_d","_tp","_tx","_ty","_fx","_fy"];
+ _np=_this select 0; _nx=_np select 0; _ny=_np select 1;
+ _cp=_this select 1; _cx=_cp select 0; _cy=_cp select 1;
+ _rx=_this select 2; _ry=_this select 3; _d=_this select 4;
+ _tp = [_cp,_d,(_nx-_cx),(_ny-_cy)] call KRON_rotpoint;
+ _tx = _tp select 0; _fx=_tx;
+ _ty = _tp select 1; _fy=_ty;
+ if (_tx<(_cx-_rx)) then {_fx=_cx-_rx};
+ if (_tx>(_cx+_rx)) then {_fx=_cx+_rx};
+ if (_ty<(_cy-_ry)) then {_fy=_cy-_ry};
+ if (_ty>(_cy+_ry)) then {_fy=_cy+_ry};
+ if ((_fx!=_tx) || (_fy!=_ty)) then {_np = [_cp,_d*-1,(_fx-_cx),(_fy-_cy)] call KRON_rotpoint};
+ _np;
+ };
+ // Misc
+ KRON_UPSgetArg = {private["_cmd","_arg","_list","_a","_v"]; _cmd=_this select 0; _arg=_this select 1; _list=_this select 2; _a=-1; {_a=_a+1; _v=format["%1",_list select _a]; if (_v==_cmd) then {_arg=(_list select _a+1)}} foreach _list; _arg};
+ KRON_UPSsetArg = {private["_cmd","_arg","_list","_a","_v"];
+ _cmd=_this select 0;
+ _arg=_this select 1;
+ _list=_this select 2;
+ _a=-1;
+ {
+ _a=_a+1;
+ _v= format ["%1", _list select _a];
+ if (_v==_cmd) then {
+ _a=_a+1;
+ _list set [_a,_arg];
+ };
+ } foreach _list;
+ _list};
+ KRON_deleteDead = {private["_u","_s"];_u=_this select 0; _s= _this select 1; _u removeAllEventHandlers "killed"; sleep _s; deletevehicle _u};
+
+
+
+
+
+ // ***********************************************************************************************************
+ // MAIN UPSMON SERVER FUNCTION
+ // ***********************************************************************************************************
+ MON_MAIN_server = {
+
+ private["_obj","_trg","_l","_pos","_countWestSur","_countEastSur","_countResSur","_WestSur","_EastSur","_ResSur","_target","_targets","_targets0","_targets1","_targets2","_npc","_cycle"
+ ,"_arti","_side","_range","_rounds","_area","_maxcadence","_mincadence","_bullet","_fire","_knownpos","_sharedenemy","_enemyside","_timeout"];
+ _cycle = 10; //Time to do a call to commander
+ _arti = objnull;
+ _side = "";
+ _range = 0;
+ _rounds = 0;
+ _area = 0;
+ _maxcadence = 0;
+ _mincadence = 0;
+ _bullet = "";
+ _fire = false;
+ _target = objnull;
+ _knownpos =[0,0,0];
+ _enemyside = [];
+
+ _WestSur = KRON_UPS_WEST_SURRENDED;
+ _EastSur = KRON_UPS_EAST_SURRENDED;
+ _ResSur = KRON_UPS_GUER_SURRENDED;
+
+
+ //Main loop
+ while {true} do
+ {
+ _countWestSur = round ( KRON_UPS_West_Total * KRON_UPS_WEST_SURRENDER / 100);
+ _countEastSur = round ( KRON_UPS_East_Total * KRON_UPS_EAST_SURRENDER / 100);
+ _countResSur = round ( KRON_UPS_Guer_Total * KRON_UPS_GUER_SURRENDER / 100);
+
+ //Checks for WEST surrender
+ if (KRON_UPS_WEST_SURRENDER > 0 && !KRON_UPS_WEST_SURRENDED ) then {
+ {
+ if (!alive _x || !canmove _x) then {KRON_AllWest = KRON_AllWest-[_x]};
+ }foreach KRON_AllWest;
+
+ if ( count KRON_AllWest <= _countWestSur ) then {
+ KRON_UPS_WEST_SURRENDED = true;
+ publicvariable "KRON_AllWest";
+ publicvariable "KRON_UPS_WEST_SURRENDED";
+ };
+ };
+
+ //Checks for EAST surrender
+ if (KRON_UPS_EAST_SURRENDER > 0 && !KRON_UPS_EAST_SURRENDED ) then {
+ {
+ if (!alive _x || !canmove _x) then {KRON_AllEast = KRON_AllEast-[_x]};
+ }foreach KRON_AllEast;
+
+ if ( count KRON_AllEast <= _countEastSur ) then {
+ KRON_UPS_EAST_SURRENDED = true;
+ publicvariable "KRON_AllEast";
+ publicvariable "KRON_UPS_EAST_SURRENDED";
+ };
+ };
+
+ //Checks for RESISTANCE surrender
+ if (KRON_UPS_GUER_SURRENDER > 0 && !KRON_UPS_GUER_SURRENDED ) then {
+ {
+ if (!alive _x || !canmove _x) then {KRON_AllRes = KRON_AllRes-[_x]};
+ }foreach KRON_AllRes;
+
+ if ( count KRON_AllRes <= _countResSur ) then {
+ KRON_UPS_GUER_SURRENDED = true;
+ publicvariable "KRON_AllRes";
+ publicvariable "KRON_UPS_GUER_SURRENDED";
+ };
+ };
+
+ //Exec surrended script
+ if (KRON_UPS_WEST_SURRENDED && !_WestSur ) then {
+ _WestSur = true;
+ [west] spawn UPSMON_surrended;
+ };
+ if (KRON_UPS_EAST_SURRENDED && !_EastSur ) then {
+ _EastSur = true;
+ [east] spawn UPSMON_surrended;
+ };
+ if (KRON_UPS_GUER_SURRENDED && !_ResSur ) then {
+ _ResSur = true;
+ [Resistance] spawn UPSMON_surrended;
+ };
+ sleep 0.5;
+
+ _sharedenemy = 0;
+ _targets0 = [];
+ _targets1 = [];
+ _targets2 = [];
+ {
+ if (!isnull _x && alive _x && !captive _x ) then {
+ _npc = _x;
+ _targets = [];
+
+ switch (side _npc) do {
+ //West targets
+ case west: {
+ _sharedenemy = 0;
+ _enemyside = [east];
+ };
+ //East targets
+ case east: {
+ _sharedenemy = 1;
+ _enemyside = [west];
+ };
+ //Resistance targets
+ case resistance: {
+ _sharedenemy = 2;
+ _enemyside = KRON_UPS_Res_enemy;
+ };
+ };
+
+ if (side _npc in KRON_UPS_Res_enemy) then {
+ _enemyside = _enemyside + [resistance];
+ };
+
+ //Gets known targets on each leader for comunicating enemy position
+ //Has better performance with targetsquery
+ //_targets = _npc nearTargets KRON_UPS_sharedist;
+ _targets = _npc targetsQuery ["","","","",""];
+
+ {
+ //_target = _x select 4; //Neartargets
+ _target = _x select 1; //Targetsquery
+ if ( side _target in _enemyside ) then {
+ // if (KRON_UPS_Debug>0) then {player globalchat format["%1: knows about %2, enemies=%3",_npc getVariable ("UPSMON_grpid"),_npc knowsabout _target, _npc countEnemy _targets ]};
+
+ if (!isnull _target && alive _target && canmove _target && !captive _target && _npc knowsabout _target > R_knowsAboutEnemy
+ && ( _target iskindof "Land" || _target iskindof "Air" || _target iskindof "Ship" )
+ && !( _target iskindof "Animal")
+ && ( _target emptyPositions "Gunner" == 0 && _target emptyPositions "Driver" == 0
+ || (!isnull (gunner _target) && canmove (gunner _target))
+ || (!isnull (driver _target) && canmove (driver _target)))
+ ) then {
+ //Saves last known position
+ //_knownpos = _x select 0; //Neartargets
+ _knownpos = _x select 4;//Targetsquery
+ _target setvariable ["UPSMON_lastknownpos", _knownpos, false];
+ // _npc setVariable ["R_knowsAboutTarget", true, false]; // !R
+
+ call (compile format ["_targets%1 = _targets%1 - [_target]",_sharedenemy]);
+ call (compile format ["_targets%1 = _targets%1 + [_target]",_sharedenemy]);
+ };
+ };
+ sleep 0.01;
+ } foreach _targets;
+ };
+ sleep 0.01;
+ }foreach KRON_NPCs;
+
+ //Share targets
+ KRON_targets0 = _targets0;
+ KRON_targets1 = _targets1;
+ KRON_targets2 = _targets2;
+
+ //Target debug console
+ if (KRON_UPS_Debug>0) then {hintsilent parseText format["%1<br/>--------------------------<br/><t color='#33CC00'>West(A=%2 C=%3 T=%4)</t><br/><t color='#FF0000'>East(A=%5 C=%6 T=%7)</t><br/><t color='#00CCFF'>Res(A=%8 C=%9 T=%10)</t><br/>"
+ ,UPSMON_Version
+ ,KRON_UPS_West_Total, count KRON_AllWest, count KRON_targets0
+ ,KRON_UPS_East_Total, count KRON_AllEast, count KRON_targets1
+ ,KRON_UPS_Guer_Total, count KRON_AllRes, count KRON_targets2 ]};
+ sleep 0.5;
+
+ //Artillery module control
+ {
+ _arti = _x select 0;
+ _rounds = _x select 1;
+ _range = _x select 2;
+ _area = _x select 3;
+ _maxcadence = _x select 4;
+ _mincadence = _x select 5;
+ _bullet = _x select 6;
+ _salvobreak = _x select 7;
+
+ if (isnil{_arti getVariable ("timeout")}) then {
+ _arti setVariable ["timeout", time, false];
+ sleep 0.1;
+ };
+
+ _timeout = _arti getVariable ("timeout");
+
+ if (!isnull (gunner _arti) && canmove (gunner _arti) && (time >= _timeout)) then {
+ _side = side gunner _arti;
+ _fire = call (compile format ["KRON_UPS_ARTILLERY_%1_FIRE",_side]);
+
+
+
+ //If fire enabled gets a known target pos for doing fire if no friendly squads near.
+ if (_fire) then {
+ _target = call (compile format ["KRON_UPS_ARTILLERY_%1_TARGET",_side]);
+ if (isnil "_target" ) then {_target = objnull;};
+
+ switch (_side) do {
+ //West targets
+ case west: {
+ _targets = KRON_targets0;
+ };
+ //East targets
+ case east: {
+ _targets = KRON_targets1;
+ };
+ //Resistance targets
+ case resistance: {
+ _targets = KRON_targets2;
+ };
+ };
+
+ //Check if has a target
+ if (!(_target in _targets ) || isnull _target || !alive _target) then {
+ _target = objnull;
+ {
+ _auxtarget = _x;
+ _targetPos = _auxtarget getvariable ("UPSMON_lastknownpos");
+ if (!isnil "_targetPos") then {
+ //If target in range check no friendly squad near
+ if (alive _auxtarget && !(_auxtarget iskindof "Air") && (round([position _arti,_targetPos] call KRON_distancePosSqr)) <= _range) then {
+ _target = _auxtarget;
+ //Must check if no friendly squad near fire position
+ {
+ if (!isnull _x && _side == side _x) then {
+ if ((round([position _x,_targetPos] call KRON_distancePosSqr)) < (KRON_UPS_safedist * 0.7)) exitwith {_target = objnull;};
+ };
+ } foreach KRON_NPCs;
+ };
+ };
+
+ //If target found exit
+ if (!isnull _target) exitwith {};
+ } foreach _targets;
+ };
+
+ //If target fires artillery
+ if (!isnull _target) then {
+ //Fix current target
+ call (compile format ["KRON_UPS_ARTILLERY_%1_TARGET = _target",_side]);
+ _targetPos = _target getvariable ("UPSMON_lastknownpos");
+ if (!isnil "_targetPos") then {
+
+ _arti removeAllEventHandlers "fired"; sleep 0.01;
+ // chatch the bullet in the air and delete it
+ _arti addeventhandler["fired", {deletevehicle (nearestobject[_this select 0, _this select 4])}];
+ [_arti,_targetPos,_rounds,_area,_maxcadence,_mincadence,_bullet,_salvobreak] spawn MON_artillery_dofire;
+ };
+ };
+ };
+ };
+ sleep 0.5;
+ } foreach KRON_UPS_ARTILLERY_UNITS;
+
+
+ // if (KRON_UPS_Debug>0) then {player globalchat format["Init_upsmon artillery=%1",count KRON_UPS_ARTILLERY_UNITS]};
+ sleep _cycle;
+ };
+ };
+ };
+
+
+// ***********************************************************************************************************
+// INITIALIZATION OF UPSMON
+// ***********************************************************************************************************
+
+ _l = allunits + vehicles;
+ {
+ if ((_x iskindof "AllVehicles") && (side _x != civilian)) then {
+ _s = side _x;
+ switch (_s) do {
+ case west:
+ { KRON_AllWest=KRON_AllWest+[_x]; };
+ case east:
+ { KRON_AllEast=KRON_AllEast+[_x]; };
+ case resistance:
+ { KRON_AllRes=KRON_AllRes+[_x]; };
+ };
+ };
+ } forEach _l;
+ _l = nil;
+
+ if (isNil("KRON_UPS_Debug")) then {KRON_UPS_Debug=0};
+
+ KRON_UPS_East_enemies = KRON_AllWest;
+ KRON_UPS_West_enemies = KRON_AllEast;
+
+ if (east in KRON_UPS_Res_enemy ) then {
+ KRON_UPS_East_enemies = KRON_UPS_East_enemies+KRON_AllRes;
+ KRON_UPS_Guer_enemies = KRON_AllEast;
+ } else {
+ KRON_UPS_East_friends = KRON_UPS_East_friends+KRON_AllRes;
+ KRON_UPS_Guer_friends = KRON_AllEast;
+ };
+
+ if (west in KRON_UPS_Res_enemy ) then {
+ KRON_UPS_West_enemies = KRON_UPS_West_enemies+KRON_AllRes;
+ KRON_UPS_Guer_enemies = KRON_UPS_Guer_enemies+KRON_AllWest;
+ } else {
+ KRON_UPS_West_friends = KRON_UPS_West_friends+KRON_AllRes;
+ KRON_UPS_Guer_friends = KRON_UPS_Guer_friends+KRON_AllWest;
+ };
+
+ KRON_UPS_West_Total = count KRON_AllWest;
+ KRON_UPS_East_Total = count KRON_AllEast;
+ KRON_UPS_Guer_Total = count KRON_AllRes;
+
+ //Initialization done
+ KRON_UPS_INIT=1;
+
+
+ //killciv EH
+ _l = allunits;
+ {
+ if (side _x == civilian) then {
+
+
+ _x AddEventHandler ["firedNear", {nul = _this spawn R_SN_EHFIREDNEAR}];
+ sleep 0.01;
+
+
+ _x AddEventHandler ["killed", {nul = _this spawn R_SN_EHKILLEDCIV}];
+ sleep 0.01;
+ };
+ } forEach _l;
+ _l = nil;
+
+
+
+
+// ---------------------------------------------------------------------------------------------------------
+processInitCommands;
+
+//Executes de main process of server
+[] SPAWN MON_MAIN_server;
+
+diag_log "--------------------------------";
+diag_log (format["UPSMON started"]);
+if(true) exitWith {};
\ No newline at end of file diff --git a/Server/Module/UPSMON/UPSMON.sqf b/Server/Module/UPSMON/UPSMON.sqf new file mode 100644 index 0000000..af4860b --- /dev/null +++ b/Server/Module/UPSMON/UPSMON.sqf @@ -0,0 +1,2575 @@ +// =========================================================================================================
+// UPSMON - Urban Patrol Script
+// version 5.1.0 beta 1
+//
+// Author: Monsada (chs.monsada@gmail.com)
+// Comunidad Hispana de Simulación:
+//
+// Wiki: http://dev-heaven.net/projects/upsmon/wiki
+// Forum: http://forums.bistudio.com/showthread.php?t=91696
+// Share your missions with upsmon: http://dev-heaven.net/projects/upsmon/boards/86
+// ---------------------------------------------------------------------------------------------------------
+// Based on Urban Patrol Script v2.0.3
+// Author: Kronzky (www.kronzky.info / kronzky@gmail.com)
+// ---------------------------------------------------------------------------------------------------------
+// Some little fixes: !Rafalsky (v5.0.8 - 5.1.0)
+// Code improvements: shay_gman(Artillery), Nordin("noveh")
+// ---------------------------------------------------------------------------------------------------------
+
+// Required parameters:
+// unit = Unit to patrol area (1st argument)
+// markername = Name of marker that covers the active area. (2nd argument)
+//
+// Patrol squad samples: (put in the leader's init field)
+// nul=[this,"area0"] execVM "scripts\upsmon.sqf";
+//
+// Defensive squad samples:
+// nul=[this,"area0","nomove"] execVM "scripts\upsmon.sqf";
+//
+// Reinforcement
+// nul=[this,"area0","reinforcement:",1] execVM "scripts\UPSMON.sqf";
+// (in trigger call: KRON_UPS_reinforcement1 = true;
+// (call pos marker mkr1): KRON_UPS_reinforcement1_pos = getMarkerPos "mkr1";
+//
+//
+// Optional parameters: _
+// random = Place unit at random start position.
+// randomdn = Only use random positions on ground level.
+// randomup = Only use random positions at top building positions.
+// min:n/max:n = Create a random number (between min and max) of 'clones'. ("min:",2,"max:",5)
+// init:string = Custom init string for created clones.
+// nomove = Unit will stay or hide in the near buildings until enemy is spotted.
+// nofollow = Unit will only follow an enemy within the marker area.(When fight sometimes can go outside)
+// onroad = Unit will get target destination only on the roads
+// nosmoke = Units will not use smoke when s/o wounded or die.
+// delete:n = Delete dead units after 'n' seconds.
+// nowait = Do not wait at patrol end points.
+// noslow = Keep default behaviour of unit (don't change to "safe" and "limited").
+// noai = Don't use enhanced AI for evasive and flanking maneuvers.
+// trigger = Display a message when no more units are left in sector.
+// empty:n = Consider area empty, even if 'n' units are left.
+// reinforcement = Makes squad as reinforcement, when alarm KRON_UPS_reinforcement==true this squad will go where enemy were.
+// reinforcement:x = Makes squad as reinforcement id, when alarm KRON_UPS_reinforcementx==true this squad will go where enemy were.
+// fortify = makes leader order to take positions on nearly buildings at distance 200 meters, squad fortified moves less than "nomove"
+// aware,combat,stealth,careless defines default behaviour of squad
+// noveh = the group will not search for transport vehicles (unless in fight and only combat vehicles)
+// nowp = No waypoints will be created for this squad UNTIL ENEMY DETECTED, this squad will comunicate enemies but will not be moved by UPSMON until enemy detected, after that upsmon takes control of squad
+// nowp2 = No waypoints will be created for this squad UNTIL ENEMY DETECTED and damaged, this squad will comunicate enemies but will not be moved by UPSMON until enemy detected and damaged, after that upsmon takes control of squad
+// nowp3 = No waypoints will be created for this squad in any way, this squad will comunicate enemies but will not be moved by UPSMON.
+// ambush = Ambush squad will not move until in combat, will lay mines if enabled and wait for incoming enemies stealth and ambush when near or discovered.
+// ambush2 = Ambush squad will not move until in combat, will NOT LAY MINES and wait for incoming enemies stealth and ambush when near or discovered.
+// ambush:n = Creates an anbush and wait maximun the especified time n in seconds. you can put 0 seconds for putting mines and go away if combined with "move" for example
+// ambush2:n = Same as ambush:n but without laying mines.
+// respawn = allow squad to respawn when all members are dead and no targets near
+// respawn:x = allows to define the number of times squad may respawn.
+// showmarker = Display the area marker.
+// track = Display a position and destination marker for each unit.
+
+// spawned = use only with squads created in runtime, this feature will add squad to UPSMON correctly.
+// aware,combat,stealth,careless defines default behaviour of squad
+
+// numbers of Civilians killed by players could be read from the array 'KILLED_CIV_COUNTER' -> [Total, by West, by East, by Res, The Killer]
+
+
+if (!isServer) exitWith {};
+
+
+if (isNil("KRON_UPS_INIT")) then {
+ KRON_UPS_INIT=0;
+};
+
+waitUntil {KRON_UPS_INIT==1};
+
+// convert argument list to uppercase
+ _UCthis = [];
+ for [{_i=0},{_i<count _this},{_i=_i+1}] do {_e=_this select _i; if (typeName _e=="STRING") then {_e=toUpper(_e)};_UCthis set [_i,_e]};
+
+ if ((count _this)<2) exitWith {
+ if (format["%1",_this]!="INIT") then {hint "UPS: Unit and marker name have to be defined!"};
+ };
+
+
+
+// Postioning
+private["_targetX","_targetY","_relTX","_relTY","_relUX","_relUY","_waiting","_pursue","_react","_newpos","_currPos","_orgPos","_targetPos","_attackPos","_flankPos","_avoidPos", "_speedmode"];
+private["_dist","_lastdist","_lastmove1","_lastmove2","_gothit", "_supressed" , "_flankdist","_nBuilding","_nBuildingt","_distnbuid","_distnbuidt"];
+private["_objsflankPos1","_cntobjs1","_objsflankPos2","_cntobjs2","_targettext","_dir1","_dir2","_dir3","_dd","_timeontarget","_dirf1","_dirf2","_fightmode",
+ "_flankPos2","_cosU","_sinU","_cosT","_sinT","_reinforcement","_reinforcementsent","_target","_targets","_flankdir","_prov","_lastpos","_newtarget","_planta","_nomove",
+ "_newflankAngle","_sharedist" ,"_targetPosOld","_fldest","_grpidx","_grpid","_i","_unitpos","_Behaviour", "_incar", "_inheli" , "_inboat","_gunner","_driver"
+ ,"_vehicle","_minreact","_lastreact","_CombatMode","_rnd","_GetOutDist","_GetOut","_GetIn_NearestVehicles","_makenewtarget","_index","_wp","_grp","_wptype","_wpformation","_i"
+ ,"_targetdead","_frontPos","_GetIn","_dist1","_dist2","_dist3","_fldestfront","_fldest2","_bld","_blddist","_bldunitin","_flyInHeight","_fortify","_buildingdist","_rfid","_rfidcalled","_Mines"
+ ,"_enemytanks","_enemytanksnear","_friendlytanksnear","_mineposition","_enemytanknear","_roads","_timeout","_lastcurrpos","_wait","_countfriends","_side","_SURRENDER","_spawned","_nowp","_unitsIn"
+ ,"_ambush","_ambushed","_ambushdist","_friendside","_enemyside","_newattackPos","_fixedtargetpos","_NearestEnemy","_targetdist","_cargo","_targetsnear","_landing","_ambushwait"
+ ,"_membertypes","_respawn","_respawnmax","_lead","_safemode","_vehicles","_dist3","_lastwptype","_template","_unittype","_initstr","_fortifyorig","_nowpType","_ambushtype" ,"_vehicletypes", "_onroad","_loop2", "_tries2","_targetPosTemp","_sokilled","_sowounded","_nosmoke","_newunit","_rlastpos","_rcurrpos","_jumpers","_isSoldier","_noveh","_deadBodiesReact"];
+
+
+_grpid =0;
+_exit = false;
+_fldest = 0;
+_unitpos = "AUTO";
+_vehicle = objnull;
+_minreact = KRON_UPS_minreact;
+_lastreact = KRON_UPS_minreact;
+_rnd = 0.0;
+_GetOutDist = 0;
+_GetOut=false;
+_index = 0;
+_wp=[];
+_wptype="HOLD";
+_wpformation = "VEE";
+_targetdead = false;
+_GetIn=false;
+_dist3 = 0;
+_fldestfront = 0;
+_fldest2=0;
+_bld = objnull;
+_flyInHeight = 0;
+_rfid = 0;
+_rfidcalled = false;
+_Mines = 3;
+_enemytanks = [];
+_friendlytanks =[];
+_enemytanksnear = false;
+_friendlytanksnear = false;
+_mineposition = [0,0,0];
+_enemytanknear = objnull;
+_NearestEnemy = objnull;
+_roads = [];
+_timeout = 0;
+_wait=90;
+_countfriends = 0;
+_side="";
+_friendside=[];
+_enemyside=[];
+_SURRENDER = 0;
+_surrended = false;
+_inheli = false;
+_spawned = false;
+_nowp = false;
+_unitsIn = [];
+_ambush = false;
+_ambushed = false;
+_ambushdist = KRON_UPS_ambushdist;
+_deadBodiesreact = R_deadBodiesReact;
+_dist2 = 0;
+_targetdist = 10000;
+_cargo = [];
+_targetsnear = false;
+_landing=false;
+_ambushwait = 10000;
+_membertypes = [];
+_vehicletypes =[];
+_respawn = false;
+_respawnmax = 10000;
+_lead=objnull;
+_safemode=["CARELESS","SAFE"];
+_vehicles = [];
+_dist3=0;
+_lastwptype = "";
+_unittype = "";
+_initstr = "";
+_fortifyorig= false;
+_rlastPos = [0,0,0];
+
+// unit that's moving
+_obj = leader (_this select 0); //group or leader
+_npc = _obj;
+
+
+
+// give this group a unique index
+KRON_UPS_Instances = KRON_UPS_Instances + 1;
+_grpid = KRON_UPS_Instances;
+_grpidx = format["%1",_grpid];
+_grpname = format["%1_%2",(side _npc),_grpidx];
+_side = side _npc;
+
+
+
+
+//To not run all at the same time we hope to have as many seconds as id's
+_rnd = _grpid;
+sleep _rnd ;
+
+
+
+
+// == set "UPSMON_grpid" to units in the group and EH===============================
+ {
+ _x setVariable ["UPSMON_grpid", _grpid, false];
+ sleep 0.05;
+
+
+ if (side _x != civilian) then
+ {//soldiers
+ _x AddEventHandler ["hit", {nul = _this spawn R_SN_EHHIT}];
+ sleep 0.05;
+ _x AddEventHandler ["killed", {nul = _this spawn R_SN_EHKILLED}];
+ sleep 0.05;
+ }
+ else
+ {//civ
+
+ _x removeAllEventHandlers "firedNear";
+ sleep 0.05;
+ _x AddEventHandler ["firedNear", {nul = _this spawn R_SN_EHFIREDNEAR}];
+ sleep 0.05;
+
+ _x removeAllEventHandlers "killed";
+ sleep 0.05;
+ _x AddEventHandler ["killed", {nul = _this spawn R_SN_EHKILLEDCIV}];
+ sleep 0.05;
+ };
+ } foreach units _npc;
+
+ //if is vehicle will not be in units so must set manually
+ if (isnil {_npc getVariable ("UPSMON_grpid")}) then {
+ _npc setVariable ["UPSMON_grpid", _grpid, false];
+ sleep 0.05;
+
+ if (side _npc != civilian) then
+ {//soldiers
+ _npc AddEventHandler ["hit", {nul = _this spawn R_SN_EHHIT}];
+ sleep 0.05;
+ _npc AddEventHandler ["killed", {nul = _this spawn R_SN_EHKILLED}];
+ sleep 0.05;
+ }
+ else
+ { //civilian
+ _npc removeAllEventHandlers "firedNear";
+ sleep 0.05;
+ _npc AddEventHandler ["firedNear", {nul = _this spawn R_SN_EHFIREDNEAR}];
+ sleep 0.05;
+
+
+
+ _npc removeAllEventHandlers "killed";
+ sleep 0.05;
+ _npc AddEventHandler ["killed", {nul = _this spawn R_SN_EHKILLEDCIV}];
+ sleep 0.05;
+ }
+ };
+ //the index will be _grpid
+ R_GOTHIT_ARRAY = R_GOTHIT_ARRAY + [0];
+
+
+
+if (KRON_UPS_Debug>0) then {player sidechat format["%1: New instance %2 %3 %4",_grpidx,_npc getVariable ("UPSMON_grpid")]};
+
+
+
+
+
+
+
+// == get the name of area marker ==============================================
+ _areamarker = _this select 1;
+ if (isNil ("_areamarker")) exitWith {
+ hint "UPS: Area marker not defined.\n(Typo, or name not enclosed in quotation marks?)";
+ };
+
+ // remember center position of area marker
+ _centerpos = getMarkerPos _areamarker;
+ _centerX = abs(_centerpos select 0);
+ _centerY = abs(_centerpos select 1);
+ _centerpos = [_centerX,_centerY];
+
+ // show/hide area marker
+ _showmarker = if ("SHOWMARKER" in _UCthis) then {"SHOWMARKER"} else {"HIDEMARKER"};
+ if (_showmarker=="HIDEMARKER") then {
+ //_areamarker setMarkerCondition "false"; // VBS2
+ _areamarker setMarkerPos [-abs(_centerX),-abs(_centerY)];
+ };
+
+// is anybody alive in the group?
+ _exit = true;
+ if (typename _npc=="OBJECT") then {
+ if (!isnull group _npc) then {
+ _npc = [_npc,units (group _npc)] call MON_getleader;
+ }else{
+ _vehicles = [_npc,2] call MON_nearestSoldiers;
+ if (count _vehicles>0) then {
+ _npc = [_vehicles select 0,units (_vehicles select 0)] call MON_getleader;
+ };
+ };
+ } else {
+ if (count _obj>0) then {
+ _npc = [_obj,count _obj] call MON_getleader;
+ };
+ };
+
+
+ // set the leader in the vehilce
+ if (!(_npc iskindof "Man")) then {
+ if (!isnull(commander _npc) ) then {
+ _npc = commander _npc;
+ }else{
+ if (!isnull(driver _npc) ) then {
+ _npc = driver _npc;
+ }else{
+ _npc = gunner _npc;
+ };
+ };
+ group _npc selectLeader _npc;
+ };
+
+// ===============================================
+ if (alive _npc) then {_exit = false;};
+ if (KRON_UPS_Debug>0 && _exit) then {player sidechat format["%1 There is no alive members %1 %2 %3",_grpidx,typename _npc,typeof _npc, count units _npc]};
+
+
+ // exit if something went wrong during initialization (or if unit is on roof)
+ if (_exit) exitWith {
+ if (KRON_UPS_DEBUG>0) then {hint "Initialization aborted"};
+ };
+
+
+
+// remember the original group members, so we can later find a new leader, in case he dies
+ _members = units _npc;
+ KRON_UPS_Total = KRON_UPS_Total + (count _members);
+
+//Fills member soldier types
+ _vehicles = [];
+ {
+ if (vehicle _x != _x ) then {
+ _vehicles = _vehicles - [vehicle _x];
+ _vehicles = _vehicles + [vehicle _x];
+ };
+ _membertypes = _membertypes + [typeof _x];
+ } foreach _members;
+
+//Fills member vehicle types
+ {
+ _vehicletypes = _vehicletypes + [typeof _x];
+ } foreach _vehicles;
+
+// what type of "vehicle" is _npc ?
+ _isman = "Man" countType [ vehicle _npc]>0;
+ _iscar = "LandVehicle" countType [vehicle _npc]>0;
+ _isboat = "Ship" countType [vehicle _npc]>0;
+ _isplane = "Air" countType [vehicle _npc]>0;
+
+// we just have to brute-force it for now, and declare *everyone* an enemy who isn't a civilian
+ _isSoldier = _side != civilian;
+
+ _friends=[];
+ _enemies=[];
+ _sharedenemy=0;
+
+ if (_isSoldier) then {
+ switch (_side) do {
+ case west:
+ { _sharedenemy=0;
+ _friendside = [west];
+ _enemyside = [east];
+ };
+ case east:
+ { _sharedenemy=1;
+ _friendside = [east];
+ _enemyside = [west];
+ };
+ case resistance:
+ {
+ _sharedenemy=2;
+ _enemyside = KRON_UPS_Res_enemy;
+
+ if (!(east in _enemyside)) then {
+ _friendside = [east];
+ };
+ if (!(west in _enemyside)) then {
+ _friendside = [west];
+ };
+ };
+ };
+ };
+
+ if (_side in KRON_UPS_Res_enemy) then {
+ _enemyside = _enemyside + [resistance];
+ }else {
+ _friendside = _friendside + [resistance];
+ };
+ sleep .05;
+
+//Sets min units alive for surrender
+ _surrender = call (compile format ["KRON_UPS_%1_SURRENDER",_side]);
+
+
+
+ // Tanks friendlys are contabiliced
+{
+ if ( side _x in _friendside && ( _x iskindof "Tank" || _x iskindof "Wheeled_APC" )) then {
+ _friendlytanks = _friendlytanks + [_x];
+ };
+}foreach vehicles;
+
+// global unit variable to externally influence script
+//call compile format ["KRON_UPS_%1=1",_npcname];
+
+// X/Y range of target area
+_areasize = getMarkerSize _areamarker;
+_rangeX = _areasize select 0;
+_rangeY = _areasize select 1;
+_area = abs((_rangeX * _rangeY) ^ 0.5);
+// marker orientation (needed as negative value!)
+_areadir = (markerDir _areamarker) * -1;
+
+
+// store some trig calculations
+_cosdir=cos(_areadir);
+_sindir=sin(_areadir);
+
+// minimum distance of new target position
+_mindist=(_rangeX^2+_rangeY^2)/3;
+if (_rangeX==0) exitWith {
+ hint format["UPS: Cannot patrol Sector: %1\nArea Marker doesn't exist",_areamarker];
+};
+
+// remember the original mode & speed
+_orgMode = behaviour _npc;
+_orgSpeed = speedmode _npc;
+
+// set first target to current position (so we'll generate a new one right away)
+_currPos = getpos _npc;
+_orgPos = _currPos;
+_orgDir = getDir _npc;
+_orgWatch=[_currPos,50,_orgDir] call KRON_relPos;
+_lastpos = _currPos;
+
+_avoidPos = [0,0];
+_flankPos = [0,0];
+_attackPos = [0,0];
+_newattackPos = [0,0];
+_fixedtargetpos = [0,0];
+_frontPos = [0,0];
+_dirf1 = 0;_dirf2=0;_flankPos2=[0,0];
+_dist = 10000;
+_lastdist = 0;
+_lastmove1 = 0;
+_lastmove2 = 0;
+_maxmove=0;
+_moved=0;
+
+_damm=0;
+_dammchg=0;
+_lastdamm = 0;
+_timeontarget = 0;
+
+_fightmode = "walk";
+_fm=0;
+_gothit = false;
+_pursue = false;
+_hitPos=[0,0,0];
+_react = 0;
+_lastknown = 0;
+_opfknowval = 0;
+
+_sin0=1;
+_sin90=1; _cos90=0;
+_sin270=-1; _cos270=0;
+_targetX =0; _targetY=0;
+_relTX=0;_relTY=0;
+_relUX=0;_relUY=0;
+_supressed = false;
+_flankdist=0;
+_nBuilding=nil;
+_nBuildingt =nil;
+_speedmode="Limited";
+_distnbuid = 0;
+_distnbuidt = 0;
+_objsflankPos1 = [];
+_cntobjs1 = 0;
+_objsflankPos2 = [];
+_cntobjs2 = 0;
+_targettext ="";
+_dir1 =0;_dir2=0;_dir3=0;_dd=0;
+_timeontarget=0;
+_reinforcement ="";
+_reinforcementsent = false;
+_target = objnull;
+_newtarget=objnull;
+_flankdir=0; //1 tendencia a flankpos1, 2 tendencia a flankpos2
+_prov=0;
+_targets=[];
+_planta=0; //Indice de plantas en edificios
+_newflankAngle = 0;
+_closeenough = KRON_UPS_closeenough;
+_gunner = objnull;
+_driver = objnull;
+_fortify = false;
+_buildingdist= 60;//Distance to search buildings near
+_Behaviour = "SAFE";
+_grp = grpnull;
+_grp = group _npc;
+_template = 0;
+_nowpType = 1;
+_ambushtype = 1;
+_rstuckControl = 0;
+_makenewtarget=true;
+
+
+
+// set target tolerance high for choppers & planes
+if (_isplane) then {_closeenough = KRON_UPS_closeenough * 2};
+
+// ***************************************** optional arguments *****************************************
+
+// wait at patrol end points
+_pause = if ("NOWAIT" in _UCthis) then {"NOWAIT"} else {"WAIT"};
+// don't move until an enemy is spotted
+_nomove = if ("NOMOVE" in _UCthis) then {"NOMOVE"} else {"MOVE"};
+
+//fortify group in near places
+ _fortify= if ("FORTIFY" in _UCthis) then {true} else {false};
+ _fortifyorig = _fortify;
+ if (_fortify) then {
+ _nomove="NOMOVE";
+ _minreact = KRON_UPS_minreact * 3;
+ _buildingdist = _buildingdist * 2;
+ _makenewtarget = false;
+ _wait = 3000;
+ };
+
+// create _targerpoint on the roads only (by this group)
+ _onroad = if ("ONROAD" in _UCthis) then {true} else {false};
+// do not use smoke (by this group)
+ _nosmoke = if ("NOSMOKE" in _UCthis) then {true} else {false};
+// do not search for vehicles (unless in fight and combat vehicles)
+_noveh = if ("NOVEH" in _UCthis) then {true} else {false};
+
+
+
+// don't make waypoints
+ _nowp = if ("NOWP" in _UCthis) then {true} else {false};
+ _nowp = if ("NOWP2" in _UCthis) then {true} else {_nowp};
+ _nowp = if ("NOWP3" in _UCthis) then {true} else {_nowp};
+ _nowpType = if ("NOWP2" in _UCthis) then {2} else {_nowpType};
+ _nowpType = if ("NOWP3" in _UCthis) then {3} else {_nowpType};
+
+//Ambush squad will no move until in combat or so close enemy
+ _ambush= if ("AMBUSH" in _UCthis) then {true} else {false};
+ _ambush= if ("AMBUSH:" in _UCthis) then {true} else {_ambush};
+ _ambush= if ("AMBUSH2" in _UCthis) then {true} else {_ambush};
+ _ambushwait = ["AMBUSH:",_ambushwait,_UCthis] call KRON_UPSgetArg;
+ _ambushwait = ["AMBUSH2:",_ambushwait,_UCthis] call KRON_UPSgetArg;
+ _ambushType = if ("AMBUSH2" in _UCthis) then {2} else {_ambushType};
+ _ambushType = if ("AMBUSH2:" in _UCthis) then {2} else {_ambushType};
+
+// respawn
+ _respawn = if ("RESPAWN" in _UCthis) then {true} else {false};
+ _respawn = if ("RESPAWN:" in _UCthis) then {true} else {_respawn};
+ _respawnmax = ["RESPAWN:",_respawnmax,_UCthis] call KRON_UPSgetArg;
+ if (!_respawn) then {_respawnmax = 0};
+
+// any init strings?
+ _initstr = ["INIT:","",_UCthis] call KRON_UPSgetArg;
+
+// don't follow outside of marker area
+ _nofollow = if ("NOFOLLOW" in _UCthis) then {"NOFOLLOW"} else {"FOLLOW"};
+// share enemy info
+ _shareinfo = if ("NOSHARE" in _UCthis) then {"NOSHARE"} else {"SHARE"};
+// "area cleared" trigger activator
+ _areatrigger = if ("TRIGGER" in _UCthis) then {"TRIGGER"} else {if ("NOTRIGGER" in _UCthis) then {"NOTRIGGER"} else {"SILENTTRIGGER"}};
+
+ // suppress fight behaviour
+ if ("NOAI" in _UCthis) then {_isSoldier=false};
+
+ // adjust cycle delay
+ _cycle = ["CYCLE:",KRON_UPS_Cycle,_UCthis] call KRON_UPSgetArg;
+ _currcycle=_cycle;
+
+ //spawned for squads created in runtime
+ _spawned= if ("SPAWNED" in _UCthis) then {true} else {false};
+ if (_spawned) then {
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: squad has been spawned, respawns %2",_grpidx,_respawnmax]};
+ switch (side _npc) do {
+ case west:
+ { KRON_AllWest=KRON_AllWest + units _npc;
+ };
+ case east:
+ { KRON_AllEast=KRON_AllEast + units _npc; };
+ case resistance:
+ {
+ KRON_AllRes=KRON_AllRes + units _npc;
+ if (east in KRON_UPS_Res_enemy ) then {
+ KRON_UPS_East_enemies = KRON_UPS_East_enemies+units _npc;
+ } else {
+ KRON_UPS_East_friends = KRON_UPS_East_friends+units _npc;
+ };
+ if (west in KRON_UPS_Res_enemy ) then {
+ KRON_UPS_West_enemies = KRON_UPS_West_enemies+units _npc;
+ } else {
+ KRON_UPS_West_friends = KRON_UPS_West_friends+units _npc;
+ };
+ };
+ };
+ call (compile format ["KRON_UPS_%1_Total = KRON_UPS_%1_Total + count (units _npc)",side _npc]);
+
+ _vehicletypes = ["VEHTYPE:",_vehicletypes,_UCthis] call KRON_UPSgetArg;
+
+ };
+
+// set drop units at random positions
+ _initpos = "ORIGINAL";
+ if ("RANDOM" in _UCthis) then {_initpos = "RANDOM"};
+ if ("RANDOMUP" in _UCthis) then {_initpos = "RANDOMUP"};
+ if ("RANDOMDN" in _UCthis) then {_initpos = "RANDOMDN"};
+ // don't position groups or vehicles on rooftops
+ if ((_initpos!="ORIGINAL") && ((!_isman) || (count _members)>1)) then {_initpos="RANDOMDN"};
+
+ // set behaviour modes (or not)
+ _orgMode = "SAFE";
+ if ("CARELESS" in _UCthis) then {_orgMode = "CARELESS"};
+ if ("AWARE" in _UCthis) then {_orgMode = "AWARE"};
+ if ("COMBAT" in _UCthis) then {_orgMode = "COMBAT"};
+ if ("STEALTH" in _UCthis) then {_orgMode = "STEALTH"};
+
+// set original beahviour
+ if (!_isSoldier) then {
+ _Behaviour = "CARELESS";
+ } else {
+ _Behaviour = _orgMode;
+ };
+ _npc setbehaviour _Behaviour;
+
+
+// set initial speed
+ _noslow = if ("NOSLOW" in _UCthis) then {"NOSLOW"} else {"SLOW"};
+ if (_noslow!="NOSLOW") then {
+ _orgSpeed = "limited";
+ } else {
+ _orgSpeed = "FULL";
+ };
+ _speedmode = _orgSpeed;
+ _npc setspeedmode _speedmode;
+
+// set If enemy detected reinforcements will be sent REIN1
+ _reinforcement= if ("REINFORCEMENT" in _UCthis) then {"REINFORCEMENT"} else {"NOREINFORCEMENT"}; //rein_yes
+ _rfid = ["REINFORCEMENT:",0,_UCthis] call KRON_UPSgetArg; // rein_#
+
+ if (_rfid>0) then {
+ _reinforcement="REINFORCEMENT";
+ //if (KRON_UPS_Debug>0) then {hintsilent format["%1: reinforcement group %2",_grpidx,_rfid,_rfidcalled,_reinforcement]};
+ };
+
+//set Is a template for spawn module?
+ _template = ["TEMPLATE:",_template,_UCthis] call KRON_UPSgetArg;
+ //Fills template array for spawn
+ if (_template > 0 && !_spawned) then {
+ KRON_UPS_TEMPLATES = KRON_UPS_TEMPLATES + ( [[_template]+[_side]+[_membertypes]+[_vehicletypes]] );
+ //if (KRON_UPS_Debug>0) then {diag_log format["%1 Adding TEMPLATE %2 _spawned %3",_grpidx,_template,_spawned]};
+ //if (KRON_UPS_Debug>0) then {player globalchat format["KRON_UPS_TEMPLATES %1",count KRON_UPS_TEMPLATES]};
+ };
+
+// make start position random
+ if (_initpos!="ORIGINAL") then {
+ // find a random position (try a max of 20 positions)
+ _try=0;
+ _bld=0;
+ _bldpos=0;
+ while {_try<20} do {
+ _currPos=[_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+ _posinfo=[_currPos] call KRON_PosInfo3;
+ // _posinfo: [0,0]=no house near, [obj,-1]=house near, but no roof positions, [obj,pos]=house near, with roof pos
+ _bld=_posinfo select 0;
+ _bldpos=_posinfo select 1;
+ if (_isplane || _isboat || !(surfaceiswater _currPos)) then {
+ if (((_initpos=="RANDOM") || (_initpos=="RANDOMUP")) && (_bldpos>0)) then {_try=99};
+ if (((_initpos=="RANDOM") || (_initpos=="RANDOMDN")) && (_bldpos==0)) then {_try=99};
+ };
+ _try=_try+1;
+ sleep .01;
+ };
+ if (_bldpos==0) then {
+
+ { //man
+ if (vehicle _x == _x) then {
+ _x setpos _currPos;
+ };
+ } foreach units _npc;
+
+ sleep .5;
+ { // vehicles
+ _targetpos = _currPos findEmptyPosition [10, 100];
+ sleep .4;
+ if (count _targetpos <= 0) then {_targetpos = _currpos};
+ _x setPos _targetpos;
+ } foreach _vehicles;
+
+ } else {
+ // put the unit on top of a building
+ _npc setPos (_bld buildingPos _bldpos);
+ _currPos = getPos _npc;
+ _nowp=true; // don't move if on roof
+ };
+ };
+
+// track unit ======================================================================================
+ _track = if (("TRACK" in _UCthis) || (KRON_UPS_Debug>0)) then {"TRACK"} else {"NOTRACK"};
+ _trackername = "";
+ _destname = "";
+ if (_track=="TRACK") then {
+ _track = "TRACK";
+ _trackername=format["trk_%1",_grpidx];
+ _markerobj = createMarker[_trackername,[0,0]];
+ _markerobj setMarkerShape "ICON";
+ _markertype = if (isClass(configFile >> "cfgMarkers" >> "WTF_Dot")) then {"WTF_DOT"} else {"DOT"};
+ _trackername setMarkerType _markertype;
+ _markercolor = switch (side _npc) do {
+ case west: {"ColorGreen"};
+ case east: {"ColorRed"};
+ case resistance: {"ColorBlue"};
+ default {"ColorBlack"};
+ };
+ _trackername setMarkerColor _markercolor;
+ _trackername setMarkerText format["%1",_grpidx];
+ _trackername setmarkerpos _currPos;
+
+ _destname=format["dest_%1",_grpidx];
+ _markerobj = createMarker[_destname,[0,0]];
+ _markerobj setMarkerShape "ICON";
+ _markertype = if (isClass(configFile >> "cfgMarkers" >> "WTF_Flag")) then {"WTF_FLAG"} else {"FLAG"};
+ _destname setMarkerType _markertype;
+ _destname setMarkerColor _markercolor;
+ _destname setMarkerText format["%1",_grpidx];
+ _destname setMarkerSize [.5,.5];
+ };
+
+
+// delete dead units ==============================================================================
+ _deletedead = ["DELETE:",0,_UCthis] call KRON_UPSgetArg;
+ if (_deletedead>0) then {
+ {
+ _x addEventHandler['killed',format["[_this select 0,%1] spawn KRON_deleteDead",_deletedead]];
+ sleep 0.01;
+ }forEach _members;
+ };
+
+// how many group clones? =========================================================================
+// TBD: add to global side arrays?
+ _mincopies = ["MIN:",0,_UCthis] call KRON_UPSgetArg;
+ _maxcopies = ["MAX:",0,_UCthis] call KRON_UPSgetArg;
+ if (_mincopies>_maxcopies) then {_maxcopies = _mincopies};
+ if (_maxcopies>140) exitWith {hint "Cannot create more than 140 groups!"};
+ if (_maxcopies>0) then {
+ _copies = _mincopies + random (_maxcopies-_mincopies);
+
+ // create the clones
+ for "_grpcnt" from 1 to _copies do {
+ // copy groups
+ if (isNil ("KRON_grpindex")) then {KRON_grpindex = 0};
+ KRON_grpindex = KRON_grpindex+1;
+ // copy group leader
+ _unittype = typeof _npc;
+ // make the clones civilians
+ // use random Civilian models for single unit groups
+ if ((_unittype=="Civilian") && (count _members==1)) then {_rnd=1+round(random 20); if (_rnd>1) then {_unittype=format["Civilian%1",_rnd]}};
+
+ _grp=createGroup side _npc;
+ _lead = _grp createUnit [_unittype, getpos _npc, [], 0, "form"];
+ _lead setVehicleVarName format["l%1",KRON_grpindex];
+ call compile format["l%1=_lead",KRON_grpindex];
+ _lead setBehaviour _orgMode;
+ _lead setSpeedmode _orgSpeed;
+ _lead setSkill skill _npc;
+ _lead setVehicleInit _initstr;
+ [_lead] join _grp;
+ _grp selectLeader _lead;
+ // copy team members (skip the leader)
+ _i=0;
+ {
+ _i=_i+1;
+ if (_i>1) then {
+ _newunit = _grp createUnit [typeof _x, getpos _x, [],0,"form"];
+ _newunit setBehaviour _orgMode;
+ _newunit setSpeedMode _orgSpeed;
+ _newunit setSkill skill _x;
+ _newunit setVehicleInit _initstr;
+ [_newunit] join _grp;
+ };
+ } foreach _members;
+
+ nul=[_lead,_areamarker,_pause,_noslow,_nomove,_nofollow,_initpos,_track,_showmarker,_shareinfo,"DELETE:",_dead] execVM "scripts\upsmon.sqf";
+ //sleep .05;
+ };
+ processInitCommands;
+ sleep .05;
+ };
+
+
+// units that can be left for area to be "cleared" =============================================================================================
+ _zoneempty = ["EMPTY:",0,_UCthis] call KRON_UPSgetArg;
+
+// create area trigger =========================================================================================================================
+ if (_areatrigger!="NOTRIGGER") then {
+ _trgside = switch (side _npc) do { case west: {"WEST"}; case east: {"EAST"}; case resistance: {"GUER"}; case civilian: {"CIV"};};
+ //_trgside = switch (side _npc) do { case west: {"EAST"}; case east: {"WEST"}; case resistance: {"ANY"}; case civilian: {"ANY"};};
+ _trgname="KRON_Trig_"+_trgside+"_"+_areamarker;
+ _flgname="KRON_Cleared_"+_areamarker;
+ // has the trigger been created already?
+ KRON_TRGFlag=-1;
+ call compile format["%1=false",_flgname];
+ call compile format["KRON_TRGFlag=%1",_trgname];
+ if (isNil ("KRON_TRGFlag")) then {
+ // trigger doesn't exist yet, so create one (make it a bit bigger than the marker, to catch path finding 'excursions' and flanking moves)
+ call compile format["%1=createTrigger['EmptyDetector',_centerpos]",_trgname];
+ call compile format["%1 setTriggerArea[_rangeX*1.5,_rangeY*1.5,markerDir _areamarker,true]",_trgname];
+ call compile format["%1 setTriggerActivation[_trgside,'PRESENT',true]",_trgname];
+ call compile format["%1 setEffectCondition 'true'",_trgname];
+ call compile format["%1 setTriggerTimeout [5,7,10,true]",_trgname];
+ if (_areatrigger!="SILENTTRIGGER") then {
+ call compile format["%1 setTriggerStatements['count thislist<=%6', 'titletext [''SECTOR <%2> LIMPIO'',''PLAIN''];''%2'' setmarkerpos [-%4,-%5];%3=true;', 'titletext [''SECTOR <%2> HA SIDO REOCUPADO'',''PLAIN''];''%2'' setmarkerpos [%4,%5];%3=false;']", _trgname,_areamarker,_flgname,_centerX,_centerY,_zoneempty];
+
+ } else {
+ call compile format["%1 setTriggerStatements['count thislist<=%3', '%2=true;', '%2=false;']", _trgname,_flgname,_zoneempty];
+ };
+ };
+ sleep .05;
+ };
+
+//If a soldier has a useful building takes about ======================================================================================================================
+ if ( _nomove=="NOMOVE" ) then {
+ sleep 10;
+ _unitsIn = [_grpid,_npc,150] call MON_GetIn_NearestStatic;
+ if ( count _unitsIn > 0 ) then { sleep 10};
+ [_npc, _buildingdist,false,_wait,true] spawn MON_moveNearestBuildings;
+ };
+
+// init done
+ _newpos = false;
+ _targetPos = [0,0,0];//_currPos;
+ _targettext ="_currPos";
+ _swimming = false;
+ _waiting = if (_nomove=="NOMOVE") then {9999} else {0};
+ _sharedist = if (_nomove=="NOMOVE") then {KRON_UPS_sharedist} else {KRON_UPS_sharedist*1.5};
+
+
+//Gets position of waypoint if no targetpos
+ if (format ["%1", _targetPos] == "[0,0,0]") then {
+ _index = (count waypoints _grp) - 1;
+ _wp = [_grp,_index];
+ _targetPos = waypointPosition _wp;
+ if (([_currpos,_targetPos] call KRON_distancePosSqr)<= 20) then {_targetPos = [0,0,0];};
+ };
+
+// ***********************************************************************************************************
+// ************************************************ MAIN LOOP ************************************************
+// ***********************************************************************************************************
+_loop=true;
+
+scopeName "main";
+while {_loop} do {
+
+
+//if (KRON_UPS_Debug>0) then {player sidechat format["%1: _cycle=%2 _currcycle=%3 _react=%4 _waiting=%5",_grpidx,_cycle,_currcycle,_react,_waiting]};
+ _timeontarget=_timeontarget+_currcycle;
+ _react=_react+_currcycle;
+ _waiting = _waiting - _currcycle;
+ _lastreact = _lastreact + _currcycle;
+ _newpos = false;
+
+
+
+ _sokilled = false;
+ _sowounded = false;
+
+
+ // CHECK IF did anybody in the group got hit or die?
+ if ((R_GOTHIT_ARRAY select _grpId) != 0) then
+ {
+ _gothit = true;
+
+ if ((R_GOTHIT_ARRAY select _grpId) == 1) then
+ {
+ _sowounded = true;
+ }
+ else
+ {
+ _sokilled = true;
+ };
+ sleep 0.01;
+ R_GOTHIT_ARRAY set [_grpId, 0];
+ };
+
+
+
+
+
+ // nobody left alive, exit routine
+ if (count _members==0) then {
+ _exit=true;
+ } else {
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+ };
+
+ //exits from loop
+ if (_exit) exitwith {};
+
+
+ //Checks if surrender is enabled
+ if ( _surrender > 0 ) then {
+ _surrended = call (compile format ["KRON_UPS_%1_SURRENDED",_side]);
+ };
+
+ //If surrended exits from script
+ if (_surrended) exitwith {
+ {
+ [_x] spawn MON_surrender;
+ }foreach _members;
+
+ if (KRON_UPS_Debug>0) then {_npc globalchat format["%1: %2 SURRENDED",_grpidx,_side]};
+ };
+
+ //Assign the current leader of the group in the array of group leaders
+ KRON_NPCs set [_grpid,_npc];
+
+ // current position
+ _currPos = getpos _npc; _currX = _currPos select 0; _currY = _currPos select 1;
+ if (_track=="TRACK" || KRON_UPS_Debug>0) then { _trackername setmarkerpos _currPos; };
+
+
+ // if the AI is a civilian we don't have to bother checking for enemy encounters
+ if ( _isSoldier && !_exit) then {
+ _pursue=false;
+ //_Behaviour = Behaviour _npc;
+
+ //Variables to see if the leader is in a vehicle
+ _incar = "LandVehicle" countType [vehicle (_npc)]>0;
+ _inheli = "Air" countType [vehicle (_npc)]>0;
+ _inboat = "Ship" countType [vehicle (_npc)]>0;
+
+
+ //If the group is strengthened and the enemies have been detected are sent to target
+ if (_rfid > 0 ) then {
+ _rfidcalled = call (compile format ["KRON_UPS_reinforcement%1",_rfid]); // will be TRUE when variable in triger will be true.
+ if (isnil "_rfidcalled") then {_rfidcalled=false};
+ _fixedtargetPos = call (compile format ["KRON_UPS_reinforcement%1_pos",_rfid]); // will be position os setfix target of sending reinforcement
+ if (isnil "_fixedtargetPos") then {
+ _fixedtargetPos=[0,0];
+ }else{
+ _fixedtargetPos = [abs(_fixedtargetPos select 0),abs(_fixedtargetPos select 1)];
+ _target = objnull;
+ };
+ };
+ sleep .01;
+
+ //Reinforcement control
+ if (_reinforcement=="REINFORCEMENT") then {
+ // (global call OR id call) AND !send yet
+ if ( (KRON_UPS_reinforcement || _rfidcalled) && (!_reinforcementsent)) then {
+ _reinforcementsent=true;
+ _fortify = false;
+ _minreact = KRON_UPS_minreact;
+ _buildingdist = 60;
+ _react = _react + 100;
+ _waiting = -1;
+ if (format ["%1",_fixedtargetPos] != "[0,0]") then {_nowp = false};
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 called for reinforcement %2",_grpidx,_fixedtargetPos]};
+ } else {
+ // !(global or id call) AND send
+ if ( !(KRON_UPS_reinforcement || _rfidcalled) && (_reinforcementsent)) then {
+ _fixedtargetPos = [0,0];
+ _attackPos = [0,0];
+ _fortify = _fortifyorig;
+ _reinforcementsent=false;
+ if (_rfid > 0 ) then {
+ call (compile format ["KRON_UPS_reinforcement%1_pos = [0,0]",_rfid]);
+ call (compile format ["KRON_UPS_reinforcement%1 = false",_rfid]);
+ };
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 reinforcement canceled",_grpidx]};
+ };
+ };
+ };
+
+ //Gets targets from radio
+ _targets = call (compile format ["KRON_targets%1",_sharedenemy]);
+
+ // if (KRON_UPS_Debug>0) then {player globalchat format["targets from global upsmon: %1",_targets]};
+ //Reveal targets found by members to leader
+ {
+ //_NearestEnemy = assignedTarget _x;
+ //if (KRON_UPS_Debug>0) then {player globalchat format["Nearest Enemy %1, know about %2",_NearestEnemy,_x knowsabout _NearestEnemy]};
+ _NearestEnemy = _x findnearestenemy _x;
+ if (_x knowsabout _NearestEnemy > R_knowsAboutEnemy && (_npc knowsabout _NearestEnemy <= R_knowsAboutEnemy || count _targets <= 0 )) then {
+
+ if (_npc knowsabout _NearestEnemy <= R_knowsAboutEnemy ) then {
+ _npc reveal _NearestEnemy;
+ if (KRON_UPS_Debug>0) then {player globalchat format["%1: %2 reveals target %3 to leader",_grpidx,typeof _x, typeof _NearestEnemy]};
+ };
+
+ //If no targets adds this
+ if (count _targets <= 0) then {
+ //_target = _NearestEnemy;
+ _targets = _targets + [_NearestEnemy];
+ _NearestEnemy setvariable ["UPSMON_lastknownpos", position _NearestEnemy, false];
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%1: %3 added to targets",_grpidx,typeof _x, typeof _target]};
+ };
+ };
+ } foreach units _npc;
+
+
+ //if no target but _npc knows enemy then this is _target
+ if (isNull (_target)) then {
+ {
+ if ((_npc knowsabout _x > R_knowsAboutEnemy) && (alive _x) && (canmove _x)) then {
+ _target =_x;
+ if (!isNull (_target)) exitWith{};
+ };
+ } foreach _targets;
+ };
+
+
+
+
+ //Resets distance to target
+ _dist = 10000;
+
+ //Gets current known position of target and distance
+ if ( !isNull (_target) && alive _target ) then {
+ _newattackPos = _target getvariable ("UPSMON_lastknownpos");
+
+ if ( !isnil "_newattackPos" ) then {
+ _attackPos=_newattackPos;
+ //Gets distance to target known pos
+ _dist = ([_currpos,_attackPos] call KRON_distancePosSqr);
+ };
+ };
+
+
+ //Initialization for geting new targets
+ //If the current target is dead or no prior knowledge is cleaned
+ if (isNull (_target) || !alive _target || !canmove _target ) then {
+ _lastknown = 0;
+ _opfknowval = 0;
+ _target = objnull;
+ };
+
+ _newtarget = _target;
+
+
+ if ((_shareinfo=="SHARE")) then {
+
+ //Requests for radio the enemy's position, if it is within the range of acts
+ if ((KRON_UPS_comradio == 2)) then
+ {
+ _targetsnear = false;
+
+ //I we have a close target alive do not search another
+ if (!alive _target || !canmove _target || _dist > _closeenough) then {
+ {
+ if ( !isnull _x && canmove _x && alive _x ) then {
+
+ _newattackPos = _x getvariable ("UPSMON_lastknownpos");
+
+ if ( !isnil "_newattackPos" ) then {
+ _dist3 = ([_currpos,_newattackPos] call KRON_distancePosSqr);
+
+ //Sets if near targets to begin warning
+ IF ( _dist3 <= (_closeenough + KRON_UPS_safedist)) then { _targetsnear = true };
+
+ //Sets new target
+ if ( ( isnull (_newtarget) || captive _newtarget|| !alive _newtarget|| !canmove _newtarget || _dist3 < _dist )
+ && ( _dist3 <= _sharedist || _reinforcementsent )
+ && ( !(_x iskindof "Air") || (_x iskindof "Air" && _isplane ))
+ && ( !(_x iskindof "Ship") || (_x iskindof "Ship" && _isboat ))
+ && ( _x emptyPositions "Gunner" == 0 && _x emptyPositions "Driver" == 0
+ || (!isnull (gunner _x) && canmove (gunner _x))
+ || (!isnull (driver _x) && canmove (driver _x)))
+ ) then {
+ _newtarget = _x;
+ _opfknowval = _npc knowsabout _x;
+ _dist = _dist3;
+ if (_dist < _closeenough) exitWith {};
+ };
+ };
+ };
+ } foreach _targets;
+ sleep 0.5;
+ };
+ };
+
+ //If you change the target changed direction flanking initialize
+ if ( !isNull (_newtarget) && alive _newtarget && canmove _newtarget && (_newtarget != _target || isNull (_target)) ) then {
+ _timeontarget = 0;
+ _targetdead = false;
+ _flankdir= if (random 100 <= 10) then {0} else {_flankdir};
+ _target = _newtarget;
+ };
+ };
+
+ // use smoke when hit or s/o killed
+ if !_nosmoke then {
+ {
+ //when hit
+ if (_sowounded && random 100 < R_USE_SMOKE_wounded) then {
+ nul = [_x,_target] spawn MON_throw_grenade;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1: We got wounded smoking!",_grpidx]};
+ };
+
+ //when die
+ if (_sokilled && random 100 < R_USE_SMOKE_killed) then {
+ nul = [_x,_target] spawn MON_throw_grenade;
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: We got killed one, smoking!",_grpidx]};
+ };
+ sleep 0.1;
+ } foreach _members;
+ };
+
+
+
+ //Gets current known position of target and distance
+ if ( !isNull (_target) && alive _target ) then {
+ //Enemy detected
+ if (_fightmode != "fight" ) then {
+ _fightmode = "fight";
+ _npc setCombatMode "RED"; // !R
+ _react = KRON_UPS_react;
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Enemy detected %2",_grpidx, typeof _target]};
+
+ if (_nowpType == 1) then {
+ nul = [_npc] call R_FN_deleteObsoleteWaypoints;
+ _nowp = false;
+ };
+ };
+
+ _newattackPos = _target getvariable ("UPSMON_lastknownpos");
+
+ if ( !isnil "_newattackPos" ) then {
+ _attackPos=_newattackPos;
+ //Gets distance to target known pos
+ _dist = ([_currpos,_attackPos] call KRON_distancePosSqr);
+ //Looks at target known pos
+ _members lookat _attackPos;
+ };
+ };
+
+ //If the enemy has moved away from the radio coverage is not a reinforcement sent we will have lost track
+ if ( _fightmode != "walk" && !isnull(_target) && _dist < 15 && _npc knowsabout _target < R_knowsAboutEnemy ) then {
+ //If squad is near last position and no target clear position of target
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Target lost",_grpidx]};
+ _fightmode="walk";
+ _speedmode = _orgSpeed;
+ _target = objnull;
+ _Behaviour = _orgMode;
+ _waiting = -1;
+ _unitpos = "AUTO";
+ _pursue=false;
+ _targetdead = true;
+ _makenewtarget = true; //Go back to the original position
+ };
+
+ //If knowledge of the target increases accelerate the reaction
+ if (_opfknowval>_lastknown ) then {
+ _react = _react + 20;
+ };
+
+ // if spotted an enemy or got shot, so start pursuit, if in combat and exceed time to react or movecompleted
+ if (!_ambushed && (_fightmode != "walk") && ((_react >= KRON_UPS_react && _lastreact >=_minreact) || moveToCompleted _npc )) then {
+ _pursue=true;
+ };
+
+
+ //Ambush ==========================================================================================================
+ if (_ambush && !_ambushed) then {
+ _ambushed = true;
+ _nowp = true;
+ _currcycle = 2;
+ _grp setFormation "LINE";
+ _npc setBehaviour "STEALTH";
+ _npc setSpeedMode "FULL";
+
+
+ /*
+ sleep 12;
+ {
+ [_x,"DOWN"] spawn MON_setUnitPos;
+ sleep 2;
+ _x stop true;
+ player sidechat format["%1 %2",_x,_npc];
+
+ } foreach units _npc;
+ */
+
+ //Puts a mine if near road
+ if ( _ambushType == 1 ) then {
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Puting mine for ambush",_grpidx]};
+ _npc setBehaviour "careless";
+ _dir1 = getDir _npc;
+ _mineposition = [position _npc,_dir1, (KRON_UPS_ambushdist / 1.2)] call MON_GetPos2D;
+ _roads = _mineposition nearroads 25;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1: Roads #:%2",_grpidx, (count _roads)]};
+
+ while {_Mines > 0} do
+ {
+ _i = 0;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 Current Roads #:%2 _Mines:%3",_grpidx, (count _roads),_Mines]};
+ if (count _roads > 0) then {
+ _rnd = floor (random (count _roads));
+ _mineposition = position (_roads select _rnd);
+ _roads = _roads - [_roads select _rnd];
+ if ([_npc,_mineposition] call MON_CreateMine) then {_Mines = _Mines -1; _i = 1;};
+ } else {
+ _mineposition = [position _npc,(_dir1-30) mod 360, (KRON_UPS_ambushdist / 1.2 ) + random 10] call MON_GetPos2D;
+ if ([_npc,_mineposition] call MON_CreateMine) then {_Mines = _Mines -1; _i = 1;};
+ };
+ sleep 0.1;
+ if (_i != 1) then {_Mines = _Mines -1;} //in case no mine was set
+ };
+
+ _npc setBehaviour "carelesscareless";
+ sleep 30;
+ {
+ if (!stopped _x) then {
+ _x domove position _npc;
+ waituntil {moveToCompleted _x || moveToFailed _x || !alive _x || !canmove _x || _x distance _npc <= 5};
+ };
+ } foreach units _npc;
+ };
+
+
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+
+ _grp setFormation "LINE";
+ _npc setBehaviour "AWARE";
+ sleep 10;
+
+ sleep 0.1;
+ _unitpos ="DOWN";
+ {
+ [_x,_unitpos] spawn MON_setUnitPos;
+ sleep 0.5;
+ _x stop true;
+ } foreach units _npc;
+ _npc setBehaviour "STEALTH";
+ _pursue = false;
+
+ }; // end of ambush mine
+
+
+
+
+
+ //Ambushr enemy is nearly aproach
+ //_ambushdist = 50;
+ // if (_npc knowsabout _NearestEnemy <= R_knowsAboutEnemy )
+
+ if (_ambush) then {
+ _prov = ((_ambushdist*2 - (_npc distance _NearestEnemy))*3) - 40;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1:%6 _ambushdist=%5 last=%2 dist=%3 prov=%4",_grpidx,_lastdist,_npc distance _NearestEnemy,_prov,_ambushdist,typeof _NearestEnemy]};
+
+ if (_gothit || _reinforcementsent || time > _ambushwait
+ || ( "Air" countType [_NearestEnemy]<=0
+ && ( _npc distance _NearestEnemy <= _ambushdist + random 10
+ || (!isNull (_NearestEnemy) && (( random 100 <= _prov && _npc distance _NearestEnemy > _lastdist)
+ || _npc distance _NearestEnemy > _ambushdist*3 && _lastdist < _ambushdist*3 && _lastdist > 0))
+ ))
+ ) then {
+ sleep ((random 1) + 1); // let the enemy then get in the area
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: ATTACK !",_grpidx]};
+ _nowp = false;
+ _ambush = false;
+ _ambushed = false;
+ _currcycle = _cycle;
+ {
+ _x stop false;
+ _x setUnitPos "Auto";
+ } foreach _members;
+ _npc setBehaviour "STEALTH";
+ _npc setCombatMode "RED";
+
+ //No engage yet
+ _pursue = false;
+ };
+
+ //Sets distance to target
+ _lastdist = _npc distance _NearestEnemy;
+ }; // end of ambush
+
+
+
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: _nowp=%2 in vehicle=%3 _inheli=%4 _npc=%5",_grpidx,_nowp,vehicle (_npc) ,_inheli,typeof _npc ]};
+
+ //If in vehicle take driver if not controlled by user
+ if (alive _npc && !_nowp) then {
+ if (!_isman || (vehicle (_npc) != _npc && !_inboat && !(vehicle (_npc) iskindof "StaticWeapon"))) then {
+
+ //If new target is close enough getout vehicle (not heli)
+ _unitsin = [];
+
+ if (!_inheli) then {
+ if (_fightmode == "walk") then {
+ _GetOutDist = _area / 20;
+ }else{
+ _GetOutDist = _closeenough * ((random .4) + 0.6);
+ };
+
+
+
+
+ //If near target or stuck getout of vehicle and lock or gothit exits inmediately
+ if (_gothit || _dist <= _closeenough * 1.5 || (_lastcurrpos select 0 == _currpos select 0 && _lastcurrpos select 1 == _currpos select 1 && moveToFailed (vehicle (_npc))) || moveTocompleted (vehicle (_npc))) then
+ {
+ _GetOutDist = 10000;
+ };
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: vehicle=%2 _npc=%3",_grpidx,vehicle (_npc) ,typeof _npc ]};
+
+ _unitsin = [_npc] call R_FN_allUnitsInCargo; // return units in cargo in all vehs used by the group
+
+ private ["_handle1"];
+ _handle1 = [_npc,_targetpos,_GetOutDist] spawn R_SN_GetOutDist; // getout if as close as _GetOutDist to the target
+ _timeout = time + 10;
+ waitUntil {scriptDone _handle1 || time > _timeout};
+
+ } else {
+ _GetOutDist = 0;
+ };
+
+
+
+ // if there was getout of the cargo
+ if (count _unitsin > 0) then {
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: Geting out of vehicle, dist=%2 atdist=%3 _area=%4",_grpidx,([_currpos,_targetpos] call KRON_distancePosSqr),_GetOutDist,_area]};
+ _timeout = time + 7;
+ {
+ waituntil {vehicle _x == _x || !canmove _x || !alive _x || time > _timeout || movetofailed _x };
+ } foreach _unitsin;
+
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ if (_fightmode == "fight" || _gothit) then {
+ _npc setBehaviour "COMBAT"; // AWARE
+ _groupOne = group _npc;
+ _groupOne setFormation "DIAMOND";
+ nul = [_npc,30] spawn MON_move;
+ };
+
+ sleep 0.2;
+ // select leader outside of vehicle
+ {
+ if (alive _x && canmove _x) exitwith {group _x selectLeader _x; _npc = _x};
+ } foreach _unitsin;
+
+
+
+ if (_fightmode == "fight") then {
+ _pursue = true;
+ }else
+ {
+ _pursue = false;
+ _makenewtarget=true;
+ };
+ };
+ };
+ };
+
+
+ //If under attack or increasing knowledge speeds up the response and regain control of the AI
+ if (_gothit) then {
+ _react = if (!_supressed) then {_react + 30};
+ if (_fightmode != "walk") then {
+ if (_nowpType != 3) then {
+ nul = [_npc] call R_FN_deleteObsoleteWaypoints;
+ _nowp = false;
+ };
+ };
+ };
+
+ //If there is no objective order is canceled persecution
+ if ((isNull (_target) || !alive _target )) then {
+ _pursue=false;
+
+ if (_gothit && !_fortify && !_nowp) then {
+ if ((_fightmode == "walk")) then
+ {
+ //It could be a sniper, better be alert and move in case
+ _Behaviour = "COMBAT";
+ _speedmode = "FULL";
+ _unitpos = "AUTO";
+ _gothit = false;
+ _makenewtarget = true;
+ _waiting = -1;
+ if ((random 100 < 20) && !_nosmoke) then {
+ nul= [_npc,_target] spawn MON_throw_grenade;
+ };
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Have been damaged moving",_grpidx,_makenewtarget]};
+ } else {
+ if ((_react >= KRON_UPS_react && _lastreact >=_minreact && count _targets <= 0) || _sowounded) then {
+ //We shoot and we have no target, we move from position
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Under fire by unkown target, moving to newpos",_grpidx]};
+ //Covers the group with a smoke grenade
+ if (!_supressed && (random 100 < 80) && !_nosmoke) then {
+ nul= [_npc,_target] spawn MON_throw_grenade;
+ };
+ _gothit = false;
+ _makenewtarget = true;
+ _waiting = -1;
+ _pause="NOWAIT";
+ _speedmode = "FULL";
+ _unitpos = "middle";
+ _Behaviour = "AWARE";
+ } else {
+ if (_lastreact >=_minreact && !_targetdead) then
+ {
+ _targetdead = true;
+ _pursue = true;
+ //We have run out of targets continue to search
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Target defeated, searching",_grpidx]};
+ };
+ };
+ };
+ };
+ };
+
+
+
+
+
+
+ //If no fixed target check if current target is available
+ if (format ["%1",_fixedtargetPos] != "[0,0]") then {
+ //If fixed target check if close enough or near enemy and gothit
+ if (([_currpos,_fixedtargetpos] call KRON_distancePosSqr) <= _closeenough || (_dist <= _closeenough && _gothit)) then {
+ _fixedtargetPos = [0,0];
+ } else {
+ _pursue = false;
+ _attackPos=_fixedtargetPos;
+ if (_react >= KRON_UPS_react && _lastreact >=_minreact) then {
+ _makenewtarget = true;
+ _unitpos = "AUTO";
+ _speed = "FULL";
+ };
+ };
+ };
+
+
+
+
+
+ //If captive or surrended do not pursue
+ if ( isnil "_attackPos") then {_pursue = false;};
+ if ( captive _target || format ["%1", _attackPos] == "[0,0]") then {_pursue = false;};
+
+ //If no waypoint do not move
+ if (_nowp) then {
+ _makenewtarget = false;
+ _pursue = false;
+ };
+
+ if (_inheli) then {
+ _landing = _heli getVariable "UPSMON_landing";
+ if (isnil ("_landing")) then {_landing=false;};
+ if (_landing) then {
+ _pursue = false;
+ };
+ };
+ sleep 0.5;
+
+// **********************************************************************************************************************
+// PURSUE: CHASE BEGINS THE LENS
+// **********************************************************************************************************************
+
+ if (_pursue) then {
+
+
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1: is in pursure",_grpidx]};
+
+ _pursue = false;
+ _newpos = true;
+ _react = 0;
+ _lastreact = 0;
+ _timeontarget = 0;
+ _makenewtarget = false;
+ _fm = 1;
+ //Cancel supress effect when reaction time
+ _supressed = false;
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ // get position of spotted unit in player group, and watch that spot
+ _targetPos = _attackPos;
+ _targetX = _targetPos select 0; _targetY = _targetPos select 1;
+ _currPos = getpos _npc;
+
+ // also go into "combat mode"
+ _pause="NOWAIT";
+ _waiting=0;
+
+ // angle from unit to target
+ _dir1 = [_currPos,_targetPos] call KRON_getDirPos;
+ // angle from target to unit (reverse direction)
+ _dir2 = (_dir1+180) mod 360;
+
+ //Establecemos una distancia de flanqueo
+ _flankdist = ((random 0.5)+0.7)*KRON_UPS_safedist;
+
+ //La distancia de flanqueo no puede ser superior a la distancia del objetivo o nos pordría pillar por la espalda
+ _flankdist = if ((_flankdist*1.40) >= _dist) then {_dist*.65} else {_flankdist};
+
+ if (_inheli) then {_flankdist = _flankdist / 2;};
+
+ // avoidance position (right or left of unit)
+ _avoidPos = [_currPos,_dir2, KRON_UPS_safedist] call MON_GetPos2D;
+
+ //Calculamos posición de avance frontal
+ _frontPos = [_targetPos,_dir2, _flankdist] call MON_GetPos2D;
+
+
+ //Adaptamos el ángulo de flanqueo a la distancia
+ _newflankAngle = ((random(KRON_UPS_flankAngle)+1) * 2 * (_flankdist / KRON_UPS_safedist )) + (KRON_UPS_flankAngle/1.4) ;
+ if (_newflankAngle > KRON_UPS_flankAngle) then {_newflankAngle = KRON_UPS_flankAngle};
+
+ //Calculamos posición de flanqueo 1 45ş
+ _dirf1 = (_dir2+_newflankAngle) mod 360;
+ _flankPos = [_targetPos,_dirf1, _flankdist] call MON_GetPos2D;
+
+
+ //Calculamos posición de flanqueo 2 -45ş
+ _dirf2 = (_dir2-_newflankAngle+360) mod 360;
+ _flankPos2 = [_targetPos,_dirf2, _flankdist] call MON_GetPos2D;
+
+ if (KRON_UPS_Debug>0) then {
+ "flank1" setmarkerpos _flankPos; "flank2" setmarkerpos _flankPos2; "target" setmarkerpos _attackPos;
+ };
+
+
+ //Decidir por el mejor punto de flanqueo
+ //Contamos las posiciones de destino de otros grupos más alejadas
+ _fldest = 0;
+ _fldest2 = 0;
+ _fldestfront = 0;
+ _i = 0;
+
+ {
+ if (_i != _grpid && format ["%1", _x] != "[0,0]") then {
+ _dist1 = [_x,_flankPos] call KRON_distancePosSqr;
+ _dist2 = [_x,_flankPos2] call KRON_distancePosSqr;
+ _dist3 = [_x,_frontPos] call KRON_distancePosSqr;
+ if (_dist1 <= _flankdist/1.5 || _dist2 <= _flankdist/1.5 || _dist3 <= _flankdist/1.5) then {
+ if (_dist1 < _dist2 && _dist1 < _dist3) then {_fldest = _fldest + 1;};
+ if (_dist2 < _dist1 && _dist2 < _dist3) then {_fldest2 = _fldest2 + 1;};
+ if (_dist3 < _dist1 && _dist3 < _dist2) then {_fldestfront = _fldestfront + 1;};
+ };
+ };
+ _i = _i + 1;
+
+ sleep 0.01;
+ } foreach KRON_targetsPos;
+
+
+ //We have the positions of other groups more distant
+ _i = 0;
+ {
+ if (_i != _grpid && !isnull(_x)) then {
+ _dist1 = [getpos(_x),_flankPos] call KRON_distancePosSqr;
+ _dist2 = [getpos(_x),_flankPos2] call KRON_distancePosSqr;
+ _dist3 = [getpos(_x),_frontPos] call KRON_distancePosSqr;
+ if (_dist1 <= _flankdist/1.5 || _dist2 <= _flankdist/1.5 || _dist3 <= _flankdist/1.5) then {
+ if (_dist1 < _dist2 && _dist1 < _dist3) then {_fldest = _fldest + 1;};
+ if (_dist2 < _dist1 && _dist2 < _dist3) then {_fldest2 = _fldest2 + 1;};
+ if (_dist3 < _dist1 && _dist3 < _dist2) then {_fldestfront = _fldestfront + 1;};
+ };
+ };
+ _i = _i + 1;
+ sleep 0.01;
+ } foreach KRON_NPCs;
+
+
+
+ //La preferencia es la elección inicial de dirección
+ switch (_flankdir) do {
+ case 1:
+ {_prov = 125};
+ case 2:
+ {_prov = -25};
+ default
+ {_prov = 50};
+ };
+
+
+ //Si es positivo significa que hay más destinos existentes lejanos a la posicion de flanqueo1, tomamos primariamente este
+ if (_fldest<_fldest2) then {_prov = _prov + 50;};
+ if (_fldest2<_fldest) then {_prov = _prov - 50;};
+
+ //Si la provablilidad es negativa indica que tomará el flank2 por lo tanto la provabilidad de coger 1 es 0
+ if (_prov<0) then {_prov = 0;};
+
+
+ //Evaluamos la dirección en base a la provablilidad calculada
+ if ((random 100) <= _prov) then {
+ _flankdir =1;
+ _flankPos = _flankPos; _targettext = "_flankPos";
+ } else {
+ _flankdir =2;
+ _flankPos = _flankPos2; _targettext = "_flankPos2";
+ };
+
+
+ //Posición de ataque por defecto el flanco
+ _targetPos = _flankPos;
+ _targettext = "_flankPos";
+
+
+ if ((surfaceIsWater _flankPos && !(_isplane || _isboat)) ) then {
+ _targetPos = _attackPos;_targettext ="_attackPos";
+ _flankdir =0;
+ } else {
+ if (_fldestfront < _fldest && _fldestfront < _fldest2) then {
+ _targetPos = _frontPos;_targettext ="_frontPos";
+ };
+ };
+
+
+ //Establish the type of waypoint
+ //DESTROY has worse behavior with and sometimes do not move
+ _wptype = "MOVE";
+
+ //Set speed and combat mode
+ _rnd = random 100;
+ if (_dist <= _closeenough) then {
+ //If we are so close we prioritize discretion fire
+ if ( _dist <= _closeenough/2 ) then {
+ //Close combat modeo
+ _speedmode = "LIMITED";
+ _wpformation = "LINE";
+ _unitpos = "AUTO"; //"Middle"
+ _react = _react + KRON_UPS_react / 2;
+ _minreact = KRON_UPS_minreact / 2;
+ if ((_nomove == "NOMOVE" && _rnd < 25) && !_reinforcementsent) then {
+ //Defensive combat
+ _Behaviour = "STEALTH";
+ _wptype = "HOLD";
+ } else {
+ if (_rnd < 80) then {
+ _Behaviour = "COMBAT"; // (combat / stealth)
+ } else {
+ _Behaviour = "AWARE";
+ };
+ _wptype = "MOVE";
+ _npc setCombatMode "RED";
+ }
+ } else {
+ //If the troop has the role of not moving tend to keep the position
+ _speedmode = "NORMAL";
+ _wpformation = "VEE"; //or VEE
+ _unitpos = "AUTO";// "Middle"
+ _minreact = KRON_UPS_minreact / 1.5;
+ if ((_nomove == "NOMOVE" && _rnd < 50) && !_reinforcementsent) then {
+ //Combate defensivo
+ _Behaviour = "COMBAT";
+ _wptype = "HOLD";
+ } else {
+ if (_rnd < 70) then {
+ _Behaviour = "AWARE";
+ } else {
+ _Behaviour = "COMBAT";
+ };
+ _wptype = "MOVE";
+ _npc setCombatMode "YELLOW";
+ };
+ };
+ } else {
+ if (( _dist <= (_closeenough + KRON_UPS_safedist))) then {
+ _speedmode = "FULL";
+ _wpformation = "WEDGE";
+ _unitpos = if (_rnd < 90) then {"Middle"} else {"AUTO"};
+ _minreact = KRON_UPS_minreact;
+ if ((_nomove=="NOMOVE" && _rnd < 75) && !_reinforcementsent) then {
+ //Combate defensivo
+ _Behaviour = "COMBAT"; //AWARE
+ _wptype = "HOLD";
+ } else {
+ //Movimiento con precaución (más rápido)
+ _Behaviour = "AWARE";
+ _wptype = "MOVE";
+ };
+ } else {
+ //In May distance of radio patrol act..
+ if (( _dist < KRON_UPS_sharedist )) then {
+ //Platoon from the target must move fast and to the point
+ _Behaviour = "AWARE";
+ _speedmode = "FULL";
+ _unitpos = if (_rnd < 60) then {"Middle"} else {"AUTO"};
+ _minreact = KRON_UPS_minreact * 2;
+ if ((_nomove=="NOMOVE" && _rnd < 95) && !_reinforcementsent) then {
+ _wptype = "HOLD";
+ _wpformation = "WEDGE";
+ } else {
+ _wptype = "MOVE";
+ _wpformation = "WEDGE";
+ };
+ } else {
+ //Platoon very far from the goal if not move nomove role
+ _Behaviour = "SAFE";
+ _speedmode = "FULL";
+ _unitpos = "AUTO";
+ _minreact = KRON_UPS_minreact * 3;
+
+ if (((_nomove=="NOMOVE") || (_nomove=="MOVE" && _rnd < 70)) && !_reinforcementsent) then {
+ _wptype = "HOLD";
+ _wpformation = "WEDGE";
+ }else{
+ _wptype = "MOVE";
+ _wpformation = "FILE"; //COLUMN
+ };
+ };
+ };
+ };
+
+
+
+ //Always keep the brackets fortified position
+ if ( _fortify && random 100 < 99) then {_wptype = "HOLD"};
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ //If leader is in vehicle will move in anyway
+ if (vehicle _npc != _npc || !_isman) then {
+ _wptype = "MOVE";
+ _Behaviour = "AWARE";
+ if ( _inheli ) then {
+ _speedmode = "FULL";
+ _unitpos = "AUTO";
+ _targetPos = _AttackPos;
+ };
+ };
+
+
+
+
+
+ //Establecemos el target
+ KRON_targetsPos set [_grpid,_targetPos];
+ sleep 0.01;
+
+ //If use statics are enabled leader searches for static weapons near.
+ // Tanks enemies are contabiliced
+ if ( KRON_UPS_useMines && _Mines > 0 ) then {
+ _enemytanksnear = false;
+ {
+ if ( ("Tank" countType [_x] > 0 || "Wheeled_APC" countType [_x] >0
+ || "Tank" countType [vehicle _x] > 0 || "Wheeled_APC" countType [vehicle _x] >0 )
+ && alive _x && canMove _x && _npc distance _x <= _closeenough + KRON_UPS_safedist )
+ exitwith { _enemytanksnear = true; _enemytanknear = _x;};
+ } foreach _targets;
+
+
+
+ //If use mines are enabled and enemy armors near and no friendly armor put mine.
+ if ( _enemytanksnear && !isnull _enemytanknear && alive _enemytanknear ) then {
+ _friendlytanksnear = false;
+ {
+ if (!( alive _x && canMove _x)) then {_friendlytanks = _friendlytanks - [_x]};
+ if (alive _x && canMove _x && _npc distance _x <= _closeenough + KRON_UPS_safedist ) exitwith { _friendlytanksnear = true;};
+ }foreach _friendlytanks;
+
+ if (!_friendlytanksnear && random(100)<30 ) then {
+ _dir1 = [_currPos,position _enemytanknear] call KRON_getDirPos;
+ _mineposition = [position _npc,_dir1, 25] call MON_GetPos2D;
+ _roads = _mineposition nearroads 50;
+ if (count _roads > 0) then {_mineposition = position (_roads select 0);};
+ if ([_npc,_mineposition] call MON_CreateMine) then {
+ _Mines = _Mines -1;
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: %3 puting mine for %2",_grpidx,typeof _enemytanknear, side _npc]};
+ };
+ };
+ };
+ };
+
+
+
+
+
+ //Si es unidad de refuerzo siempre acosará al enemigo
+ if (_reinforcementsent) then {
+ _wptype="MOVE";
+ _newpos=true;
+ _makenewtarget = false;
+ };
+
+ if (_nofollow=="NOFOLLOW" && _wptype != "HOLD") then {
+ _targetPos = [_targetPos,_centerpos,_rangeX,_rangeY,_areadir] call KRON_stayInside;
+ _targetdist = [_currPos,_targetPos] call KRON_distancePosSqr;
+ if ( _targetdist <= 1 ) then {
+ _wptype="HOLD";
+ };
+ };
+
+ if (_wptype == "HOLD") then {
+ _targetPos = _currPos; _targettext ="_currPos";
+ };
+
+ //Is updated with the latest value, changing the target
+ _lastknown = _opfknowval;
+
+ //If for whatever reason cancels the new position should make clear the parameters that go into pursuit
+ if (!_newpos) then {
+ //If the unit has decided to maintain position but is being attacked is being suppressed, should have the opportunity to react
+ _newpos = _gothit;
+
+ if (!_newpos) then {
+ _targetPos=_lastpos;
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 Mantaining orders %2",_grpidx,_nomove]};
+ };
+ };
+ if (KRON_UPS_Debug>=1) then {
+ "avoid" setmarkerpos _avoidPos; "flank" setmarkerpos _flankPos; _destname setMarkerPos _targetPos;
+ };
+ }; //END PURSUE
+ sleep 0.1;
+ }; //((_isSoldier) && ((count _enemies)>0)
+
+
+// **********************************************************************************************************************
+// NO NEWS
+// **********************************************************************************************************************
+ if !(_newpos) then {
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ // calculate new distance
+ // if we're waiting at a waypoint, no calculating necessary
+ _currpos = getpos _npc;
+
+
+
+ //Sets behaviour of squad if nearly changes of target
+ if (_targetsnear) then{
+ if (( toUpper(_Behaviour) IN _safemode) && _isSoldier) then {
+ _Behaviour = "AWARE";
+ _npc setBehaviour _Behaviour;
+ };
+ };
+
+
+
+ //If in safe mode if find dead bodies change behaviour
+ if ((toUpper(_Behaviour) IN _safemode) && _deadBodiesReact)then {
+ _unitsin = [_npc,_buildingdist] call MON_deadbodies;
+ if (count _unitsin > 0) then {
+ if !_isSoldier then {
+ _npc setSpeedMode "FULL";
+ } else {
+ if ( random 100 < 75) then {
+ _Behaviour = "AWARE";
+ } else {
+ _Behaviour = "COMBAT";
+ };
+ _react = _react + 30;
+ _npc setBehaviour _Behaviour;
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 dead bodies found! set %2",_grpidx,_Behaviour, count _targets]};
+ };
+ };
+ };
+
+
+ //Stuck control
+ if (!_nowp && alive _npc && canmove _npc && _wptype == "MOVE" && _timeontarget >= 60 && _lastcurrpos select 0 == _currpos select 0 && _lastcurrpos select 1 == _currpos select 1) then {
+ [_npc] call MON_cancelstop;
+ _makenewtarget = true;
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 stucked, moving",_grpidx]};
+ };
+
+ _lastpos = _targetPos;
+ _lastcurrpos = _currpos; //sets last currpos for avoiding stuk
+
+ if (_waiting<0) then {
+ //Gets distance to targetpos
+ _targetdist = [_currPos,_targetPos] call KRON_distancePosSqr;
+
+ //It assesses whether it has exceeded the maximum waiting time and the objective is already shot to return to the starting position.
+ if (_fightmode!="walk") then {
+ if (_timeontarget > KRON_UPS_alerttime && count _targets <= 0 && ( isNull (_target) || !alive (_target) || captive _target)) then {
+ _pursue = false;
+ _gothit = false;
+ _targetdead = true;
+ _fightmode = "walk";
+ _speedmode = _orgSpeed;
+ _targetPos = _currPos;
+ _reinforcementsent = false;
+ _target = objnull;
+ _fixedtargetPos = [0,0];
+ _Behaviour = _orgMode;
+ _waiting = -1;
+ _unitpos = "AUTO";
+ _wpformation = "WEDGE";
+
+ KRON_UPS_reinforcement = false; //there is no threat
+ if (_rfid > 0 ) then {
+ call (compile format ["KRON_UPS_reinforcement%1 = false;",_rfid]);
+ };
+
+ {[_x,"AUTO"] spawn MON_setUnitPos;} foreach units _npc;
+ _npc setBehaviour _orgMode;
+
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 Without objectives, leaving combat mode",_grpidx]};
+ };
+ };
+
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%1 _targetdist %2 atdist=%3 dist=%4",_grpidx, _targetdist, _area/8,_dist]};
+ // if not in combat and we're either close enough, seem to be stuck, or are getting damaged, so find a new target
+ if (!_nowp && (!_gothit) && (!_swimming) && (_fightmode == "walk") && (( _targetdist <= (_area/4) || moveToFailed _npc) && (_timeontarget > KRON_UPS_maxwaiting))) then {
+ _makenewtarget=true;
+ _unitpos = "AUTO";
+ _Behaviour = _orgMode;
+ };
+
+ // make new target
+ if (_makenewtarget) then
+ {
+ _gothit = false;
+ _react = 0;
+ _lastreact = 0;
+ _makenewtarget = false;
+ _timeontarget = 0;
+ _wptype = "MOVE";
+
+ if (format ["%1",_fixedtargetPos] !="[0,0]") then {
+ _targetPos = _fixedtargetPos; _targettext ="Reinforcement";
+ } else {
+
+ if ((_nomove=="NOMOVE") && (_timeontarget>KRON_UPS_alerttime)) then {
+ if (KRON_UPS_Debug>0) then {player sidechat format["nomove: %1",_nomove]};
+ if (([_currPos,_orgPos] call KRON_distancePosSqr)<_closeenough) then {
+ _newpos = false;
+ _wptype = "HOLD";
+ _waiting = 9999;
+ if (_fortify) then {
+ _minreact = KRON_UPS_minreact * 3;
+ _buildingdist = _buildingdist * 2;
+ _wait = 3000;
+ };
+ } else {
+ _targetPos=_orgPos; _targettext ="_orgPos";
+ };
+ } else {
+
+ //rStuckControl !R
+ _rcurrPos = getpos _npc;
+ if (_rlastPos select 0 == _rcurrPos select 0 && _rlastPos select 1 == _rcurrPos select 1) then {
+
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 !RstuckControl try to move",_grpidx]};
+ if (vehicle _npc != _npc) then {
+ _rstuckControl = _rstuckControl + 1;
+ if (_rstuckControl > 1) then {
+ _jumpers = crew (vehicle _npc);
+ {
+ _x spawn MON_doGetOut;
+ sleep 0.5;
+ } forEach _jumpers;
+
+ } else {
+ nul = [vehicle _npc] spawn MON_domove;
+ }
+
+ } else {
+ nul = [_npc,25] spawn MON_domove;
+ };
+
+ } else {
+ _rstuckControl = 0;
+ };
+ _rlastPos = _rcurrPos;
+
+
+
+ // re-read marker position/size
+ _centerpos = getMarkerPos _areamarker; _centerX = abs(_centerpos select 0); _centerY = abs(_centerpos select 1);
+ _centerpos = [_centerX,_centerY];
+ _areasize = getMarkerSize _areamarker; _rangeX = _areasize select 0; _rangeY = _areasize select 1;
+ _areadir = (markerDir _areamarker) * -1;
+
+ // find a new target that's not too close to the current position
+ _targetPos=_currPos; _targettext ="newTarget";
+ _tries=0;
+
+ while {((([_currPos,_targetPos] call KRON_distancePosSqr) < _mindist)) && (_tries<50)} do {
+ _tries=_tries+1;
+ // generate new target position
+ _targetPos = [_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+
+ _loop2=FALSE;
+ // boat or plane
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1, type: %2",_npc, typeOf _npc]}; sleep 4;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 isplane",_isplane]}; sleep 4;
+ if (_isplane || _isboat) then {
+ // boat
+ if (_isboat) then {
+ _tries2=0;
+ while {(!_loop2) && (_tries2 <50)} do {
+ _tries2=_tries2+1;
+ _targetPosTemp = [_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+ if (surfaceIsWater _targetPosTemp) then {
+ _targetPos = _targetPosTemp;
+ _loop2 = TRUE;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 Boat just got new targetPos",_grpidx]};
+ };
+ sleep 0.05;
+ };
+
+ // plane
+ } else {
+ _targetPos = [_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 Plane just got new targetPos",_grpidx]};
+ };
+
+ // man or car
+ } else {
+ // "_onroad"
+ if _onroad then {
+ _tries2=0;
+ while {(!_loop2) && (_tries2 <100)} do {
+ _tries2=_tries2+1;
+
+ _targetPosTemp = [_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+ _roads = (_targetPosTemp nearRoads 50);
+ if ((count _roads) > 0) then {
+ _targetPosTemp = getpos (_roads select 0);
+ _targetPos = _targetPosTemp;
+ _loop2 = TRUE;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 Onroad just got new targetPos",_grpidx]};
+ };
+ sleep 0.05;
+ };
+ // any place on ground
+ } else {
+
+ _tries2=0;
+ while {(!_loop2) && (_tries2 <100)} do {
+ _tries2=_tries2+1;
+ _targetPosTemp = [_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
+ if (!surfaceIsWater _targetPosTemp) then {
+ _targetPos = _targetPosTemp;
+ _loop2 = TRUE;
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1 Man just got new TP %2, %3",_grpidx,_targetPos,_tries2]};
+ };
+ sleep 0.05;
+ };
+
+ };
+ };
+ };
+ };
+ };
+ sleep 0.05;
+
+
+ // distance to target position
+ _avoidPos = [0,0]; _flankPos = [0,0]; _attackPos = [0,0]; _frontPos = [0,0];
+ _fm=0;
+ _newpos=true;
+ };
+ };
+ };
+
+ // if in water, get right back out of it again
+ if (surfaceIsWater _currPos) then {
+ if (_isman && !_swimming) then {
+ _drydist=999;
+ // look around, to find a dry spot
+ for [{_a=0}, {_a<=270}, {_a=_a+90}] do {
+ _dp=[_currPos,30,_a] call KRON_relPos;
+ if !(surfaceIsWater _dp) then {_targetPos=_dp};
+ };
+ _newpos=true;
+ _swimming=true;
+ };
+ } else {
+ _swimming=false;
+ };
+
+ sleep 0.5;
+
+
+// **********************************************************************************************************************
+// NEWPOS: SE EJECUTA LA ORDEN DE MOVIMIENTO
+// **********************************************************************************************************************
+// if (KRON_UPS_Debug>0) then {player sidechat format["%1 rea=%2 wai=%3 tim=%4 tg=%5 %6",_grpidx,_react,_waiting,_timeontarget,typeof _target,alive _target]};
+ if ((_waiting<=0) && _newpos) then {
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ _currPos = getpos _npc;
+ _newpos = false;
+ _waiting = -1;
+ _swimming=false;
+ _GetIn_NearestVehicles = false;
+
+ //Gets distance to targetpos
+ _targetdist = [_currPos,_targetPos] call KRON_distancePosSqr;
+
+ //If gothit and not in vehicle
+ if (_gothit && _npc == vehicle (_npc) && alive _npc ) then {
+
+ //Unidad suprimida
+ if ((random 100) <50) then {
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1 supressed by fire",_grpidx]};
+
+ //The unit is deleted, delete the current waypoint
+ _supressed = true;
+ _targetPos = _currPos; _targettext ="SUPRESSED";
+ _wptype = "HOLD";
+
+ //Prone
+ {
+ //Motion vanishes
+ if ( _x iskindof "Man" && canmove _x && alive _x) then {
+ if ((random 100)<40 || (primaryWeapon _x ) in KRON_UPS_MG_WEAPONS) then {[_x,"DOWN",20] spawn MON_setUnitPosTime;
+ }else{ [_x,"Middle"] spawn MON_setUnitPos;};
+ };
+ sleep 0.01;
+ } foreach units _npc;
+
+ //All Retreat!!
+ if ((random 100)<=60 && morale _npc < 0) then {
+ _targetPos = _avoidPos;_targettext = "_avoidPos";
+ _wptype = "MOVE";
+ _flankdir = 0;
+ if (!_newpos && KRON_UPS_Debug>0) then {player sidechat format["%1 All Retreat!!!",_grpidx]};
+ };
+ };
+
+ if ((random 100) < 15 && _targettext == "_avoidPos" && !_nosmoke) then {
+ [_npc,_target] call MON_throw_grenade;
+ };
+ sleep 0.5;
+ };
+
+
+
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ //If you have not been removed progress continue
+ if (alive _npc) then {
+ _currPos = getpos _npc;
+
+ if ( _wptype == "MOVE") then {
+
+ //Try to avoid stucked soldiers out of vehicles
+ if ( _npc == vehicle _npc) then {
+ {
+ if (alive _x && canmove _x) then {
+ //[_x] spawn MON_cancelstop;
+ [_x] dofollow _npc;
+ };
+ } foreach _members;
+ };
+ sleep 0.05;
+
+ //Search for vehicle
+ if ((!_gothit && _targetdist >= ( KRON_UPS_searchVehicledist )) && _isSoldier && !_noveh) then {
+
+ if ( vehicle _npc == _npc && _dist > _closeenough ) then {
+
+ _unitsIn = [_grpid,_npc] call MON_GetIn_NearestVehicles;
+
+ if ( count _unitsIn > 0) then {
+ _GetIn_NearestVehicles = true;
+ _speedmode = "FULL";
+ _unitpos = "AUTO";
+ _npc setbehaviour "SAFE";
+ _npc setspeedmode "FULL";
+ _timeout = time + 60;
+
+ _vehicle = objnull;
+ _vehicles = [];
+ {
+ waituntil {vehicle _x != _x || !canmove _x || !canstand _x || !alive _x || time > _timeout || movetofailed _x};
+
+ if ( vehicle _x != _x && (isnull _vehicle || _vehicle != vehicle _x)) then {
+ _vehicle = vehicle _x ;
+ _vehicles = _vehicles + [_vehicle]
+ };
+ }foreach _unitsIn;
+ sleep 1;
+
+ {
+ _vehicle = _x;
+ _cargo = _vehicle getvariable ("UPSMON_cargo");
+ if ( isNil("_cargo")) then {_cargo = [];};
+ _cargo ordergetin true;
+
+ //Wait for other groups to getin
+ {
+ waituntil {vehicle _x != _x || !canmove _x || !canstand _x || !alive _x || time > _timeout || movetofailed _x};
+ } foreach _cargo;
+
+ //Starts gunner control
+ nul = [_vehicle] spawn MON_Gunnercontrol;
+ sleep 0.1;
+ // nul = [_x,30] spawn MON_domove; //!R just little kick to make sure it moves
+ } foreach _vehicles;
+
+ //Cheks if leader has dead until wait
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc) exitwith {_exit=true;};
+
+
+ if ( "Air" countType [vehicle (_npc)]>0) then {
+ _rnd = (random 2) * 0.1;
+ _flyInHeight = round(KRON_UPS_flyInHeight * (0.9 + _rnd));
+ vehicle _npc flyInHeight _flyInHeight;
+
+ //If you just enter the helicopter landing site is defined
+ if (_GetIn_NearestVehicles) then {
+ _GetOutDist = round(((KRON_UPS_paradropdist ) * (random 100) / 100 ) + 150);
+
+ [vehicle _npc, _TargetPos, _GetOutDist, 90] spawn MON_doParadrop; // org _flyInHeight
+ sleep 1;
+ //Execute control stuck for helys
+ [vehicle _npc] spawn MON_HeliStuckcontrol;
+ if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: flyingheiht=%2 paradrop at dist=%3",_grpidx, _flyInHeight, _GetOutDist,_rnd]};
+ };
+ };
+ };
+ };
+ };
+ };
+ sleep 0.05;
+
+
+ //Get in combat vehicles
+ if (!_gothit && !_GetIn_NearestVehicles && _fightmode != "walk" && _isSoldier) then {
+ _dist2 = _dist / 4;
+ if ( _dist2 <= 100 ) then {
+ _unitsIn = [];
+ _unitsIn = [_grpid,_npc,_dist2,false] call MON_GetIn_NearestCombat;
+ _timeout = time + (_dist2/2);
+
+ if ( count _unitsIn > 0) then {
+ if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: Geting in combat vehicle targetdist=%2",_grpidx,_npc distance _target]};
+ _npc setbehaviour "SAFE";
+ _npc setspeedmode "FULL";
+
+ {
+ waituntil {vehicle _x != _x || !canmove _x || !canstand _x || !alive _x || time > _timeout || movetofailed _x};
+ }foreach _unitsIn;
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ //Return to combat mode
+ _npc setbehaviour _Behaviour;
+ _timeout = time + 150;
+ {
+ waituntil {vehicle _x != _x || !canmove _x || !alive _x || time > _timeout || movetofailed _x};
+ }foreach _unitsIn;
+
+ {
+ if ( vehicle _x iskindof "Air") then {
+ //moving hely for avoiding stuck
+ if (driver vehicle _x == _x) then {
+ _vehicle = vehicle (_x);
+ nul = [_vehicle,1000] spawn MON_domove;
+ //Execute control stuck for helys
+ [_vehicle] spawn MON_HeliStuckcontrol;
+ if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: Geting in combat vehicle after",_grpidx,_npc distance _target]};
+ };
+ };
+
+ if (driver vehicle _x == _x) then {
+ //Starts gunner control
+ nul = [vehicle _x] spawn MON_Gunnercontrol;
+ };
+ sleep 0.01;
+ }foreach _unitsIn;
+ };
+
+ };
+ };
+
+
+
+ sleep 0.05;
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ //If use statics are enabled leader searches for static weapons near.
+ if ((KRON_UPS_useStatics && (vehicle _npc == _npc) && !_GetIn_NearestVehicles && _isSoldier ) && ((_wptype == "HOLD" && (random 100) < 80) || (_wptype != "HOLD" && (random 100) < 60))) then {
+
+ _unitsIn = [_grpid,_npc,_buildingdist] call MON_GetIn_NearestStatic;
+
+ if ( count _unitsIn > 0) then {
+ _npc setbehaviour "SAFE";
+ _npc setspeedmode "FULL";
+ _timeout = time + 60;
+
+ {
+ waituntil {vehicle _x != _x || !canmove _x || !alive _x || time > _timeout || movetofailed _x};
+ }foreach _unitsIn;
+
+ };
+ sleep 0.05;
+ };
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ //Buildings usage.
+ if (!_GetIn_NearestVehicles) then {
+ if ( _wptype == "HOLD" && vehicle _npc == _npc && ( _fortify ||(random 100) < 60) ) then {
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: Moving to nearest buildings",_grpidx]};
+ [_npc,_buildingdist,false,_wait] spawn MON_moveNearestBuildings;
+ } else {
+ //If we are close enough patrol in buildings for searching enemies
+ if ((( _wptype != "HOLD" && vehicle _npc == _npc && (random 100) < 90 )
+ && _npc == vehicle _npc && _dist <= ( _closeenough ))) then {
+ [_npc,_buildingdist,true] spawn MON_moveNearestBuildings;
+ };
+ };
+ sleep 0.05;
+ };
+
+ // did the leader die?
+ _npc = [_npc,_members] call MON_getleader;
+ if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};
+
+ if (isnull _grp || _grp != group _npc) then {
+ _grp = group _npc;
+ };
+
+
+ _index = currentWaypoint _grp;
+
+ //If the waypoing is different than it has or is different from what we set hold
+ IF (_wptype != "HOLD" || _lastwptype != _wptype) then {
+ //Has not completed or are waypoints
+ //_index = 1 Waypoint by default, not use.
+ if ( _index == 1 || _index > count waypoints _grp && !isnull _grp) then {
+ _wp = _grp addWaypoint [_targetPos, 0];
+ _index = _wp select 1;
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1: created wp %2 index %3",_grpidx,_wp, _index]};
+ } else {
+ _wp = [_grp,_index];
+ // if (KRON_UPS_Debug>0) then {player globalchat format["%1: not created wp %2 index %3 %4",_grpidx,_wp, _index,_targetPos]};
+ };
+ };
+
+ // _wp = [_grp,_index];
+
+
+
+ // if iscar the run fast if targetpost is far.
+ if ((!_gothit && _targetdist >= (_closeenough * 1.5)) && (vehicle _npc != _npc)) then {
+ _speedmode = "FULL";
+ } else {
+ // _speedmode = _orgSpeed;
+ };
+
+
+
+ //We define the parameters of the new waypoint
+ _wp setWaypointType _wptype;
+ _wp setWaypointPosition [_targetPos, 0];
+ _wp setWaypointFormation _wpformation;
+ _wp setWaypointSpeed _speedmode;
+ _lastwptype = _wptype;
+
+
+ //If you have more than 1 waypoints delete the obsolete
+ {
+ if ( _x select 1 < _index ) then {
+ deleteWaypoint _x;
+ };
+ sleep 0.05;
+ } foreach waypoints _grp;
+
+
+ //if (KRON_UPS_Debug>0) then {diag_log format["%1: waypoints %2 %3 %4 %5",_grpidx,count waypoints _grp, _grp, group _npc, group (leader _npc)]};
+
+ //Sets behaviour
+ if (toupper(behaviour _npc) != toupper (_Behaviour)) then {
+ _npc setBehaviour _Behaviour;
+ };
+
+ //Refresh position vector
+ KRON_targetsPos set [_grpid,_targetPos];
+
+ //Although there are predefined type of movement to a small percentage will vary on an individual level
+
+
+ {
+ if ((random 100)<95 && _x == vehicle _x && _x iskindof "Man" && !((primaryWeapon _x ) in KRON_UPS_MG_WEAPONS)) then {
+ nul = [_x,_unitpos] spawn MON_setUnitPos;
+ }else{
+ nul = [_x,"AUTO"] spawn MON_setUnitPos;
+ };
+ } foreach units _npc;
+
+
+ //If closeenough will leave some soldiers doing supress fire
+ if (_gothit || _dist <= _closeenough) then {
+ {
+ if (!canStand _x || ((primaryWeapon _x ) in KRON_UPS_MG_WEAPONS) || (vehicle _x == _x && _x iskindof "Man" && (random 100) < 50) ) then {
+ _x suppressFor 15;
+ };
+ } foreach units _npc;
+ };
+ };
+
+
+ _gothit = false;
+
+
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: %2 %3 %4 %5 %6 %7 %8 %9 %10",_grpidx, _wptype, _targettext,_dist, _speedmode, _unitpos, _Behaviour, _wpformation,_fightmode,count waypoints _grp];};
+ };
+
+ if (_track=="TRACK") then {
+ switch (_fm) do {
+ case 1:
+ {_destname setmarkerSize [.4,.4]};
+ case 2:
+ {_destname setmarkerSize [.6,.6]};
+ default
+ {_destname setmarkerSize [.5,.5]};
+ };
+ _destname setMarkerPos _targetPos;
+
+ };
+
+ //If in hely calculations must done faster
+ if (_isplane || _inheli) then {
+ _currcycle = _cycle/2;
+ _flyInHeight = KRON_UPS_flyInHeight;
+ vehicle _npc flyInHeight _flyInHeight;
+
+ };
+
+ if ((_exit) || (isNil("_npc"))) then {
+ _loop=false;
+ } else {
+ // slowly increase the cycle duration after an incident
+ sleep _currcycle;
+ };
+
+}; //while {_loop}
+
+
+ if (KRON_UPS_Debug>0) then {hint format["%1 exiting mainloop",_grpidx]};
+
+ //Limpiamos variables globales de este grupo
+ KRON_targetsPos set [_grpid,[0,0]];
+ KRON_NPCs set [_grpid,objnull];
+ KRON_UPS_Exited=KRON_UPS_Exited+1;
+
+ if (_track=="TRACK") then {
+ //_trackername setMarkerType "Dot";
+ _trackername setMarkerType "Empty";
+ _destname setMarkerType "Empty";
+ };
+
+ //Gets dist from orinal pos
+ if (!isnull _target) then {
+ _dist = ([_orgpos,position _target] call KRON_distancePosSqr);
+ };
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1 _dist=%2 _closeenough=%3",_grpidx,_dist,_closeenough]};
+
+ //does respawn of group =====================================================================================================
+ if (_respawn && _respawnmax > 0 && !_surrended && _dist > _closeenough) then {
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1 doing respawn",_grpidx]};
+
+ // copy group leader
+ _unittype = _membertypes select 0;
+
+ // make the clones civilians
+ // use random Civilian models for single unit groups
+ if ((_unittype=="Civilian") && (count _members==1)) then {_rnd=1+round(random 20); if (_rnd>1) then {_unittype=format["Civilian%1",_rnd]}};
+
+ _grp=createGroup _side;
+ _lead = _grp createUnit [_unittype, _orgpos, [], 0, "form"];
+ _lead setVehicleInit _initstr;
+ [_lead] join _grp;
+ _grp selectLeader _lead;
+
+ // copy team members (skip the leader)
+ _i=0;
+ {
+ _i=_i+1;
+ if (_i>1) then {
+ _newunit = _grp createUnit [_x, _orgpos, [],0,"form"];
+ _newunit setVehicleInit _initstr;
+ [_newunit] join _grp;
+ sleep 0.1;
+ };
+ } foreach _membertypes;
+
+
+ if ( _lead == vehicle _lead) then {
+ {
+ if (alive _x && canmove _x) then {
+ [_x] dofollow _lead;
+ };
+ sleep 0.1;
+ } foreach units _lead;
+ };
+
+ {
+ _targetpos = _orgpos findEmptyPosition [10, 200];
+ sleep .4;
+ if (count _targetpos <= 0) then {_targetpos = _orgpos};
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%1 create vehicle _newpos %2 ",_x,_targetpos]};
+ _newunit = _x createvehicle (_targetpos);
+ } foreach _vehicletypes;
+
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%1 _vehicletypes: %2",_grpidx, _vehicletypes]};
+
+ //Set new parameters
+ if (!_spawned) then {
+
+ _UCthis = _UCthis + ["SPAWNED"];
+
+ if ((count _vehicletypes) > 0) then {
+ _UCthis = _UCthis + ["VEHTYPE:"] + ["dummyveh"];
+ };
+ };
+
+
+ _UCthis set [0,_lead];
+ _respawnmax = _respawnmax - 1;
+ _UCthis = ["RESPAWN:",_respawnmax,_UCthis] call KRON_UPSsetArg;
+ sleep 0.1;
+ _UCthis = ["VEHTYPE:",_vehicletypes,_UCthis] call KRON_UPSsetArg;
+
+
+ // if (KRON_UPS_Debug>0) then {player globalchat format["%1 _UCthis: %2",_grpidx,_UCthis]};
+ //Exec UPSMON script
+ _UCthis SPAWN UPSMON;
+ sleep 0.1;
+ processInitCommands;
+ };
+
+ _friends=nil;
+ _enemies=nil;
+ _enemytanks = nil;
+ _friendlytanks = nil;
+ _roads = nil;
+ _targets = nil;
+ _members = nil;
+ _membertypes = nil;
+ _UCthis = nil;
+
+ if (!alive _npc) then {
+ deleteGroup _grp;
+ };
\ No newline at end of file diff --git a/Server/Module/UPSMON/UPSMON/!R/R_functions.sqf b/Server/Module/UPSMON/UPSMON/!R/R_functions.sqf new file mode 100644 index 0000000..396892f --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/!R/R_functions.sqf @@ -0,0 +1,343 @@ +/*
+ autor: !R
+
+ 5.1.0
+*/
+
+
+
+// get new position [x,y,x] from pos in distance and angle.
+// [_pos, _distance, _angle] call R_relPos3D;
+// [newX,newY,Z]
+R_relPos3D =
+ {
+ private["_p","_d","_a","_x","_y","_z","_xout","_yout"];
+ _p=_this select 0;
+ _x=_p select 0;
+ _y=_p select 1;
+ _z=_p select 2;
+ _d=_this select 1;
+ _a=_this select 2;
+ _xout=_x + sin(_a) * _d;
+ _yout=_y + cos(_a) * _d;
+ [_xout,_yout,_z]
+ };
+
+
+// [_unit] spawn R_ThrowSmoke;
+R_ThrowSmoke =
+ {
+ private ["_unit","_shell",
+ "_moves","_unitPos","_pos","_flare","_direction"];
+
+ /*
+ _stanThrow = ["AwopPercMstpSgthWrflDnon_Start1", "AwopPercMstpSgthWrflDnon_Throw1","AwopPercMstpSgthWrflDnon_End1"];
+ _kneeThrow = ["AwopPknlMstpSgthWrflDnon_Start", "AwopPknlMstpSgthWrflDnon_Throw" ,"AwopPknlMstpSgthWrflDnon_End"];
+ _proneThrow= ["AwopPpneMstpSgthWrflDnon_Start", "AwopPpneMstpSgthWrflDnon_Throw" ,"AwopPpneMstpSgthWrflDnon_End"];
+ */
+
+ _moves = ["AwopPercMstpSgthWrflDnon_Start1","AwopPknlMstpSgthWrflDnon_Start","AwopPpneMstpSgthWrflDnon_Start"];
+
+ _unit = _this select 0;
+ _shell = "SmokeShell";
+ _unitPos = unitPos _unit;
+
+ //Animation
+ switch (_unitPos) do {
+
+ case "Auto":
+ {
+ _unit playMove (_moves select 1);
+ };
+
+ case "Up":
+ {
+ _unit playMove (_moves select 0);
+ };
+
+ case "Middle":
+ {
+ _unit playMove (_moves select 1);
+ };
+
+ case "Down":
+ {
+ _unit playMove (_moves select 2);
+ };
+ };
+
+ sleep 4;
+ _direction = direction _unit;
+
+ // use such bypass as setvelocity does not work in MP
+ _pos = position _unit;
+ _pos = [(_pos select 0),(_pos select 1),(_pos select 2)+1.5];
+ _pos = [_pos, 18, _direction] call R_relPos3D;
+
+ if (alive _unit && canmove _unit) then {
+ _flare = _shell createVehicle _pos;
+ };
+
+ // setvelocity does not work in MP http://dev-heaven.net/issues/17949
+ /*
+ _vector = [18,direction _unit,0] call C B A_fnc_polar2vect;
+
+ _pos=position _unit;
+ _pos=[(_pos select 0),(_pos select 1),(_pos select 2)+2];
+ _flare = _shell createVehicle _pos;
+ _flare setPos _pos;
+ _flare setvelocity _vector;
+
+ */
+ };
+
+
+
+ // [_unit] call R_FN_deleteObsoleteWaypoints;
+ // leave only the last way point
+ R_FN_deleteObsoleteWaypoints =
+ {
+ private ["_unit","_grp"];
+
+ _unit = _this select 0;
+ _grp = group _unit;
+ while {(count (waypoints _grp)) > 1} do
+ {
+ deleteWaypoint ((waypoints _grp) select 0);
+ };
+ };
+
+
+
+ // array = [_npc] call R_FN_vehiclesUsedByGroup;
+ // return array of vehicles used by group
+ R_FN_vehiclesUsedByGroup =
+ {
+ private ["_npc","_vehicles"];
+
+ _npc = _this select 0;
+ _vehicles = [];
+
+ if (!alive _npc) exitwith {};
+
+ {
+ if (( vehicle _x != _x || !(_x iskindof "Man")) && !((vehicle _x) in _vehicles)) then {
+ _vehicles = _vehicles + [vehicle _x];
+ };
+ } foreach units _npc;
+
+ _vehicles
+ };
+
+
+ // array = [_vehicle] call R_FN_unitsInCargo;
+ // array of units in cargo of the vehicle (in vehicle and assigned as cargo)
+ R_FN_unitsInCargo =
+ {
+ private ["_vehicle","_x","_unitsInCargo"];
+
+ _vehicle = _this select 0;
+ _unitsInCargo = [];
+ {
+ if( (assignedVehicleRole _x) select 0 == "Cargo") then
+ {
+ _unitsInCargo = _unitsInCargo + [_x];
+ };
+ } forEach crew _vehicle;
+
+ _unitsInCargo
+ };
+
+
+
+
+
+ // array = [_npc] call R_FN_allUnitsInCargo;
+ // array of all units in cargo of the group (not driver, commander or gunner)
+ R_FN_allUnitsInCargo =
+ {
+ private ["_npc","_vehicles","_unitsInCargo","_allUnitsInCargo"];
+
+ _npc = _this select 0;
+ if (!alive _npc) exitwith {};
+
+ _allUnitsInCargo =[];
+
+ _vehicles = [_npc] call R_FN_vehiclesUsedByGroup;
+
+ {
+ _unitsInCargo = [_x] call R_FN_unitsInCargo;
+ _allUnitsInCargo = _allUnitsInCargo + _unitsInCargo;
+
+ } foreach _vehicles;
+
+ _allUnitsInCargo
+ };
+
+
+ // old MON_GetOutDist
+ // <- _npc
+ // <- _targetPos: position for exiting(if no waypoint used)
+ // <- _atdist: minimal dist to the _targetpos do getout
+ // -> nothing
+ // nul = [_npc,_targetpos,_atdist] spawn R_SN_GetOutDist;
+ R_SN_GetOutDist = {
+ private["_vehicle","_npc","_target","_atdist","_getout","_dogetout","_driver","_commander","_targetpos","_dist","_vehpos","_vehicles"];
+
+ _npc = _this select 0;
+ _targetpos = _this select 1;
+ _atdist = _this select 2; // minimal dist to the target to do getOut
+
+ _dogetout = []; // units to do getout
+ _vehicles = []; // vehs used by the group
+
+ if (!alive _npc) exitwith{};
+
+ _vehicle = vehicle _npc;
+ _vehpos = getpos _vehicle;
+
+ _dist = round([_vehpos,_targetpos] call KRON_distancePosSqr); // dist to the target
+
+ // if (KRON_UPS_Debug>0) then {player sidechat format["%1: Getoutdist dist=%2 atdist=%3 ",typeof _vehicle,_dist, _atdist]};
+
+ // if _npc is in vehicle
+ if ( _vehicle != _npc || !(_npc iskindof "Man")) then {
+
+ if ( (_dist) <= _atdist ) then {
+ _vehicles = [_npc] call R_FN_vehiclesUsedByGroup; // vehicles use by the group
+ {
+ _dogetout = [_x] call R_FN_unitsInCargo; // units cargo in the vehicle
+ _driver = driver _x;
+
+ if ( count _dogetout > 0 ) then {
+ //Stop the veh for 5.5 sek
+ nul = [_vehicle,5] spawn MON_doStop;
+
+ sleep 0.8; // give time to actualy stop
+
+ {
+ _x spawn MON_GetOut;
+ sleep 0.3;
+ } foreach _dogetout;
+
+ //We removed the id to the vehicle so it can be reused
+ _x setVariable ["UPSMON_grpid", 0, false];
+ _x setVariable ["UPSMON_cargo", [], false];
+
+ [_npc,_x, _driver] spawn MON_checkleaveVehicle; // if every one outside, make sure driver can walk
+ sleep 0.01;
+ };
+ } foreach _vehicles;
+ };
+ };
+ };
+
+ // #define GOTHIT(X) ([X] call R_FN_GOTHIT)
+ // nul = [_grpId] call R_FN_GOTHIT;
+ R_FN_GOTHIT =
+ {
+ _grpId = _this select 0;
+ if ((R_GOTHIT_ARRAY select _grpId) != 0) then
+ {
+ true
+ }
+ else
+ {
+ false
+ }
+ };
+
+ // use in gothit proces
+ // nul = [_unit, _shooter] spawn R_SN_EHHIT;
+ R_SN_EHHIT =
+ {
+ private ["_unit","_shooter","_grpId"];
+ _unit = _this select 0;
+ _shooter = _this select 1;
+ _grpId = _unit getVariable ("UPSMON_grpid");
+
+ if ((side _unit != side _shooter) && (R_GOTHIT_ARRAY select _grpId) == 0) then
+ {
+ R_GOTHIT_ARRAY set [_grpId, 1];
+ // if (KRON_UPS_Debug > 0) then {player globalchat format["UNIT: %1, SHOOTER :%2 %3",_unit,_shooter,side _shooter]};
+ };
+ };
+
+
+ // use in gothit proces
+ // nul = [_unit, _shooter] spawn R_SN_EHKILLED;
+ R_SN_EHKILLED =
+ {
+ private ["_unit","_shooter","_grpId"];
+
+ _unit = _this select 0;
+ _shooter = _this select 1;
+ _grpId = _unit getVariable ("UPSMON_grpid");
+
+ if ((side _unit != side _shooter) && (R_GOTHIT_ARRAY select _grpId) == 0) then
+ {
+ R_GOTHIT_ARRAY set [_grpId, 2];
+ // if (KRON_UPS_Debug > 0) then {player globalchat format["UNIT: %1, SHOOTER :%2 %3",_unit,_shooter,side _shooter]};
+ };
+ };
+
+
+ // logic is needed to display rGlobalChat
+ private ["_center","_group"];
+ _center = createCenter sideLogic; _group = createGroup _center;
+ R_Logic_civkill = _group createUnit ["LOGIC", [2,2,1], [], 0, "NONE"];
+ _group = nil;
+ _center = nil;
+
+
+ // used in gothit proces
+ // nul = [_unit, _shooter] spawn R_SN_EHKILLEDCIV;
+ R_SN_EHKILLEDCIV =
+ {
+ private ["_killer","_side"];
+ _killer = _this select 1;
+
+ //only if player killed a civilian
+ if (isPlayer _killer) then {
+
+ KILLED_CIV_COUNTER set [0,(KILLED_CIV_COUNTER select 0) + 1];
+
+ // if (KRON_UPS_Debug > 0) then {player globalchat format["KILLER: %1, %2", side _killer,KILLED_CIV_COUNTER ]};
+ switch (side _killer) do
+ {
+ case west:
+ {
+ KILLED_CIV_COUNTER set [1,(KILLED_CIV_COUNTER select 1) + 1];
+ };
+
+ case east:
+ {
+ KILLED_CIV_COUNTER set [2,(KILLED_CIV_COUNTER select 2) + 1];
+ };
+
+ case resistance:
+ {
+ KILLED_CIV_COUNTER set [3,(KILLED_CIV_COUNTER select 3) + 1];
+ };
+ };
+ KILLED_CIV_COUNTER set [4,_killer];
+
+ //if (KRON_UPS_Debug > 0) then {player globalchat format["KILLER: %1", side _killer ]};
+ if (KRON_UPS_Debug > 0) then {player globalchat format["KILLED_CIV_COUNTER: %1",KILLED_CIV_COUNTER]};
+ if (R_WHO_IS_CIV_KILLER_INFO > 0) then {
+ [R_Logic_civkill, nil , rglobalChat, format ["A CIVILIAN WAS KILLED BY %1",_killer]] call RE;
+ };
+ };
+ };
+
+
+ //firedNear
+ R_SN_EHFIREDNEAR =
+ {
+ private ["_civ"];
+ _civ = leader (_this select 0);
+ _civ setspeedmode "FULL";
+ };
+
+
+
\ No newline at end of file diff --git a/Server/Module/UPSMON/UPSMON/!R/markerAlpha.sqf b/Server/Module/UPSMON/UPSMON/!R/markerAlpha.sqf new file mode 100644 index 0000000..7b0ea31 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/!R/markerAlpha.sqf @@ -0,0 +1,14 @@ +/* =============================================
+ !R
+ Hide area markers.
+
+ create Game Logic Object
+ put in initialization field:
+
+ nul = call compile preprocessFile "scripts\UPSMON\!R\markerAlpha.sqf";
+
+ all markers area must be named area0, area1...area13
+
+================================================= */
+
+{ _x setmarkeralpha 0; } foreach ["area0", "area1", "area2","area3","area4","area5","area6","area7","area8","area9","area10","area11","area12","area13"];
\ No newline at end of file diff --git a/Server/Module/UPSMON/UPSMON/MON_artillery_add.sqf b/Server/Module/UPSMON/UPSMON/MON_artillery_add.sqf new file mode 100644 index 0000000..ecaec71 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/MON_artillery_add.sqf @@ -0,0 +1,64 @@ +/* =====================================================================================================
+ MON_spawn.sqf
+ Author: Monsada (chs.monsada@gmail.com)
+ Comunidad Hispana de Simulación:
+ http://www.simulacion-esp.com
+ =====================================================================================================
+ Parámeters: [_artillery,(_range,_rounds,_area,_cadence,_mincadence)] execvm "scripts\UPSMON\MON_artillery_add.sqf";
+ <- _artillery object to attach artillery script, must be an object with gunner.
+ <- ( _rounds ) rounds to fire each time, default 1
+ <- ( _range ) range of artillery, default 800
+ <- ( _area ) Dispersion area, 150m by default
+ <- ( _maxcadence ) Cadence of fire, is random between min, default 10s
+ <- ( _mincadence ) Minimum cadence, default 5s
+ <- ( _bullet ) Class of bullet to fire, default ARTY_Sh_81_HE
+ =====================================================================================================
+ 1. Place a static weapon on map.
+ 2. Exec module in int of static weapon
+
+ nul=[this] execVM "scripts\UPSMON\MON_artillery_add.sqf";
+
+ 1. Be sure static weapon has a gunner or place a "fortify" squad near, this will make squad to take static weapon.
+ 2. Create a trigger in your mission for setting when to fire. Set side artillery variable to true:
+
+ KRON_UPS_ARTILLERY_EAST_FIRE = true;
+
+ This sample will do east artilleries to fire on known enemies position, when you want to stop fire set to false.
+
+ For more info:
+ http://dev-heaven.net/projects/upsmon/wiki/Artillery_module
+ =====================================================================================================*/
+if (!isserver) exitWith {};
+
+//Waits until UPSMON is init
+waitUntil {!isNil("KRON_UPS_INIT")};
+waitUntil {KRON_UPS_INIT==1};
+
+private ["_artillery","_smoke1","_i","_area","_position","_maxcadence","_mincadence","_sleep","_rounds","_dummypos","_salvobreak"];
+_range = 800;
+_area = 150;
+_maxcadence = 10;
+_mincadence = 5;
+_sleep = 0;
+_rounds = 1;
+_bullet = "ARTY_Sh_81_HE";
+_vector =[];
+_salvobreak = 10;
+
+_artillery = _this select 0;
+//if (KRON_UPS_Debug>0) then {player globalchat format["MON_artillery_add before %1 %2 %3",isnull _artillery,alive _artillery]};
+if (isnull _artillery || !alive _artillery) exitwith{};
+if ((count _this) > 1) then {_rounds = _this select 1;};
+if ((count _this) > 2) then {_range = _this select 2;};
+if ((count _this) > 3) then {_area = _this select 3;};
+if ((count _this) > 4) then {_maxcadence = _this select 4;};
+if ((count _this) > 5) then {_mincadence = _this select 5;};
+if ((count _this) > 6) then {_bullet = _this select 6;};
+if ((count _this) > 7) then {_salvobreak = _this select 7;};
+//Add artillery to array of artilleries
+_vector = [_artillery,_rounds,_range,_area,_maxcadence,_mincadence,_bullet,_salvobreak];
+if (isnil "KRON_UPS_ARTILLERY_UNITS" ) then {KRON_UPS_ARTILLERY_UNITS = []};
+KRON_UPS_ARTILLERY_UNITS = KRON_UPS_ARTILLERY_UNITS + [_vector];
+
+_dummypos = [getpos _artillery, 50, getdir _artillery] call R_relPos3D;
+(gunner _artillery) lookAt [_dummypos select 0, _dummypos select 1,(_dummypos select 2)+100];
diff --git a/Server/Module/UPSMON/UPSMON/MON_spawn.sqf b/Server/Module/UPSMON/UPSMON/MON_spawn.sqf new file mode 100644 index 0000000..e952752 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/MON_spawn.sqf @@ -0,0 +1,115 @@ +/* =====================================================================================================
+ MON_spawn.sqf
+ Author: Monsada (chs.monsada@gmail.com)
+ Comunidad Hispana de Simulación:
+ http://www.simulacion-esp.com
+ =====================================================================================================
+ Parámeters: [Param1,Param2,Param3,[Param4]] EXECVM "SCRIPTS\UPSMON\MON_SPAWN.SQF";
+ <- Param1 Id of the template to copy.
+ <- Param2 Position to create new squad.
+ <- Param3 Nş of squads to create
+ <- Param4 Array of parameters of UPSMON, first must be name of marc to patrol
+ =====================================================================================================
+ Function that allows to spawn UPSMON squads.
+
+ 1- create a squad in editor. Exec UPSMON and set TEMPLATE id, this will save members of squad, not equipement.
+ nul = [this,"town","TEMPLATE:",1] execVM "scripts\upsmon.sqf";
+ 2- Exec MON_spawn on trigger or where you want telling the copy of the template to create
+ and the position.
+ nul = [1,[0,0,0],3,[mark, upsmon optional params]] EXECVM "SCRIPTS\UPSMON\MON_SPAWN.SQF";
+ =====================================================================================================*/
+if (!isserver) exitWith {};
+
+//Waits until UPSMON is init
+waitUntil {!isNil("KRON_UPS_INIT")};
+waitUntil {KRON_UPS_INIT==1};
+private ["_template","_position","_params","_copies","_membertypes","_unittype","_side","_UCthis","_initstr","_grp","_lead","_newunit","_i","_newpos","_vehicle","_initlstr"];
+
+//Parameter reading
+_template = _this select 0;
+_position = _this select 1;
+_copies = _this select 2;
+_params = _this select 3;
+
+//Initialization
+_membertypes = [];
+_side = "";
+_UCthis = [];
+_initstr = "";
+_initlstr = "";
+_grp = grpnull;
+_lead = objnull;
+_newunit = objnull;
+_newpos=[];
+_vehicle=[];
+
+//Gets parameters of UPSMON
+for [{_i=0},{_i<count _params},{_i=_i+1}] do {_e=_params select _i; if (typeName _e=="STRING") then {_e=toUpper(_e)};_UCthis set [_i,_e]};
+_initstr = ["INIT:","",_UCthis] call KRON_UPSgetArg;
+_initlstr = ["INITL:","",_UCthis] call KRON_UPSgetArg;
+_initlstr = _initlstr + _initstr;
+_spawned= if ("SPAWNED" in _UCthis) then {true} else {false};
+if (!_spawned) then {_UCthis = _UCthis + ["SPAWNED"]};
+
+if (KRON_UPS_Debug>0) then {player globalchat format["Spawning %3 copies of template %1",_template,_position,_copies,count KRON_UPS_TEMPLATES]};
+//if (KRON_UPS_Debug>0) then {diag_log format["Spawning %3 copies of template %1 on %2 templates %4",_template,_position,_copies,count KRON_UPS_TEMPLATES]};
+
+//Search if any template
+{
+ if ((_x select 0) == _template) then {
+ _side = _x select 1;
+ _membertypes = _x select 2;
+ _vehicletypes = _x select 3;
+ //Gets leader type
+ _unittype= _membertypes select 0;
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["template %1:%2 ",_template,_membertypes]};
+
+ for [{_i=1},{_i<=_copies},{_i=_i+1}] do {
+
+ // make the clones civilians
+ // use random Civilian models for single unit groups
+ if ((_unittype=="Civilian") && (count _members==1)) then {_rnd=1+round(random 20); if (_rnd>1) then {_unittype=format["Civilian%1",_rnd]}};
+
+ _grp=createGroup _side;
+
+ _lead = _grp createUnit [_unittype, _position, [], 0, "form"];
+ _lead setVehicleInit _initlstr;
+ [_lead] join _grp;
+ _grp selectLeader _lead;
+ sleep 1;
+
+ // copy team members (skip the leader)
+ _c=0;
+ {
+ _c=_c+1;
+ if (_c>1) then {
+ _newpos = _position findEmptyPosition [10, 200];
+ sleep .4;
+ if (count _newpos <= 0) then {_newpos = _position};
+ _newunit = _grp createUnit [_x, _newpos, [],0,"form"];
+ _newunit setVehicleInit _initstr;
+ [_newunit] join _grp;
+ };
+ } foreach _membertypes;
+
+
+ {
+ _newpos = _position findEmptyPosition [10, 200];
+ sleep .4;
+ if (count _newpos <= 0) then {_newpos = _position};
+ _newunit = _x createvehicle (_newpos);
+ } foreach _vehicletypes;
+
+ //Set new parameters
+ _params = [_lead] + _UCthis;
+
+ //Exec UPSMON script
+ _params SPAWN UPSMON;
+
+ processInitCommands;
+ };
+ };
+}foreach KRON_UPS_TEMPLATES;
+
+if (true) exitwith{};
diff --git a/Server/Module/UPSMON/UPSMON/MON_surrended.sqf b/Server/Module/UPSMON/UPSMON/MON_surrended.sqf new file mode 100644 index 0000000..15c4ee7 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/MON_surrended.sqf @@ -0,0 +1,23 @@ +// =========================================================================================================
+// Script for adding the action of follow player.
+// Version: 1.0
+// Author: Monsada (smirall@hotmail.com)
+// ---------------------------------------------------------------------------------------------------------
+private ["_side","_soldiers"];
+_side = _this select 0;
+
+_soldiers = switch (_side) do {
+ case west: {KRON_AllWest};
+ case east: {KRON_AllEast};
+ case resistance: {KRON_AllRes};
+};
+
+{
+ if ( leader _x == _x ) then {
+ _x addaction ["Order your men to follow me", "scripts\UPSMON\actions\followme.sqf", [], 1, false];
+ } else {
+ _x addaction ["Follow me", "scripts\UPSMON\actions\followme.sqf", [], 1, false];
+ };
+}foreach _soldiers;
+
+if (true) exitWith {};
diff --git a/Server/Module/UPSMON/UPSMON/actions/followme.sqf b/Server/Module/UPSMON/UPSMON/actions/followme.sqf new file mode 100644 index 0000000..1d325c5 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/actions/followme.sqf @@ -0,0 +1,93 @@ +// =========================================================================================================
+// Script for action follow me when surrended, adds the soldier to player squad in a random choice.
+// Version: 1.0
+// Author: Monsada (smirall@hotmail.com)
+// ---------------------------------------------------------------------------------------------------------
+private ["_obj","_caller","_id","_objtype","_rnd","_join","_direction"];
+_npc = _this select 0;
+_caller = _this select 1;
+_id = _this select 2;
+
+_rnd = 0;
+_join=true;
+_npc switchmove "";
+
+_direction = ((getpos _caller select 0) - (getpos _npc select 0)) atan2 ((getpos _caller select 1) - (getpos _npc select 1));
+
+//If positive values are needed then use:
+if(_direction < 0) then {_direction = _direction + 360};
+_npc setdir _direction;
+_npc dowatch _caller;
+_npc setSpeedMode "LIMITED";
+_npc domove position _caller;
+
+
+sleep 0.5;
+
+_rnd = random 100;
+_npc setmimic "Sad";
+
+if (_rnd <= 30 ) then {
+ _npc globalchat "Ok";
+};
+
+if (_rnd > 30 && _rnd <= 50) then {
+ _npc globalchat "Yes";
+};
+
+
+if (_rnd > 50 && _rnd <= 100) then {
+ _join=false;
+ _rnd = random 100;
+
+ if (_rnd < 20) then {
+ _npc setmimic "angry";
+ _npc switchmove "CtsPercMstpSnonWnonDnon_idle31rejpaniVnose";
+ _npc globalchat "Kiss my ass";
+ };
+
+ if (_rnd > 20 && _rnd <= 40) then {
+ _npc setmimic "Agresive";
+ _npc switchmove "CtsPercMstpSnonWnonDnon_idle33rejpaniVzadku";
+ sleep 3;
+ _npc globalchat "Que te den";
+ };
+
+ if (_rnd > 40 && _rnd <= 60) then {
+ _npc setmimic "Agresive";
+ _npc switchmove "CtsPercMstpSnonWnonDnon_idle33rejpaniVzadku";
+ sleep 1;
+ _npc globalchat "Fuck you";
+ };
+
+ if (_rnd > 60 && _rnd <= 80) then {
+ _npc setmimic "Agresive";
+ _npc switchmove "CtsPercMstpSnonWnonDnon_idle32podrbaniNanose";
+ sleep 0.5;
+ _npc globalchat "Follow your mother";
+ };
+
+ if (_rnd > 80 && _rnd <= 100) then {
+ _npc setmimic "angry";
+ sleep 0.1;
+ _npc switchmove "CtsPercMstpSnonWnonDnon_idle32podrbaniNanose";
+ _npc globalchat "Fuck you";
+ };
+};
+
+if (_join) then {
+ // remove the action once it is activated
+ _npc stop false;
+ if (_npc == leader _npc) then {
+ _npc globalchat "All follow that man";
+ {
+ _x switchmove "";
+ [_x] joinSilent _caller;
+ }foreach units _npc;
+ } else {
+ _npc removeAction _id;
+ [_npc] joinSilent _caller;
+ };
+};
+
+if (true) exitWith {};
diff --git a/Server/Module/UPSMON/UPSMON/common/MON_functions.sqf b/Server/Module/UPSMON/UPSMON/common/MON_functions.sqf new file mode 100644 index 0000000..8adf336 --- /dev/null +++ b/Server/Module/UPSMON/UPSMON/common/MON_functions.sqf @@ -0,0 +1,2204 @@ +// =========================================================================================================
+// Biblioteca de funciones comunes
+// Version: 5.1.0
+// Author: Monsada (smirall@hotmail.com)
+// http://www.simulacion-esp.com/
+// Comunidad Hispana de Simulación
+// =========================================================================================================
+
+MON_bugged_vehicles = ["BIS_alice_emptydoor","ACE_Grenade_Geometry"];
+
+// in Vanilia extra bugged vehicle
+if !(AcePresent) then {
+ MON_bugged_vehicles = MON_bugged_vehicles + ["HMMWV_M998A2_SOV_DES_EP1"];
+};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que permite posicionar objetos a la altura definida
+//param1: objeto
+//param2: altura
+MON_subir = {
+if (!isserver) exitwith{};
+private ["_object","_altura","_pos","_x","_y","_z","_bld","_bldpos"];
+
+_object = _this select 0;
+_altura = _this select 1;
+
+_x = 0;
+_y = 0;
+_z = 0;
+_pos =0;
+_bld = objnull;
+_bldpos =0;
+
+_pos = getposasl _object;
+
+_x = _pos select 0;
+_y = ( _pos select 1 );
+_z = ( _pos select 2 ) + _altura;
+_object setposasl [_x,_y ,_z];
+};
+//Retorna la dirección entre dos posiciones
+MON_getDirPos = {private["_a","_b","_from","_to","_return"]; _from = _this select 0; _to = _this select 1; _return = 0; _a = ((_to select 0) - (_from select 0)); _b = ((_to select 1) - (_from select 1)); if (_a != 0 || _b != 0) then {_return = _a atan2 _b}; if ( _return < 0 ) then { _return = _return + 360 }; _return};
+// ---------------------------------------------------------------------------------------------------------
+//Función de borra unidades que han sido matadas
+//param1: objeto a borrar cuando muera
+//param2: tiempo a esperar antes de borrar el objeto
+MON_deleteDead = {private["_u","_s"];_u=_this select 0; _s= _this select 1; _u removeAllEventHandlers "killed"; sleep _s; deletevehicle _u};
+MON_deleteDeadDist = {private["_u","_s","_dist","_OCercanos","_cicle","_deleted","_isplayer"];
+ _i = 0;
+ _cicle = 10;
+ _deleted = false;
+ _isplayer = false;
+ _u = _this select 0; _s = _this select 1; _dist = _this select 2;
+ _u removeAllEventHandlers "killed";
+ sleep _s;
+
+ while {!_deleted} do {
+ _isplayer = false;
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_u, ["Man"] , _dist];
+
+ //Validamos si alguno de los soldados cerca es un jugador y está vivo
+ {if (isplayer _x && alive _x) exitwith {_isplayer = true;}}foreach _OCercanos;
+
+ if (!_isplayer) then {
+ deletevehicle _u;
+ _deleted = true;
+ };
+ sleep _cicle;
+ };
+};
+// ---------------------------------------------------------------------------------------------------------
+//Función tomada de UPS, busca el comando en la lista y devuelve el siguiente elemento
+//param1: comando a buscar
+//param2: valor por defecto del comando
+//param3: array con los comandos
+//Retorna valor del comando encontrado o valor por defecto
+MON_getArg = {private["_cmd","_arg","_list","_a","_v"]; _cmd=_this select 0; _arg=_this select 1; _list=_this select 2; _a=-1; {_a=_a+1; _v=format["%1",_list select _a];
+if (_v==_cmd) then {_arg=(_list select _a+1)}} foreach _list; _arg};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve una posición en 3D a partir de otra, una dirección y una distancia
+//param1: posición
+//param2: dirección
+//param3: distancia
+//Retorna vector de posicion en 3D [0,0,0]
+MON_GetPos =
+{
+ private ["_pos","_dir","_dist","_cosU","_cosT","_relTX","_sinU","_sinT","_relTY","_newPos","_newPosX","_newPosY", "_targetZ" ];
+ _pos = _this select 0;
+ _dir = _this select 1;
+ _dist = _this select 2;
+
+ _targetX = _pos select 0; _targetY = _pos select 1; _targetZ = _pos select 2;
+
+ //Calculamos posición
+ _cosU = [_dir] call MON_GetCOS; _sinU = [_dir] call MON_GetSIN;
+ _cosT = abs cos(_dir); _sinT = abs sin(_dir);
+ _relTX = _sinT * _dist * _cosU; _relTY = _cosT * _dist * _sinU;
+ _newPosX = _targetX + _relTX; _newPosY = _targetY + _relTY;
+ _newPos = [_newPosX,_newPosY,_targetZ];
+ _newPos;
+};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve una posición en 2D a partir de otra, una dirección y una distancia
+//param1: posición
+//param2: dirección
+//param3: distancia
+//Retorna vector de posicion en 2D [0,0]
+MON_GetPos2D =
+{
+ private ["_pos","_dir","_dist","_cosU","_cosT","_relTX","_sinU","_sinT","_relTY","_newPos","_newPosX","_newPosY" ];
+ _pos = _this select 0;
+ _dir = _this select 1;
+ _dist = _this select 2;
+
+ _targetX = _pos select 0; _targetY = _pos select 1;
+
+ //Calculamos posición
+ _cosU = [_dir] call MON_GetCOS; _sinU = [_dir] call MON_GetSIN;
+ _cosT = abs cos(_dir); _sinT = abs sin(_dir);
+ _relTX = _sinT * _dist * _cosU; _relTY = _cosT * _dist * _sinU;
+ _newPosX = _targetX + _relTX; _newPosY = _targetY + _relTY;
+ _newPos = [_newPosX,_newPosY];
+ _newPos;
+};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve las posiciones que se pueden ocupar dentro de un edificio
+//param1: objeto location
+//Retorna numero de posiciones que tiene el edificio
+MON_BldPos = {private ["_bld","_bldpos"];
+ _bld=_this; _bldpos = 1;
+ while {format ["%1", _bld buildingPos _bldpos] != "[0,0,0]"} do {_bldpos = _bldpos + 1;};
+ _bldpos = _bldpos - 1; _bldpos;};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve la casa que hay más cerca del objeto param1 y las posiciones que se pueden ocupar dentro de ella.
+//param1: objeto
+//Retorna vector con [objeto location, posiciones que tiene]
+MON_PosInfo = {
+ private["_obj","_bld","_bldpos"];
+ _obj=_this;
+ _bld = nearestbuilding _obj;
+ _bldpos= _bld call MON_BldPos;
+ [_bld,_bldpos];
+ };
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve el valor negativo o positivo del seno en base a un angulo
+MON_GetSIN = {
+ private["_dir","_sin","_cos"];
+ _dir=_this select 0;
+ if (_dir<90) then
+ {
+ _sin=1;
+ } else
+ {
+ if (_dir<180) then
+ {
+ _sin=-1;
+ } else
+ {
+ if (_dir<270) then
+ {
+ _sin=-1;
+ }
+ else
+ {
+ _sin=1;
+ };
+ };
+ };
+ _sin
+};
+
+// ---------------------------------------------------------------------------------------------------------
+//Función que devuelve el valor negativo o positivo del coseno en base a un angulo
+MON_GetCOS = {
+ private["_dir","_cos"];
+ _dir=_this select 0;
+ if (_dir<90) then
+ {
+ _cos=1;
+ } else
+ {
+ if (_dir<180) then
+ {
+ _cos=1;
+ } else
+ {
+ if (_dir<270) then
+ {
+ _cos=-1;
+ }
+ else
+ {
+ _cos=-1;
+ };
+ };
+ };
+ _cos
+};
+
+//Función que busca vehiculos cercanos y hace entrar a las unidades del lider
+//Parámeters: [_grpid,_npc]
+// <- _grpid: id of group to assign to vehicle
+// <- _npc: lider
+// -> _getin: true if any getin
+MON_GetIn_NearestVehicles = {
+ private["_vehicles","_npc","_units","_unitsIn","_grpid","_getin"];
+ _grpid = _this select 0;
+ _npc = _this select 1;
+
+ _vehicles=[[]];
+ _air=[[]];
+ _units = [];
+ _unitsIn = [];
+ _getin=false;
+
+ if (leader _npc == _npc) then {
+ _units = units _npc;
+ } else
+ {
+ _units = _units + [_npc];
+ };
+
+ {
+ if ( (_x!= vehicle _x && !((vehicle _x) iskindof "StaticWeapon" )) || !(_x iskindof "Man") || !alive _x || !canmove _x || !canstand _x) then {_units = _units-[_x];};
+ }foreach _units;
+
+ _unitsIn = _units;
+
+ //First catch combat vehicles
+ if ( (count _units) > 0) then {
+ _air = [_npc,200] call MON_NearestsAirTransports;
+ {if (_npc knowsabout (_x select 0) <= 0.5) then{ _air = _air - [_x]};}foreach _air;
+ _units = [_grpid, _units, _air, false] call MON_selectvehicles;
+ };
+ sleep 0.05;
+ if ( (count _units) > 1) then {
+ _vehicles = [_npc,200,true] call MON_NearestsLandCombat;
+ {if (_npc knowsabout(_x select 0) <= 0.5) then{ _vehicles = _vehicles - [_x]};}foreach _vehicles;
+ _units = [_grpid, _units, _vehicles, false] call MON_selectvehicles;
+ };
+ sleep 0.05;
+ if ( (count _units) > 0) then {
+ _vehicles = [_npc,200] call MON_NearestsLandTransports;
+ {if (_npc knowsabout (_x select 0) <= 0.5) then{ _vehicles = _vehicles - [_x]};}foreach _vehicles;
+ _units = [_grpid, _units, _vehicles, false] call MON_selectvehicles;
+ };
+ sleep 0.05;
+ if ( (count _units) > 0 && (count _vehicles) > 0) then {
+ sleep 1;
+ _vehicles = _vehicles + _air;
+ _units = [_grpid, _units, _vehicles, true] call MON_selectvehicles;
+ };
+ sleep 0.05;
+ _unitsIn = _unitsIn - _units;
+
+ _unitsIn;
+ //sleep 0.05;
+};
+
+//Función que busca vehiculos cercanos y hace entrar a las unidades del lider
+//Parámeters: [_grpid,_npc]
+// <- _grpid: id of group to assign to vehicle
+// <- _npc: lider
+// -> _getin: true if any getin
+MON_GetIn_NearestCombat = {
+ private["_vehicles","_npc","_units","_unitsIn","_grpid","_getin","_dist","_all"];
+ _grpid = _this select 0;
+ _npc = _this select 1;
+ _dist = _this select 2;
+ _all = _this select 3;
+
+ _vehicles=[[]];
+ _units = [];
+ _unitsIn = [];
+ _getin=false;
+
+ if (leader _npc == _npc) then {
+ _units = units _npc;
+ } else
+ {
+ _units = _units + [_npc];
+ };
+
+ {
+ if ( (_x!= vehicle _x && !((vehicle _x) iskindof "StaticWeapon" )) || !(_x iskindof "Man") || !alive _x || !canmove _x || !canstand _x) then {_units = _units-[_x];};
+ }foreach _units;
+
+ //If suficient units leader will not get in
+ if (!all) then {
+ if (count _units > 2 ) then {_units = _units - [leader _npc]};
+ };
+
+ _unitsIn = _units;
+
+ //We need 2 units available if not any leave vehicle to another squad
+ if ( (count _units) > 1) then {
+ _vehicles = [_npc,_dist,_all] call MON_NearestsAirCombat;
+ {if (_npc knowsabout (_x select 0) <= 0.5) then{ _vehicles = _vehicles - [_x]};}foreach _vehicles;
+ _units = [_grpid, _units, _vehicles, false] call MON_selectvehicles;
+ };
+ sleep 0.05;
+
+ if ( (count _units) > 1) then {
+ _vehicles = [_npc,_dist,_all] call MON_NearestsLandCombat;
+ {if (_npc knowsabout(_x select 0) <= 0.5) then{ _vehicles = _vehicles - [_x]};}foreach _vehicles;
+ _units = [_grpid, _units, _vehicles, false] call MON_selectvehicles;
+ };
+
+ _unitsIn = _unitsIn - _units;
+
+ _unitsIn;
+};
+
+//Función que busca vehiculos cercanos y hace entrar a las unidades del lider
+//Parámeters: [_grpid,_npc]
+// <- _grpid: id of group to assign to vehicle
+// <- _npc: lider
+// -> _getin: true if any getin
+MON_GetIn_NearestBoat = {
+ private["_vehicles","_npc","_units","_unitsIn","_grpid","_getin","_dist"];
+ _grpid = _this select 0;
+ _npc = _this select 1;
+ _dist = _this select 2;
+
+ _vehicles=[[]];
+ _units = [];
+ _unitsIn = [];
+ _getin=false;
+
+ if (leader _npc == _npc) then {
+ _units = units _npc;
+ } else
+ {
+ _units = _units + [_npc];
+ };
+
+ {
+ if ( (_x!= vehicle _x && !((vehicle _x) iskindof "StaticWeapon" )) || !(_x iskindof "Man") || !alive _x || !canmove _x || !canstand _x) then {_units = _units-[_x];};
+ }foreach _units;
+
+ _unitsIn = _units;
+
+ //We need 2 units available if not any leave vehicle to another squad
+ if ( (count _units) > 0) then {
+ _vehicles = [_npc,_dist] call MON_Nearestsboats;
+ {if (_npc knowsabout (_x select 0) <= 0.5) then{ _vehicles = _vehicles - [_x]};}foreach _vehicles;
+ _units = [_grpid, _units, _vehicles, false] call MON_selectvehicles;
+ };
+
+ if ( (count _units) > 1 && (count _vehicles) > 0) then {
+ sleep 1;
+ _units = [_grpid, _units, _vehicles, true] call MON_selectvehicles;
+ };
+
+ _unitsIn = _unitsIn - _units;
+ _unitsIn;
+};
+
+//Función que busca staticos cercanos y hace entrar a las unidades del lider
+//Parámeters: [_grpid,_npc]
+// <- _grpid: id of group to assign to vehicle
+// <- _npc: lider
+// -> _getin: true if any getin
+MON_GetIn_NearestStatic = {
+ private["_vehicles","_npc","_units","_unitsIn","_grpid","_getin","_count"];
+ _grpid = _this select 0;
+ _npc = _this select 1;
+ _count = 0;
+ _distance = 100;
+ if ((count _this) > 2) then {_distance = _this select 2;};
+
+ _vehicles=[];
+ _units = [];
+ _unitsIn = [];
+ _getin=false;
+
+ //Buscamos staticos cerca
+ _vehicles = [_npc,_distance] call MON_NearestsStaticWeapons;
+
+ if ( count _vehicles == 0) exitwith {_unitsIn;};
+
+ if (leader _npc == _npc) then {
+ _units = (units _npc) - [_npc];
+ } else
+ {
+ _units = _units + [_npc];
+ };
+
+ //Solo tomamos las unidades vivas y que no estén en vehiculo
+ {
+ if ( (_x iskindof "Man") && _x == vehicle _x && alive _x && canmove _x && canstand _x) then {
+ _unitsIn = _unitsIn + [_x];
+ };
+ }foreach _units;
+
+ //Intentamos tomar solo las que estén disponibles
+ _units = [];
+ {
+ if (unitready _x) then {
+ _units = _units + [_x];
+ };
+ }foreach _unitsin;
+
+ //Si hay unidades disponibles las usamos
+ if (count _units > 0) then {
+ _unitsIn = _units;
+ };
+
+ //if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: Found %2 estatic weapons %3 men available",_grpid,count _vehicles, count _unitsIn]};
+
+ _units = _unitsIn;
+ if ( count _unitsIn > 0) then {
+ _units = [_grpid, _units, _vehicles, true] call MON_selectvehicles;
+ };
+
+ _unitsIn = _unitsIn - _units;
+
+ _unitsIn;
+};
+
+//Function to assign units to vehicles
+//Parámeters: [_grpid,_unitsin,_vehicle]
+// <- _grpid: id of group to assign to vehicle
+// <- _units: array of units to getin
+// <- _vehicles: array of vehicles to use
+// -> _untis: array of units getin
+ MON_selectvehicles = {
+ private["_vehicles","_emptypositions","_units","_unitsIn","_i","_grpid","_vehgrpid","_unit","_wp","_any","_index","_cargo"];
+ _grpid = _this select 0;
+ _units = _this select 1;
+ _vehicles = _this select 2;
+ _any = _this select 3; //meter en cualquier vehiculo
+
+ _wp = [];
+ _vehicle = [];
+ _unitsIn = [];
+ _emptypositions = 0;
+ _i = 0;
+ _vehgrpid = 0;
+ _unit = objnull;
+ _index = 0;
+ _cargo = [];
+
+ {
+ if ((count _units) == 0 ) exitwith {};
+
+ _vehicle = _x select 0 ;
+ _emptypositions = _x select 1;
+ _unitsIn = [];
+ _i = 0;
+ _vehgrpid = _vehicle getvariable ("UPSMON_grpid");
+ _cargo = _vehicle getvariable ("UPSMON_cargo");
+ if ( isNil("_vehgrpid") ) then {_vehgrpid = 0;};
+ if ( isNil("_cargo") ) then {_cargo = [];};
+
+ //Asignamos el vehiculo a a la escuadra si contiene las posiciones justas
+ if (_vehgrpid == 0) then {
+ _vehicle setVariable ["UPSMON_grpid", _grpid, false];
+ _vehicle setVariable ["UPSMON_cargo", _unitsIn, false];
+ _vehgrpid = _grpid;
+ };
+
+ {
+ if (!alive _x || !canmove _x) then {_cargo = _cargo - [_x]; };
+ }foreach _cargo;
+
+ _emptypositions = _emptypositions - (count _cargo - count ( crew _vehicle) );
+
+
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1 %2 positions=%3 cargo=%4 crew=%5",_grpid, typeof _vehicle, _emptypositions, count _cargo,count (crew _vehicle)]};
+ //ahora buscamos en cualquier vehiculo
+ if ( _vehgrpid == _grpid || (_emptypositions > 0 && _any)) then {
+
+ while {_i < _emptypositions && _i < count _units} do
+ {
+ _unit = _units select _i;
+ _unitsIn = _unitsIn + [_unit];
+ _i = _i + 1;
+ };
+ _units = _units - _unitsIn;
+
+ if ( (count _unitsIn) > 0) then {
+ //Metemos las unidades en el vehiculo
+ [_grpid,_unitsIn,_vehicle] spawn MON_UnitsGetIn;
+ if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: Get in %2 %3 units of %4 available",_grpid,typeof _vehicle,count _unitsIn,_emptypositions]};
+ //if (KRON_UPS_Debug>0 ) then {diag_log format["%1: Moving %3 units into %2 with %4 positions",_grpid,typeof _vehicle,count _unitsIn,_emptypositions]};
+ };
+ };
+ _index = _index + 1;
+ sleep 0.05;
+ } foreach _vehicles;
+
+ _units;
+ };
+
+
+//Funcion que mete la tropa en el vehiculo
+//Parámeters: [_grpid,_unitsin,_vehicle]
+// <- _grpid: id of group to assign to vehicle
+// <- _unitsin: array of units to getin
+// <- _vehicle
+MON_UnitsGetIn = {
+ private["_grpid","_vehicle","_npc","_driver","_gunner", "_unitsin", "_units" , "_Commandercount","_Drivercount","_Gunnercount","_cargo",
+ "_Cargocount","_emptypositions","_commander","_vehgrpid","_cargo"];
+
+ _grpid = _this select 0;
+ _unitsin = _this select 1;
+ _vehicle = _this select 2;
+
+ _units = _unitsin;
+ _driver = objnull;
+ _gunner = objnull;
+ _commander = objnull;
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+ _cargo = [];
+
+ _Cargocount = (_vehicle) emptyPositions "Cargo";
+ _Gunnercount = (_vehicle) emptyPositions "Gunner";
+ _Commandercount = (_vehicle) emptyPositions "Commander";
+ _Drivercount = (_vehicle) emptyPositions "Driver";
+
+ //Obtenemos el identificador del vehiculo
+ _vehgrpid = _vehicle getvariable ("UPSMON_grpid");
+ _cargo = _vehicle getvariable ("UPSMON_cargo");
+ if ( isNil("_vehgrpid") ) then {_vehgrpid = 0;};
+ if ( isNil("_cargo") ) then {_cargo = [];};
+
+ _cargo = _cargo - _unitsin; //Para evitar duplicados
+ _cargo = _cargo + _unitsin; //Ańadimos a la carga
+ _vehicle setVariable ["UPSMON_cargo", _cargo, false];
+
+ //Hablitamos a la IA para entrar en el vehiculo
+ {
+ [_x,0] call MON_dostop;
+
+ if ("StaticWeapon" countType [vehicle (_x)]>0) then
+ {
+ _x spawn MON_doGetOut;
+ };
+
+ unassignVehicle _x;
+ _x spawn MON_Allowgetin;
+ }foreach _units;
+
+ //Assigned to the leader as commander or cargo
+ {
+ if ( _vehgrpid == _grpid && _x == leader _x && _Commandercount > 0 ) exitwith
+ {
+ _Commandercount = 0;
+ _commander = _x;
+ _commander assignAsCommander _vehicle;
+ _units = _units - [_x];
+ [_x] orderGetIn true;
+ };
+
+ if ( _x == leader _x && _Cargocount > 0 ) exitwith
+ {
+ _x assignAsCargo _vehicle;
+ _units = _units - [_x];
+ _Cargocount = _Cargocount - 1;
+ [_x] orderGetIn true;
+ };
+ }foreach _units;
+ //if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: _vehgrpid %2 ,_Gunnercount %3, %4",_grpid,_vehgrpid,_Gunnercount,count _units]};
+
+ //Si el vehiculo pertenece al grupo asignamos posiciones de piloto, sinó solo de carga
+ if ( _vehgrpid == _grpid ) then {
+
+ //Asignamos el conductor
+ if ( _Drivercount > 0 && count (_units) > 0 ) then {
+ _driver = _units select (count _units - 1);
+ [_driver,_vehicle,0] spawn MON_assignasdriver;
+ _units = _units - [_driver];
+ };
+
+ //Asignamos el artillero
+ if ( _Gunnercount > 0 && count (_units) > 0 ) then {
+ _gunner = [_vehicle,_units] call MON_getNearestSoldier;
+ [_gunner,_vehicle] spawn MON_assignasgunner;
+ _units = _units - [_gunner];
+ };
+ };
+
+ //if (KRON_UPS_Debug>0 ) then {player sidechat format["%1: _vehgrpid=%2 units=%4",_grpid,_vehgrpid,_cargocount,count _units]};
+ //Movemos el resto como carga
+ if ( _Cargocount > 0 && count (_units) > 0 ) then {
+ {
+ _x assignAsCargo _vehicle;
+ [_x] orderGetIn true;
+ sleep 0.05;
+ } forEach _units;
+ };
+
+ {
+ [_x] spawn MON_avoidDissembark;
+ } forEach _unitsin - [_driver] - [_gunner] -[_commander];
+
+};
+
+MON_getNearestSoldier = {
+ private["_units","_obj","_near"];
+
+ _obj = _this select 0;
+ _units = _this select 1;
+
+ _near = objnull;
+
+ {
+ if (isnull _near) then {
+ _near = _x;
+ } else {
+ if ( _x distance _obj < _near distance _obj ) then {_near = _x;};
+ };
+ }foreach _units;
+ _near;
+};
+
+MON_avoidDissembark = {
+ private["_npc","_vehicle","_timeout"];
+
+ _npc = _this select 0;
+ _vehicle = vehicle _npc ;
+
+ _timeout = 120;
+ _timeout = time + _timeout;
+
+ while {_npc == vehicle _npc && alive _npc && canmove _npc && time < _timeout} do {
+ sleep 1;
+ };
+
+ if (!alive _npc || !canmove _npc || time >= _timeout || driver vehicle _npc == _npc) exitwith{};
+ _npc stop true;
+
+ while {_npc != vehicle _npc && alive _npc && canmove _npc} do {sleep 1;};
+ _npc stop false;
+ sleep 0.5;
+
+ if (!alive _npc || !canmove _npc) exitwith{};
+};
+
+
+//Función que devuelve un vehiculo de transporte cercano
+//Parámeters: [_npc]
+// <- _npc: object for position search
+// -> _vehicle: vehicle
+MON_NearestLandTransport = {
+ private["_vehicle","_npc","_transportSoldier","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount"];
+
+ _npc = _this;
+
+ _OCercanos = [];
+ _transportSoldier = 0;
+ _vehicle = objnull;
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Car","TANK","Truck","Motorcycle"] , 150];
+
+ {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Commandercount = (_x) emptyPositions "Commander";
+ _Drivercount = (_x) emptyPositions "Driver";
+
+ _transportSoldier = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && canMove _x && _transportSoldier >= count (units _npc) && !(typeof _x in MON_bugged_vehicles)
+ && (_drivercount > 0 || side _npc == side _x )) exitwith {_vehicle = _x;};
+ }foreach _OCercanos;
+
+ _vehicle;
+};
+
+//Función que devuelve un array con los vehiculos terrestres más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_NearestsLandTransports = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Car","TANK","Truck","Motorcycle"] , _distance];
+
+ {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Commandercount = (_x) emptyPositions "Commander";
+ _Drivercount = (_x) emptyPositions "Driver";
+
+ _emptypositions = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && _emptypositions > 0 && canMove _x && !(typeof _x in MON_bugged_vehicles)
+ && (_drivercount > 0 || side _npc == side _x )) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+
+ _vehicles;
+};
+
+//Función que devuelve un array con los vehiculos terrestres más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_NearestsLandCombat = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance","_all"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+ _all = _this select 2;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Car","TANK","Truck","Motorcycle"] , _distance];
+
+ {
+ if (_all) then {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ };
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Drivercount = (_x) emptyPositions "Driver";
+ _Commandercount = (_x) emptyPositions "Commander";
+
+ _emptypositions = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && _Gunnercount > 0 && canMove _x && !(typeof _x in MON_bugged_vehicles)
+ && (_drivercount > 0 || side _npc == side _x )) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+
+ _vehicles;
+};
+
+//Función que devuelve un array con los vehiculos aereos más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_NearestsAirTransports = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Helicopter"] , _distance];
+
+ {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Commandercount = (_x) emptyPositions "Commander";
+ _Drivercount = (_x) emptyPositions "Driver";
+
+ _emptypositions = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && _emptypositions > 0 && canMove _x && !(typeof _x in MON_bugged_vehicles)
+ && (_drivercount > 0 || side _npc == side _x )) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+
+ _vehicles;
+};
+
+//Function that returns an array with the closest air vehicles
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_NearestsAirCombat = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance","_all"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+ _all = _this select 2;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Helicopter"] , _distance];
+
+ {
+ if (_all) then {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ };
+
+ // _Gunnercount = [_x] call RAF_numberOfTurrets;
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Drivercount = (_x) emptyPositions "Driver";
+ _Commandercount = (_x) emptyPositions "Commander";
+
+ _emptypositions = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && _Gunnercount > 0 && canMove _x && !(typeof _x in MON_bugged_vehicles)
+ && (_drivercount > 0 || side _npc == side _x )) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+ _vehicles //return
+};
+
+//Función que devuelve un array con los vehiculos staticos más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_NearestsStaticWeapons = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["StaticWeapon"] , _distance];
+
+ {
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _emptypositions = _Gunnercount;
+ if (!locked _x && alive _x && _emptypositions > 0 && !(typeof _x in MON_bugged_vehicles) ) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+
+ _vehicles //return
+ };
+
+//Función que devuelve un array con los vehiculos marinos más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_Nearestsboats = {
+ private["_vehicles","_npc","_emptypositions","_OCercanos","_driver", "_Commandercount","_Drivercount","_Gunnercount","_Cargocount","_distance"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+
+ _OCercanos = [];
+ _emptypositions = 0;
+ _vehicles = [];
+ _Cargocount = 0;
+ _Gunnercount = 0;
+ _Commandercount = 0;
+ _Drivercount = 0;
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Ship"] , _distance];
+
+ {
+ _Cargocount = (_x) emptyPositions "Cargo";
+ _Gunnercount = (_x) emptyPositions "Gunner";
+ _Commandercount = (_x) emptyPositions "Commander";
+ _Drivercount = (_x) emptyPositions "Driver";
+
+ _emptypositions = _Cargocount + _Gunnercount + _Commandercount + _Drivercount;
+
+ if (!locked _x && _emptypositions > 0 && canMove _x && (_drivercount > 0 || side _npc == side _x )) then { _vehicles = _vehicles + [[_x,_emptypositions]];};
+ }foreach _OCercanos;
+
+ _vehicles //return
+ };
+
+//Function to delay the taking of the steering wheel and the vehicle will not have time to rise and
+MON_assignasdriver = {
+ private["_vehicle","_driver","_wait"];
+ _driver = _this select 0;
+ _vehicle = _this select 1;
+ _wait = _this select 2;
+
+ [_driver,_wait] spawn MON_dostop;
+ sleep _wait;
+
+ unassignVehicle _driver;
+ _driver assignasdriver _vehicle;
+ [_driver] orderGetIn true;
+
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: assigning to driver of %2 ",_driver, typeof _vehicle]};
+};
+
+MON_assignasgunner = {
+ private["_vehicle","_gunner","_dist"];
+ _gunner = _this select 0;
+ _vehicle = _this select 1;
+ _dist=0;
+
+ _gunner assignasgunner _vehicle;
+ [_gunner] orderGetIn true;
+
+ waituntil { _gunner != vehicle _gunner || !alive _gunner || !canmove _gunner ||!alive _vehicle || !canfire _vehicle};
+
+ if ( alive _gunner && alive _vehicle && canmove _gunner && canfire _vehicle) then {
+ _dist = _gunner distance _vehicle;
+ if (_dist < 3) then {
+ _gunner moveInTurret [_vehicle, [0]] ;
+ };
+ };
+};
+
+
+//Allow getin
+MON_Allowgetin = {
+ //Hablitamos a la IA para entrar en el vehiculo
+ [_this] allowGetIn true;
+};
+
+
+//If every on is outside, make sure driver can move
+ MON_checkleaveVehicle={
+ _npc = _this select 0;
+ _vehicle = _this select 1;
+ _driver = _this select 2;
+ _in = false;
+
+ //Take time to go all units
+ sleep 5;
+ {
+ if (_x != vehicle _x) then {_in = true};
+ }foreach units _npc;
+
+
+ // if no one is inside
+ if (!_in) then {
+ _driver enableAI "MOVE";
+ sleep 1;
+ _driver stop false;
+ sleep 1;
+ _driver leaveVehicle _vehicle;
+ sleep 1;
+ };
+ };
+
+
+//Function for order a unit to exit if no gunner
+//Parámeters: [_npc]
+// <- _npc:
+MON_GetOut = {
+ private["_vehicle","_npc","_getout" ,"_gunner"];
+
+ _npc = _this;
+ _vehicle = vehicle (_npc);
+ _gunner = objnull;
+ _gunner = gunner _vehicle;
+
+ sleep 0.05;
+ if (!alive _npc) exitwith{};
+
+ //If no leave the vehicle gunner
+ if ( isnull _gunner || !alive _gunner || !canmove _gunner || (_gunner != _npc && driver _vehicle != _npc && commander _vehicle != _npc) ) then {
+ [_npc] allowGetIn false;
+ _npc spawn MON_doGetOut;
+ unassignVehicle _npc;
+
+ //sleep 0.2;
+ };
+ };
+
+//Function for order a unit to exit
+//Parámeters: [_npc]
+// <- _npc:
+MON_doGetOut = {
+ private["_vehicle","_npc","_getout" ,"_gunner","_groupOne","_timeout","_dir"];
+
+ _npc = _this;
+ _vehicle = vehicle (_npc);
+
+ sleep 0.05;
+ if (_vehicle == _npc) exitwith{};
+
+ //Wait until vehicle is stopped
+ waituntil {!alive _npc || !canmove _npc || !alive _vehicle || ( (abs(velocity _vehicle select 0)) <= 0.1 && (abs(velocity _vehicle select 1)) <= 0.1 )
+ || ( _vehicle iskindof "Air" && ((position _vehicle) select 2) <= 1)};
+
+ if (!alive _npc || !canmove _npc) exitwith{};
+ unassignVehicle _npc;
+ _npc action ["getOut", _vehicle];
+ doGetOut _npc;
+ [_npc] allowGetIn false;
+ nul = [_npc] spawn MON_cancelstop;
+
+ waituntil {!alive _npc || !canmove _npc || vehicle _npc == _npc};
+ if (!alive _npc || !canmove _npc) exitwith{};
+
+ if (leader _npc != _npc) then {
+ //Moves out with dispersion of 45ş
+ _dir = getDir _npc;
+ _dir = _dir + 45 - (random 90);
+ nul = [_npc,25,_dir] spawn MON_domove;
+ //if (KRON_UPS_Debug>0 ) then { player globalchat format["%1 Moving away from %2 %2ş",_npc, typeof _vehicle,_dir];};
+ };
+};
+
+//Function for exiting of heli
+//Parámeters: [_heli,_targetPos,_atdist]
+// <- _heli:
+// <- _targetPos: position for exiting(if no waypoint used)
+// <- _atdist: distance for doing paradrop or landing
+MON_doParadrop = {
+ if (KRON_UPS_Debug>0 ) then { player globalchat format["Mon_doParadrop started"];};
+ private["_heli","_npc","_getout" ,"_gunner","_targetpos","_helipos","_dist","_index","_grp","_wp","_targetPosWp","_targetP","_units","_crew","_timeout","_jumpers"];
+ _heli = _this select 0;
+ _targetPos = [0,0];
+ _atdist = 250;
+ _flyingheigh = KRON_UPS_flyInHeight;
+ _landonBeh = ["CARELESS","SAFE"];
+ _timeout=0;
+
+ //Gets optional parameters
+ if ((count _this) > 1) then {_targetPos = _this select 1;};
+ if ((count _this) > 2) then {_atdist = _this select 2;};
+ if ((count _this) > 3) then {_flyingheigh = _this select 3;};
+
+ _helipos = [0,0];
+ _targetposWp = [0,0];
+ _gunner = objnull;
+ _gunner = gunner _heli;
+ _dist = 1000000;
+ _index = 0;
+ _grp = GRPNULL;
+ _wp = [];
+ _units =[];
+ _crew =[];
+
+ waituntil {count crew _heli > 0 || !alive _heli || !canmove _heli};
+ _grp = group ((crew _heli) select 0);
+ _npc = leader ((crew _heli) select 0);
+ _units = units _npc;
+
+ while { (_dist >= _atdist || _dist < 10) && alive _heli && canmove _heli && count crew _heli > 0} do {
+ _heli flyInHeight _flyingheigh;
+
+
+ /*
+ //Take last waypoint
+ _index = (count waypoints _grp) - 1;
+ _wp = [_grp,_index];
+ _targetPosWp = waypointPosition _wp;
+ if (format ["%1", _targetPosWp] == "[0,0,0]") then {_targetPosWp = _targetPos};
+ */
+
+ _targetPosWp = _targetPos;
+
+ _helipos = position _heli;
+ _dist = round([_helipos,_targetPosWp] call KRON_distancePosSqr);
+ //if (KRON_UPS_Debug>0 ) then {player globalchat format["Goiing to drop zone _dist=%1, _atdist=%2", _dist, _atdist ];};
+ sleep 1;
+ };
+
+ if (!alive _heli || count crew _heli == 0) exitwith{};
+ _crew = crew _heli;
+
+ //Jump
+ if (((position _heli) select 2) >= 90 && !surfaceIsWater position _heli && (!(toupper (behaviour _npc) IN _landonBeh) || (random 100) < 20)) then {
+ //moving hely for avoiding stuck
+ if (KRON_UPS_Debug>0 ) then {_heli globalchat format["doing paradrop high %1 dist=%2",(position _heli) select 2,_dist,_atdist];};
+
+ _jumpers = [_heli] call R_FN_unitsInCargo;
+
+ //Do paradrop
+ {
+ if( (assignedVehicleRole _x) select 0 == "Cargo")then
+ {
+ unassignVehicle _x;
+ _x action ["EJECT", _heli] ;
+ _x stop false;
+ [_x] allowGetIn false;
+ [_x] spawn MON_ACE_Watersurvival;
+
+ };
+ sleep 0.5;
+ } forEach crew _heli;
+ [_heli,700] spawn MON_domove;
+
+ //Clear Hely vars
+ _heli setVariable ["UPSMON_grpid", 0, false];
+ _heli setVariable ["UPSMON_cargo", [], false];
+
+ // set orginal fly hight
+ // _flyingheigh = KRON_UPS_flyInHeight;
+ // _heli flyInHeight _flyingheigh;
+
+ //Waits until all units are down
+ _timeout = time + 60;
+ {
+ waituntil {(_x == vehicle _x ) || !alive _x || !canmove _x || isnull _x || time > _timeout};
+ //Fix bug of ACE that sometimes AI gets in stand animation
+ //_x switchMove "AmovPercMsprSlowWrflDf_AmovPpneMstpSrasWrflDnon_2";
+ } foreach _jumpers;
+
+
+ if ( _npc == vehicle _npc) then {
+ {
+ if (alive _x && canmove _x) then {
+ [_x] dofollow _npc;
+ };
+ } foreach units _npc;
+ };
+
+
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%1 after paradrop",_npc]};
+
+ if (alive _npc && canmove _npc) then {
+ _npc move _targetPosWp;
+ }else{
+ {if (alive _x && canmove _x) exitwith { _x move _targetPosWp;}}foreach _crew;
+ };
+
+ //If only pilot land heli
+ if (count crew _heli <=1) then {
+ [_heli] spawn MON_landHely;
+ };
+ } else {
+ //land
+
+ if ( ((position _heli) select 2) >= 60 && !surfaceIsWater _helipos && ((random 100)<20 || !canmove _heli || (toupper (behaviour _npc) IN _landonBeh))) then {
+ [_heli] spawn MON_landHely;
+
+ }
+ else {
+ If (alive _heli && canmove _heli && count crew _heli > 0) then {
+ if (KRON_UPS_Debug>0 ) then {_heli globalchat format["%1 failed paradrop, trying another time",typeof _heli];};
+ //Try another time
+ _heli flyInHeight _flyingheigh;
+ sleep 3;
+ [_heli, _targetPos, _atdist*1.5,_flyingheigh] spawn MON_doParadrop;
+ };
+ };
+ };
+};
+
+//Lands hely
+MON_landHely = {
+ private["_heli","_npc","_crew","_NearestEnemy","_timeout","_landing","_targetpos","_jumpers"];
+ _heli = _this select 0;
+ _crew =[];
+ _targetpos=[0,0];
+ _timeout = 0;
+ _landing = false;
+
+ sleep 0.05;
+ if (!alive _heli || !canmove _heli ) exitwith{};
+ _crew = crew _heli;
+ _npc = leader (_crew select 0);
+
+ //Checks hely is already landing
+ _landing = _heli getVariable "UPSMON_landing";
+ if (isnil ("_landing")) then {_landing=false; _heli setVariable ["UPSMON_landing", false, false];};
+ if (_landing) exitwith {};
+
+ //Orders to land heli
+ _heli land "LAND";
+ if (KRON_UPS_Debug>0 ) then {player globalchat format["%1 is landing",typeof _heli];};
+
+ //Puts a mark for knowing hely is landing
+ _heli setVariable ["UPSMON_landing", true, false];
+
+ //Waits for land position
+ waituntil {!alive _heli || toUpper(landResult _heli) != "NOTREADY" };
+ if (alive _heli && (toUpper(landResult _heli) == "NOTFOUND")) exitwith {
+ if (KRON_UPS_Debug>0 ) then { player globalchat format["%1 no landing zone, doing paradrop",typeof _heli];};
+ _heli setVariable ["UPSMON_landing", false, false];
+ [_heli] spawn MON_doparadrop;
+ };
+
+ //1rt try-Waits until velocity and heigh are good for getting out
+ _timeout = 60 + time;
+ waituntil {!alive _heli || time > _timeout || ((abs(velocity _heli select 2)) <= 1 && ((position _heli) select 2) <= 0.7)};
+
+ //2nd try-Waits until velocity and heigh are good for getting out
+ if (((position _heli) select 2) > 2 && ((position _heli) select 2) < 30 && !surfaceiswater position _heli) then {
+ _heli land "LAND";
+ _timeout = 30 + time;
+ waituntil {!alive _heli || time > _timeout || ((position _heli) select 2) > 30 || ( (abs(velocity _heli select 2)) <= 1 && ((position _heli) select 2) <= 0.7)};
+
+ //Failed landing doing paradrop
+ if ( ((position _heli) select 2) > 30) exitwith {
+ if (KRON_UPS_Debug>0 ) then { player globalchat format["%1 landing timeout, doing paradrop",typeof _heli];};
+ _heli setVariable ["UPSMON_landing", false, false];
+ sleep 5;
+ [_heli] spawn MON_doparadrop;
+ };
+ };
+
+ //Chechs if alive before continuing
+ if (!alive _heli) exitwith{};
+
+
+ //If there is pilot and gunner, get out only cargo
+ if ((!isnull gunner _heli) && (!isnull driver _heli)) then {
+ _jumpers = [_heli] call R_FN_unitsInCargo;
+ } else {
+ _jumpers = crew _heli;
+ };
+
+
+ //dogetout each of _jumpers
+ {
+ _x spawn MON_doGetOut;
+ sleep 0.5;
+ } forEach _jumpers;
+
+ _timeout = 20 + time;
+
+ //Waits until all getout of heli
+ {
+ waituntil {vehicle _x == _x || !canmove _x || !alive _x || movetofailed _x || time > _timeout };
+ } forEach _jumpers;
+
+ sleep 1;
+ _heli land "NONE";
+ sleep 1;
+ [_heli,700] spawn MON_domove;
+
+
+
+
+ // If leader alive sets combat mode
+ if (alive _npc && canmove _npc) then {
+ //Gets nearest known enemy for putting in combat mode
+ _NearestEnemy = _npc findNearestEnemy _npc;
+ if (!isnull _NearestEnemy ) then {
+ _npc setBehaviour "AWARE";
+ _groupOne = group _npc;
+ _groupOne setFormation "DIAMOND";
+ };
+
+ //Moves to current target Position
+ _grpid = _npc getvariable "UPSMON_grpid";
+ if !(isnil "_grpid") then {
+ _targetpos =(KRON_targetsPos select _grpid);
+ _npc move _targetpos;
+ if (KRON_UPS_Debug>0 ) then { player globalchat format["%1 landed, moving to %2 %3",_grpid,_targetpos,count KRON_targetsPos];};
+ };
+ };
+
+ //Quitamos el id al vehiculo para que pueda ser reutilizado
+ _heli setVariable ["UPSMON_grpid", 0, false];
+ _heli setVariable ["UPSMON_cargo", [], false];
+ _heli setVariable ["UPSMON_landing", false, false];
+};
+
+//Controls that heli not stoped flying
+MON_HeliStuckcontrol = {
+ private["_heli","_landing","_stuckcontrol","_dir1","_targetPos","_lastpos"];
+ _heli = _this select 0;
+
+ _landing = false;
+ _stuckcontrol = false;
+ _targetPos=[0,0,0];
+ _dir1 = 0;
+
+ sleep 0.05;
+ if ( !alive _heli || !canmove _heli ) exitwith{};
+
+ //Checks stuckcontrol not active
+ _stuckcontrol = _heli getVariable "UPSMON_stuckcontrol";
+ if (isnil ("_stuckcontrol")) then {_stuckcontrol=false};
+ if (_stuckcontrol) exitwith {};
+
+ _heli setVariable ["UPSMON_stuckcontrol", true, false];
+ //if (KRON_UPS_Debug>0 ) then {player globalchat format["%1 stuck control begins",typeof _heli];};
+
+ //Stuck loop control
+ while {(alive _heli) && (count crew _heli) > 0 } do {
+ sleep 5;
+ if ((abs(velocity _heli select 0)) <= 5 && (abs(velocity _heli select 1)) <= 5 && (abs(velocity _heli select 2)) <= 5 && ((position _heli) select 2) >= 30) then {
+
+ _landing = _heli getVariable "UPSMON_landing";
+ if (isnil ("_landing")) then {_landing=false;};
+
+ if (!_landing) then {
+ //moving hely for avoiding stuck
+ [_heli,800] spawn MON_domove;
+ if (KRON_UPS_Debug>0 ) then {player GLOBALCHAT format["%1 stucked at %2m height, moving",typeof _heli,(position _heli) select 2];};
+ sleep 25;
+ };
+ };
+ };
+ //if (KRON_UPS_Debug>0 ) then {player globalchat format["%1 exits from stuck control",typeof _heli];};
+ _heli setVariable ["UPSMON_stuckcontrol", false, false];
+};
+
+//Function that checks is gunner is alive, if not moves a cargo
+MON_Gunnercontrol = {
+ private["_vehicle","_gunnercontrol","_hasgunner","_crew","_crew2"];
+ _vehicle = _this select 0;
+
+ _targetPos=[0,0,0];
+ _dir1 = 0;
+ _gunnercontrol = false;
+ _hasgunner = (_vehicle) emptyPositions "Gunner" > 0 || !isnull gunner _vehicle;
+ _crew = [];
+ _crew2 = []; //Without driver and gunner
+
+ sleep 0.05;
+ if ( !alive _vehicle || !canmove _vehicle ) exitwith{};
+
+ //Checks stuckcontrol not active
+ _gunnercontrol = _vehicle getVariable "UPSMON_gunnercontrol";
+ if (isnil ("_gunnercontrol")) then {_gunnercontrol=false};
+ if (_gunnercontrol) exitwith {};
+
+ _vehicle setVariable ["UPSMON_gunnercontrol", true, false];
+
+ _crew = crew _vehicle;
+ //gunner and driver loop control
+ while { alive _vehicle && canmove _vehicle && count _crew > 0} do {
+ _crew = crew _vehicle;
+ {
+ if (!canmove _x || !alive _x) then {_crew = _crew -[_x];};
+ }foreach _crew;
+
+ //Driver control
+ if ((isnull (driver _vehicle) || !alive (driver _vehicle) || !canmove (driver _vehicle)) && count _crew > 0) then {
+ _crew2 = _crew - [gunner _vehicle];
+ if (count _crew2 > 0) then {
+ (_crew2 select (count _crew2 - 1)) spawn MON_movetodriver;
+ };
+ };
+
+ //Gunner control
+ if ( _hasgunner && (isnull (gunner _vehicle) || !alive (gunner _vehicle) || !canmove (gunner _vehicle)) && count _crew > 1) then {
+ _crew2 = _crew - [driver _vehicle];
+ if (count _crew2 > 0) then {
+ (_crew2 select (count _crew2 - 1)) spawn MON_movetogunner;
+ }else{
+ (_crew select 0) spawn MON_movetogunner;
+ };
+ };
+ sleep 20;
+ //if (KRON_UPS_Debug>0 ) then {player globalchat format["%1 crew=%2",typeof _vehicle, count _crew];};
+ };
+ //if (KRON_UPS_Debug>0 ) then {player globalchat format["%1 exits from gunner control",typeof _vehicle];};
+ _vehicle setVariable ["UPSMON_gunnercontrol", false, false];
+};
+
+
+//Mueve a todo el grupo adelante
+MON_move = {
+ private["_npc","_dir1","_targetPos","_dist"];
+ _npc = _this select 0;
+ _dist = _this select 1;
+
+ sleep 0.05;
+ if (!alive _npc || !canmove _npc ) exitwith{};
+
+ _dir1 = getDir _npc;
+ _targetPos = [position _npc,_dir1, _dist] call MON_GetPos2D;
+ _npc move _targetPos;
+};
+
+//Mueve al soldado adelante
+MON_domove = {
+ private["_npc","_dir1","_targetPos","_dist"];
+ _npc = _this select 0;
+ _dist = _this select 1;
+ if ((count _this) > 2) then {_dir1 = _this select 2;} else{_dir1 = getDir _npc;};
+
+ sleep 0.05;
+ if (!alive _npc || !canmove _npc ) exitwith{};
+
+ _targetPos = [position _npc,_dir1, _dist] call MON_GetPos2D;
+ //If position water and not boat not go
+ if (surfaceIsWater _targetPos && !(_npc iskindof "boat" || _npc iskindof "air") ) exitwith {};
+ _npc domove _targetPos;
+};
+
+//Función que detiene al soldado y lo hace esperar x segundos
+MON_doStop = {
+ private["_sleep","_npc"];
+
+ _npc = _this select 0;
+ _sleep = _this select 1;
+
+ sleep 0.05;
+ if (!alive _npc || !canmove _npc ) exitwith{};
+ if ( _sleep == 0 ) then {_sleep = 0.1};
+
+ //Restauramos valores por defecto de movimiento
+ //_npc disableAI "MOVE";
+ dostop _npc ;
+ sleep _sleep;
+ [_npc] spawn MON_cancelstop;
+};
+
+//Función que detiene al soldado y lo hace esperar x segundos
+MON_cancelstop = {
+ private["_npc"];
+ _npc = _this select 0;
+ _npc stop false;
+};
+
+//Make grenade dodge animation
+MON_evadeGrenade = {
+ if (!alive _this || (vehicle _this) != _this || !canmove _this) exitwith{};
+
+ _this playmovenow "AmovPercMstpSlowWrflDnon_ActsPpneMstpSlowWrflDr_GrenadeEscape";
+ sleep 8;
+ if (!alive _this || (vehicle _this) != _this || !canmove _this) exitwith{};
+ _this switchmove "AmovPpneMstpSrasWrflDnon_AmovPpneMevaSlowWrflDr"; //croqueta
+ _this playmovenow "AmovPpneMstpSrasWrflDnon"; //prone
+};
+
+//Realiza la animación de la croqueta
+MON_animCroqueta = {
+ if (!alive _this || (vehicle _this) != _this || !canmove _this || !(_this iskindof "Man")) exitwith{};
+
+ if ((random 1)<=.50) then {
+ _this switchmove "AmovPpneMstpSrasWrflDnon_AmovPpneMevaSlowWrflDl"; //croqueta
+ } else {
+ _this switchmove "AmovPpneMstpSrasWrflDnon_AmovPpneMevaSlowWrflDr"; //croqueta
+ };
+};
+
+//Throw a grenade
+MON_throw_grenade = {
+ private["_target","_npc"];
+ _npc = _this select 0;
+ _target = _this select 1;
+ sleep random 1.5;
+ if (!alive _npc || (vehicle _npc) != _npc || !canmove _npc) exitwith{};
+ [_npc,_target] spawn MON_dowatch;
+ sleep 0.1;
+
+ // R_Functions
+ [_npc] spawn R_ThrowSmoke;
+
+
+ /*
+
+ _npc addMagazine "SmokeShell";
+ _npc selectWeapon "throw";
+ sleep .1;
+ _npc fire ["SmokeShellMuzzle","SmokeShellMuzzle","SmokeShell"];
+ */
+};
+
+//Establece el tipo de posición
+MON_setUnitPos = {
+ private["_pos","_npc"];
+ _npc = _this select 0;
+ _pos = _this select 1;
+
+ sleep 0.5;
+ if (!alive _npc || !canmove _npc || _npc != vehicle _npc || !(_npc iskindof "Man")) exitwith{};
+ _npc setUnitPos _pos;
+ sleep 1;
+};
+//Establece el tipo de posición
+MON_setUnitPosTime = {
+ private["_pos","_npc"];
+ _npc = _this select 0;
+ _pos = _this select 1;
+ _time = _this select 2;
+
+ if (!alive _npc || !canmove _npc) exitwith{};
+ _npc setUnitPos _pos;
+ sleep _time;
+ _npc setUnitPos "AUTO";
+ sleep 1;
+};
+
+// Función para mirar en una dirección
+MON_dowatch = {
+ private["_target","_npc"];
+ _npc = _this select 0;
+ _target = _this select 1;
+
+ if (!alive _npc) exitwith{};
+ _npc dowatch _target;
+ sleep 1;
+};
+
+//Función que mueve al soldado a la posición de conductor
+//Parámeters: [_npc,_vehicle]
+// <- _npc: unit to move to driver pos
+// <- _vehicle
+MON_movetoDriver = {
+ private["_vehicle","_npc"];
+ _npc = _this ;
+ _vehicle = vehicle _npc;
+
+ //Si está muerto
+ if (vehicle _npc == _npc || !alive _npc || !canmove _npc || !(_npc iskindof "Man")) exitwith{};
+
+ if (isnull(driver _vehicle) || !alive(driver _vehicle) || !canmove(driver _vehicle)) then {
+ //if (KRON_UPS_Debug>0) then {player sidechat format["%1: Moving to driver of %2 ",_npc,typeof _vehicle]};
+ _npc action ["getOut", _vehicle];
+ doGetOut _npc;
+ WaitUntil {vehicle _npc==_npc || !alive _npc || !canmove _npc};
+ //Si está muerto
+ if (!alive _npc || !canmove _npc) exitwith{};
+ unassignVehicle _npc;
+ _npc assignasdriver _vehicle;
+ _npc moveindriver _vehicle;
+ };
+};
+
+//Función que mueve al soldado a la posición de conductor
+//Parámeters: [_npc,_vehicle]
+// <- _npc: unit to move to driver pos
+// <- _vehicle
+MON_movetogunner = {
+ private["_vehicle","_npc"];
+ _npc = _this ;
+ _vehicle = vehicle _npc;
+
+ sleep 0.05;
+ //Si está muerto
+ if (vehicle _npc == _npc || !alive _npc || !canmove _npc || !(_npc iskindof "Man")) exitwith{};
+
+ if (isnull(gunner _vehicle) || !alive(gunner _vehicle) || !canmove(gunner _vehicle)) then {
+ if (KRON_UPS_Debug>0) then {player sidechat format["%1: Moving to gunner of %2 ",_npc,typeof _vehicle]};
+ _npc action ["getOut", _vehicle];
+ doGetOut _npc;
+ WaitUntil {vehicle _npc==_npc || !alive _npc || !canmove _npc};
+ //Si está muerto
+ if (!alive _npc || !canmove _npc) exitwith{};
+ unassignVehicle _npc;
+ _npc assignasgunner _vehicle;
+ _npc moveingunner _vehicle;
+ };
+};
+
+//Función que retorna array de arrays con edificios y sus plantas
+//Parámeters: [_object,(_distance,_minfloors)]
+// <- _object: soldier to get near buildings
+// <- _distance: distance to search buildings (optional, 25 by default)
+// <- _minfloors: min floors of building (optional) if not especified min floors is 2
+// -> [_bld,_bldpos]
+MON_GetNearestBuildings = {
+ private ["_object","_altura","_pos","_bld","_bldpos","_posinfo","_minfloors","_OCercanos","_distance","_blds"];
+ _distance = 25;
+ _minfloors = 2;
+ _altura = 0;
+ _blds = [];
+
+ _object = _this select 0;
+ if ((count _this) > 1) then {_distance = _this select 1;};
+ if ((count _this) > 2) then {_minfloors = _this select 2;};
+
+ _pos =0;
+ _bld = objnull;
+ _bldpos =0;
+ _posinfo=[];
+
+ //La altura mínima es 2 porque hay muchos edificios q devuelven 2 de altura pero no se puede entrar en ellos.
+ if ( minfloors == 0 ) then {
+ minfloors = 2;
+ };
+
+ // _posinfo: [0,0]=no house near, [obj,0]=house near, but no roof positions, [obj,pos]=house near, with roof pos
+ //_posinfo= _object call MON_PosInfo;
+ _OCercanos = nearestObjects [_object, ["house","building"] , _distance];
+
+ {
+ _bldpos = _x call MON_BldPos;
+ if ( _bldpos >= _minfloors && damage _x <= 0 ) then { _blds = _blds + [[_x,_bldpos]];};
+ //player sidechat format["%1 cerca de edificio con %2 plantas %5",typeof _object,_bldpos];
+ }foreach _OCercanos;
+
+ _blds;
+};
+
+//Function to move al units of squad to near buildings
+//Parámeters: [_npc,(_patrol,_minfloors)]
+// <- _npc: lider
+// <- _distance: distance to search buildings (optional, 25 by default)
+// <- _patrol: wheter must patrol or not
+MON_moveNearestBuildings = {
+ private ["_npc","_altura","_pos","_bld","_bldpos","_posinfo","_blds","_distance","_cntobjs1","_bldunitin","_blddist","_patrol","_wait","_all"];
+ _distance = 30;
+ _altura = 0;
+ _patrol = false;
+ _wait=60;
+ _all = false;
+
+ _npc = _this select 0;
+ if ((count _this) > 1) then {_distance = _this select 1;};
+ if ((count _this) > 2) then {_patrol = _this select 2;};
+ if ((count _this) > 3) then {_wait = _this select 3;};
+ if ((count _this) > 4) then {_all = _this select 4;};
+
+
+ _pos =0;
+ _bld = objnull;
+ _bldpos =0;
+ _cntobjs1=0;
+ _bldunitsin=[];
+ _units=[];
+ _blds=[];
+
+ //If all soldiers move leader too
+ if (_all) then {
+ _units = (units _npc);
+ }else{
+ _units = (units _npc) - [_npc];
+ };
+
+ sleep 0.05;
+ {
+ if (_x iskindof "Man" && unitReady _x && _x == vehicle _x && canmove _x && alive _x && canstand _x) then {_bldunitsin = _bldunitsin + [_x]}
+ }foreach _units;
+
+ if (count _bldunitsin == 0) exitwith {};
+
+ //Obtenemos los edificios cercanos al lider
+ _blds = [_npc,_distance] call MON_GetNearestBuildings;
+
+ if (count _blds==0) exitwith {};
+
+ //Movemos a la unidades a los edificios cercanos.
+ [_bldunitsin, _blds, _patrol,_wait,_all] spawn MON_moveBuildings;
+
+};
+
+
+//Function to move al units of squad to near buildings
+//Parámeters: [_npc,(_patrol,_minfloors)]
+// <- _units: array of units
+// <- _blds: array of buildingsinfo [_bld,pos]
+// <- _patrol: wheter must patrol or not
+// -> _bldunitsin: array of units moved to builidings
+MON_moveBuildings = {
+ private ["_npc","_altura","_pos","_bld","_bldpos","_posinfo","_blds","_cntobjs1","_bldunitin","_blddist","_i","_patrol","_wait","_all","_minpos","_blds2"];
+ _patrol = false;
+ _wait = 60;
+ _minpos = 2;
+ _all = false;
+
+ _units = _this select 0;
+ _blds = _this select 1;
+ if ((count _this) > 2) then {_patrol = _this select 2;};
+ if ((count _this) > 3) then {_wait = _this select 3;};
+ if ((count _this) > 4) then {_all = _this select 4;};
+ if ((count _this) > 5) then {_minpos = _this select 5;};
+
+ _altura = 0;
+ _pos =0;
+ _bld = objnull;
+ _bldpos =0;
+ _cntobjs1=0;
+ _bldunitsin=[];
+ _movein=[];
+ _blds2 =[];
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["MON_moveBuildings _units=%1 _blds=%2",count _units, count _blds]; };
+ //if (KRON_UPS_Debug>0) then {diag_log format["MON_moveBuildings _units=%1 _blds=%2",count _units, count _blds];};
+
+ {
+ _bld = _x select 0;
+ _bldpos = _x select 1;
+
+ if ( _bldpos >= _minpos ) then {
+ _cntobjs1 = 1;
+ _movein = [];
+ _i = 0;
+
+ if (_patrol) then {
+ if (_bldpos >= 8) then { _cntobjs1 = 2 };
+ } else {
+ if (_bldpos >= 8) then { _cntobjs1 = round(random 3) + 1;};
+ };
+
+ //Buscamos una unidad cercana para recorrerlo
+ {
+ if (_x iskindof "Man" && unitReady _x && canmove _x && alive _x && vehicle _x == _x && _i < _cntobjs1) then{
+ _movein = _movein + [_x];
+ _i = _i + 1;
+ };
+ } foreach _units;
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["_units=%3 _bldunitsin %4 _movein=%1",_movein, typeof _bld, count _units, count _bldunitsin];}
+ //if (KRON_UPS_Debug>0) then {diag_log format["_units=%3 _bldunitsin %4 _movein=%1 %2 %5",_movein, typeof _bld, count _units, count _bldunitsin,_x];};
+
+ if (count _movein > 0) then {
+ _bldunitsin = _bldunitsin + _movein;
+ _units = _units - _bldunitsin;
+ if (_patrol) then {
+ {
+ [_x,_bld,_bldpos] spawn MON_patrolBuilding;
+ }foreach _movein;
+ } else {
+ {
+ _altura = floor(random(_bldpos));
+ if (_altura<2) then {_altura = _minpos};
+ [_x,_bld,_altura,_wait] spawn MON_movetoBuilding;
+ }foreach _movein;
+ };
+ };
+ };
+
+ if (count _units == 0) exitwith {};
+ }foreach _blds;
+
+ //If need to enter all units in building and rest try with a superior lvl
+ if ( _all && count _units > 0 ) then {
+ _blds2 = [];
+ _minpos = _minpos + 3;
+ {
+ if ( (_x select 1) >= _minpos) then {
+ _blds2 = _blds2 + [_x];
+ };
+ }foreach _blds;
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["MON_moveBuildings exit _units=%1 _blds=%2",count _units, count _blds2]; };
+ //if (KRON_UPS_Debug>0) then {diag_log format["MON_moveBuildings exit _units=%1 _blds=%2",count _units, count _blds2];};
+
+ if (count _blds2 > 0 ) then {
+ [_units, _blds2, _patrol,_wait,_all,_minpos] call MON_moveBuildings;
+ };
+ _bldunitsin = _bldunitsin + _units;
+ };
+ _bldunitsin;
+};
+
+//Function to move a unit to a position in a building
+//Parámeters: [_npc,(_patrol,_minfloors)]
+// <- _npc: soldier
+// <- _bld: building
+// <- _altura: building
+// <- _wait: time to wait in position
+MON_movetoBuilding = {
+
+ private ["_npc","_altura","_bld","_wait","_dist","_retry","_soldiers"];
+ _wait = 60;
+ _timeout = 120;
+ _dist = 0;
+ _retry = false;
+
+ _npc = _this select 0;
+ _bld = _this select 1;
+ _altura = _this select 2;
+ if ((count _this) > 3) then {_wait = _this select 3;};
+
+ //Si está en un vehiculo ignoramos la orden
+ if (vehicle _npc != _npc || !alive _npc || !canmove _npc) exitwith{};
+
+ //Si ya está en un edificio ignoramos la orden
+ _inbuilding = _npc getvariable ("UPSMON_inbuilding");
+ if ( isNil("_inbuilding") ) then {_inbuilding = false;};
+ if (_inbuilding) exitwith{};
+
+ _npc domove (_bld buildingPos _altura);
+ _npc setVariable ["UPSMON_inbuilding", _inbuilding, false];
+ _npc setvariable ["UPSMON_buildingpos", nil, false];
+ _timeout = time + _timeout;
+
+ //if (KRON_UPS_Debug>0) then {player globalchat format["%4|_bld=%1 | %2 | %3",typeof _bld, _npc, typeof _npc ,_altura];};
+ //if (KRON_UPS_Debug>0) then {diag_log format["%4|_bld=%1 | %2 | %3",typeof _bld, _npc, typeof _npc ,_altura];};
+
+ waitUntil {moveToCompleted _npc || moveToFailed _npc || !alive _npc || !canmove _npc || _timeout < time};
+
+ if (moveToCompleted _npc && alive _npc && canmove _npc) then {
+ _dist = [position _npc,_bld buildingPos _altura] call KRON_distancePosSqr;
+
+ _soldiers = [_npc,1] call MON_nearestSoldiers;
+
+ //If more soldiers in same floor see to keep or goout.
+ if (count _soldiers > 0) then {
+ {
+ if (!isnil{_x getvariable ("UPSMON_buildingpos")}) exitwith {_retry = true};
+ }foreach _soldiers;
+ };
+
+ if (!_retry && _dist <= 2) then {
+ _npc setvariable ["UPSMON_buildingpos", _altura, false];
+ sleep 0.1;
+ [_npc,_wait] spawn MON_dostop;
+ };
+ };
+
+ if (!alive _npc || !canmove _npc) exitwith{};
+ _npc setVariable ["UPSMON_inbuilding", false, false];
+
+
+ //Down one position.
+ if (_retry ) then {
+ _altura = _altura + 1;
+ _bldpos = _bld call MON_BldPos;
+
+ if (_altura <= _bldpos) then {
+ [_npc,_bld,_altura] spawn MON_movetoBuilding;
+ };
+ };
+};
+
+
+//Función para mover a una unidad al edificio más cercano
+//Parámeters: [_npc,_bld,(_BldPos)]
+// <- _npc: soldier to move
+// <- _bld:building to patrol
+// <- _BldPos: positions of builiding (optional)
+MON_patrolBuilding = {
+ private ["_npc","_bld","_bldpos","_posinfo","_minfloors","_OCercanos","_distance","_timeout","_pos","_inbuilding","_rnd","_NearestEnemy","_patrolto","_time"];
+ _bldpos = 0;
+ _pos = 0;
+ _timeout = 0;
+ _i = 1;
+ _inbuilding = false;
+ _rnd = 0;
+ _patrolto = 0;
+ _NearestEnemy = objnull;
+ _time = 0;
+
+ _npc = _this select 0;
+ _bld = _this select 1;
+ if ((count _this) > 2) then {_bldpos = _this select 2;} else {_bldpos = _x call MON_BldPos;};
+
+ if (_i > _bldpos) then {_i = _bldpos};
+ _patrolto = round ( 10 + random (_bldpos) );
+
+ if (_patrolto > _bldpos) then {_patrolto = _bldpos};
+
+ //Si ya está muerto o no se puede mover se ignora
+ if (!(_npc iskindof "Man") || !alive _npc || !canmove _npc) exitwith{};
+
+ //Si ya está en un edificio ignoramos la orden
+ _inbuilding = _npc getvariable ("UPSMON_inbuilding");
+ if ( isNil("_inbuilding") ) then {_inbuilding = false;};
+
+ //Asignamos el vehiculo a a la escuadra si contiene las posiciones justas
+ if (!_inbuilding) then {
+ _inbuilding = true;
+ _npc setVariable ["UPSMON_inbuilding", _inbuilding, false];
+ [_npc,"Middle"] spawn MON_setUnitPos;
+ _timeout = time + 60;
+
+ //player sidechat format["%1 patrol building %2 from %3 to %4",typeof _npc, typeof _bld,_i, _patrolto];
+
+ while { _i <= _patrolto && alive _npc && canmove _npc} do{
+
+ _npc domove (_bld buildingPos _i);
+
+
+ _time = time + 30;
+ waitUntil {moveToCompleted _npc or moveToFailed _npc or !alive _npc or _time < time};
+
+ if (moveToCompleted _npc) then {
+ _timeout = time + 60;
+ _i = _i + 1;
+ } else {
+ if (moveToFailed _npc || !canmove _npc || !alive _npc || _timeout < time) then {
+ //player sidechat format["%1 Cancelando patrulla en %2",_npc, typeof _bld];
+ _i = _patrolto + 1;
+ };
+ };
+ sleep 0.05;
+ };
+
+ //Si está en un vehiculo ignoramos la orden
+ if (!alive _npc || !canmove _npc) exitwith{};
+
+ //Volvemos con el lider
+ _npc domove (position leader _npc);
+
+ //Marcamos que ya hemos finalizado
+ sleep 60; //Damos tiempo para salir del edificio
+ _npc setVariable ["UPSMON_inbuilding", false, false];
+ };
+};
+
+//Function to put a mine
+//Parámeters: [_npc,(_position)]
+// <- _npc: leader
+// <- _position:location for mine (optional)
+MON_CreateMine = {
+ private ["_npc","_rnd","_soldier","_mine","_dir","_position"];
+ _soldier = _this select 0;
+ if ((count _this) > 1) then {_position = _this select 1;} else {_position = [0,0];};
+
+ _mine = objnull;
+ _rnd = 0;
+ _dir = 0;
+ _npc = leader _soldier;
+
+ if (_soldier == _npc ) then {
+ _rnd = round (random ( count ((units _npc))));
+ _soldier = (units _npc) select _rnd;
+ };
+
+ //leader only control not work
+ //Si está en un vehiculo ignoramos la orden
+ if (!(_soldier iskindof "Man" ) || _soldier == _npc || _soldier!=vehicle _soldier || !alive _soldier || !canmove _soldier) exitwith {false};
+
+ //Animación para montar el arma
+ if ((count _this) > 1) then {
+ [_soldier,_position] spawn MON_doCreateMine;
+ }else{
+ [_soldier] spawn MON_doCreateMine;
+ };
+ true;
+};
+
+MON_doCreateMine = {
+ private ["_npc","_rnd","_soldier","_mine","_dir","_position"];
+ _position = [0,0];
+
+ _soldier = _this select 0;
+ if ((count _this) > 1) then {_position = _this select 1;};
+
+ //If not is Man or dead exit
+ if (!(_x iskindof "Man" ) || _soldier!=vehicle _soldier || !alive _soldier || !canmove _soldier) exitwith {false};
+
+ _soldier stop false;
+ [_soldier,"AUTO"] spawn MON_setUnitPos;
+
+ if ((count _this) > 1) then {
+ _soldier domove _position;
+ waituntil {unitReady _soldier || moveToCompleted _soldier || moveToFailed _soldier || !alive _soldier || !canmove _soldier};
+ };
+
+ if (moveToFailed _soldier || !alive _soldier || _soldier != vehicle _soldier || !canmove _soldier) exitwith {false};
+
+ //Crouche
+ _soldier playMovenow "ainvpknlmstpslaywrfldnon_1";
+ sleep 1;
+
+ if (!alive _soldier || !canmove _soldier) exitwith{};
+ _dir = getdir _soldier;
+ _position = [position _soldier,_dir, 0.5] call MON_GetPos2D;
+ _mine = createMine ["MineMine", _position , [], 0];
+
+ //Prepare mine
+ _soldier playMoveNow "AinvPknlMstpSlayWrflDnon_medic";
+ sleep 5;
+
+ //Return to formation
+ _soldier domove position ( leader _soldier );
+};
+
+//Function to surrender AI soldier
+//Parámeters: [_npc]
+// <- _npc: soldier to surrender
+MON_surrender = {
+ private ["_npc","_vehicle"];
+ _npc = _this select 0;
+
+ if (!alive _npc || !canmove _npc) exitwith {};
+
+ _npc addrating -1000;
+ _npc setcaptive true;
+ sleep 0.5;
+
+ _vehicle = vehicle _npc;
+
+ if ( _npc != _vehicle || !(_npc iskindof "Man" )) then {
+ _vehicle setcaptive true;
+
+ if ( "Air" countType [_vehicle]>0) then {
+
+ //Si acaba de entrar en el heli se define punto de aterrizaje
+ if (_npc == driver _vehicle ) then {
+ [_vehicle] call MON_landHely;
+ };
+ } else {
+ _npc spawn MON_doGetOut;
+ };
+
+ //Esperamos a que esté parado
+ waituntil {_npc == vehicle _npc || !alive _npc};
+ };
+
+ if (!alive _npc || !canmove _npc) exitwith {};
+ _npc setcaptive true;
+ _npc stop true;
+
+ [_npc,"UP"] call MON_setUnitPos;
+ removeAllWeapons _npc;
+ sleep 1;
+ _npc playMoveNow "AmovPercMstpSnonWnonDnon_AmovPercMstpSsurWnonDnon";
+
+};
+
+//Returns leader if was dead
+MON_getleader = {
+ private ["_npc","_members"];
+ _npc = _this select 0;
+ _members = _this select 1;
+
+ sleep 0.05;
+ if (!alive _npc ) then {
+ //takes commder a soldier not in vehicle
+ {
+ if (alive _x && canmove _x && _x == vehicle _x && !isplayer _x) exitwith {
+ _npc = _x;
+ };
+ } foreach _members;
+
+ //if no soldier out of vehicle takes any
+ if (!alive _npc ) then {
+ {
+ if (alive _x && canmove _x) exitwith {_npc = _x;};
+ } foreach _members;
+ };
+
+ //If not alive or already leader or is player exits
+ if (isPlayer _npc || !alive _npc || !canmove _npc ) then
+ {
+ {
+ if (alive _x && !isPlayer _x) exitwith {_npc = [_npc, _members] call MON_getleader;};
+ }foreach _members;
+ };
+
+ if (leader _npc == _npc) exitwith {_npc};
+
+ //Set new _npc as leader
+ group _npc selectLeader _npc;
+ };
+ _npc // return
+};
+
+MON_ACE_Watersurvival = {
+ private ["_lb","_pos","_ejector","_in","_grpid","_rnd"];
+ _in =[];
+ _rnd = 0;
+ _ejector = _this select 0;
+ //if (KRON_UPS_Debug>0) then {player globalchat format["MON_ACE_Watersurvival %1",typeof _ejector]};
+
+ waitUntil { !canmove _ejector || !alive _ejector || isnull (_ejector) || ((getPos vehicle _ejector) select 2 < 1) };
+ if ( !surfaceIsWater (getpos _ejector) || !canmove _ejector || !alive _ejector || isnull (_ejector) ) exitWith {};
+
+ //Miramos de entrar en un barco cercano
+ _grpid = _ejector getvariable "UPSMON_grpid";
+ if (isnil "_grpid") then {_grpid = 0};
+ _in = [_grpid,_ejector,30] call MON_GetIn_NearestBoat;
+
+ //If no boat near creates a zodiac
+ if (count _in <= 0) then {
+ if (!(isNil "ace_main")) then {
+ _lb = "ACE_Lifeboat_US" createVehicle getposASL _ejector;
+ }else{
+ _lb = "Zodiac" createVehicle getposASL _ejector;
+ };
+ _pos = getposASL _ejector;
+ _pos set [0, ((_pos select 0) + 2)];
+ _pos set [1, ((_pos select 1) + 2)];
+ //_pos set [2, 0];
+ _lb setPos _pos;
+
+ //Moves in boat
+ if !(isPlayer _ejector) then {
+ [_ejector,_lb,0] call MON_assignasdriver;
+ };
+ };
+
+ //Wait until reached eart
+ waitUntil { !canmove _ejector || !alive _ejector || isnull (_ejector) || !surfaceIsWater (position _ejector) };
+ if (KRON_UPS_Debug>0) then {player globalchat format["Exit from boat%1",typeof _lb]};
+ _ejector spawn MON_dogetout;
+};
+
+//=============================================================Changed by Shay_gman========================================================================================
+//Function to do artillery
+//Parámeters: [_position,(_rounds,_area,_cadence,_mincadence)]
+// <- _arti:
+// <- _position: center of fire create artillery
+// <- _rounds: rounds of fire
+// <- _area: Dispersion area
+// <- _maxcadence: Cadence of fire, is random between min
+// <- _mincadence: Minimum cadence
+// <- _bullet: class of bullet to fire, default ARTY_Sh_81_HE
+
+MON_artillery_dofire = {
+ if (!isserver) exitWith {};
+ private ["_smoke1","_i","_area","_position","_maxcadence","_mincadence","_sleep","_rounds","_arti","_timeout","_salvo_break"];
+ _area = 150;
+ _maxcadence = 10;
+ _mincadence = 5;
+ _sleep = 0;
+ _rounds = 5;
+ _bullet = "ARTY_Sh_81_HE";
+ _position =[];
+ _salvo_break = 10;
+
+ _arti = _this select 0;
+ _position = _this select 1;
+ if ((count _this) > 2) then {_rounds = _this select 2;};
+ if ((count _this) > 3) then {_area = _this select 3;};
+ if ((count _this) > 4) then {_maxcadence = _this select 4;};
+ if ((count _this) > 5) then {_mincadence = _this select 5;};
+ if ((count _this) > 6) then {_bullet = _this select 6;};
+ if ((count _this) > 7) then {_salvo_break = _this select 7;};
+
+ // set reload time for 1000 make do not fire untill this salvo finish
+ _timeout = time + 1000;
+ _arti setVariable ["timeout", _timeout, false];
+
+ _area2 = _area * 2;
+ if (KRON_UPS_Debug>0) then { player globalchat format["artillery doing fire on %1",_position] };
+ for [{_i=0}, {_i<_rounds}, {_i=_i+1}] do
+ {
+ _arti fire (weapons _arti select 0);
+ _sleep = random _maxcadence;
+ if (_sleep < _mincadence) then {_sleep = _mincadence};
+ sleep _sleep;
+ _smoke1 = _bullet createVehicle [(_position select 0)+ random _area2 - _area, (_position select 1)+ random _area2 - _area, (_position select 2)+ 100];
+ _arti setVehicleAmmo 1;
+ };
+
+ // set reload time for next salvo
+ _timeout = time + _salvo_break;
+ _arti setVariable ["timeout", _timeout, false];
+ };
+
+//Función que devuelve un array con los vehiculos terrestres más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_deadbodies = {
+ private["_vehicles","_npc","_bodies","_OCercanos","_distance","_side"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+ //_side = _this select 2;
+
+ _OCercanos = [];
+ _bodies = [];
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Man"] , _distance];
+
+ {
+ if (_npc knowsabout _x >0.5 && (!canmove _x || !alive _x)) then { _bodies = _bodies + [_x];};
+ }foreach _OCercanos;
+
+ _bodies;
+ };
+
+//Función que devuelve un array con los vehiculos terrestres más cercanos
+//Parámeters: [_npc,_distance]
+// <- _npc: object for position search
+// <- _distance: max distance from npc
+// -> _vehicles: array of vehicles
+MON_nearestSoldiers = {
+ private["_vehicles","_npc","_soldiers","_OCercanos","_distance","_side"];
+
+ _npc = _this select 0;
+ _distance = _this select 1;
+
+ if (isnull _npc) exitwith {};
+
+ _OCercanos = [];
+ _soldiers = [];
+
+ //Buscamos objetos cercanos
+ _OCercanos = nearestObjects [_npc, ["Man"] , _distance];
+ _OCercanos = _OCercanos - [_npc];
+
+ {
+ if ( alive _x && canmove _x ) then { _soldiers = _soldiers + [_x];};
+ }foreach _OCercanos;
+
+ _soldiers;
+};
\ No newline at end of file |
