From a3a91d4f45b22fd487ecbc954ad979be5d03efdd Mon Sep 17 00:00:00 2001 From: hybrid Date: Thu, 11 Jun 2026 19:38:09 +0300 Subject: init --- Server/AI/AI_AddMultiplayerRespawnEH.sqf | 1 + Server/AI/AI_AdvancedRespawn.sqf | 119 +++++++++++++++++++++++++++++++ Server/AI/AI_Resistance.sqf | 17 +++++ Server/AI/AI_SquadRespawn.sqf | 104 +++++++++++++++++++++++++++ Server/AI/AI_TLWPHandler.sqs | 39 ++++++++++ Server/AI/AI_UpdateSupplyTruck.sqf | 24 +++++++ Server/AI/AI_Upgrade.sqf | 32 +++++++++ Server/AI/Orders/AI_MoveTo.sqf | 17 +++++ Server/AI/Orders/AI_Patrol.sqf | 34 +++++++++ Server/AI/Orders/AI_TownPatrol.sqf | 71 ++++++++++++++++++ Server/AI/Orders/AI_WPAdd.sqf | 39 ++++++++++ Server/AI/Orders/AI_WPRemove.sqf | 6 ++ 12 files changed, 503 insertions(+) create mode 100644 Server/AI/AI_AddMultiplayerRespawnEH.sqf create mode 100644 Server/AI/AI_AdvancedRespawn.sqf create mode 100644 Server/AI/AI_Resistance.sqf create mode 100644 Server/AI/AI_SquadRespawn.sqf create mode 100644 Server/AI/AI_TLWPHandler.sqs create mode 100644 Server/AI/AI_UpdateSupplyTruck.sqf create mode 100644 Server/AI/AI_Upgrade.sqf create mode 100644 Server/AI/Orders/AI_MoveTo.sqf create mode 100644 Server/AI/Orders/AI_Patrol.sqf create mode 100644 Server/AI/Orders/AI_TownPatrol.sqf create mode 100644 Server/AI/Orders/AI_WPAdd.sqf create mode 100644 Server/AI/Orders/AI_WPRemove.sqf (limited to 'Server/AI') diff --git a/Server/AI/AI_AddMultiplayerRespawnEH.sqf b/Server/AI/AI_AddMultiplayerRespawnEH.sqf new file mode 100644 index 0000000..1308fb4 --- /dev/null +++ b/Server/AI/AI_AddMultiplayerRespawnEH.sqf @@ -0,0 +1 @@ +(leader _this) addMPEventHandler ['MPRespawn',{if (isServer && !(isPlayer (_this select 0))) then {_this Spawn AIAdvancedRespawn}}]; \ No newline at end of file diff --git a/Server/AI/AI_AdvancedRespawn.sqf b/Server/AI/AI_AdvancedRespawn.sqf new file mode 100644 index 0000000..a05caac --- /dev/null +++ b/Server/AI/AI_AdvancedRespawn.sqf @@ -0,0 +1,119 @@ +/* Enhanced Respawn Management via Multiplayer Event Handler - Experimental */ +Private ['_autonomous','_availableSpawn','_buildings','_checks','_closestRespawn','_corpse','_deathLoc','_hq','_i','_isForcedRespawn','_mobileRespawns','_moveMode','_pos','_ran','_range','_rcm','_rd','_respawn','_respawnLoc','_respawnedUnit','_side','_sideText','_skip','_team','_update','_upgrades']; + +_respawnedUnit = _this select 0; +_corpse = _this select 1; + +_deathLoc = getPos _corpse; +_rd = 'WFBE_RESPAWNDELAY' Call GetNamespace; +_rcm = 'WFBE_RESPAWNCAMPSMODE' Call GetNamespace; + +_side = side _respawnedUnit; +//--- Ensure that the side is not civilian. +if (_side == civilian) then { + if (_respawnedUnit isKindOf westSoldierBaseClass) then {_side = west}; + if (_respawnedUnit isKindOf eastSoldierBaseClass) then {_side = east}; +}; +_sideText = str _side; +_team = group _respawnedUnit; +_respawn = (_team) Call GetTeamRespawn; +_respawnLoc = objNull; + +diag_log format ["[WFBE (INFORMATION)][frameno:%7 | ticktime:%8] AI_AdvancedRespawn: AI Team Leader '%1' (Team '%2', Rank '%3', Type '%4', Side '%5') has respawned after dieing at %6",_respawnedUnit,_team,rank _respawnedUnit,typeOf _respawnedUnit,_side,_deathLoc,diag_frameno,diag_tickTime]; + +//--- Remove previous EH. +_respawnedUnit removeAllEventHandlers "Killed"; +Call Compile Format ["_respawnedUnit addEventHandler ['Killed',{[_this select 0,_this select 1,%1] Spawn UnitKilled}]",_side]; + +//--- Place the leader on a 'safe' position. +_respawnedUnit setPos getMarkerPos Format["%1TempRespawnMarker",_sideText]; + +_availableSpawn = []; +_isForcedRespawn = false; + +//--- Ensure that the ai is not forced to respawn. +if (typeName _respawn == 'STRING') then {if (_respawn == "forceRespawn") then {_isForcedRespawn = true}}; + +//--- Towns. +if (_rcm > 0 && !_isForcedRespawn) then { + _availableSpawn = _availableSpawn + ([_deathLoc, _side] Call GetRespawnCamps); +}; + +_upgrades = (_sideText) Call GetSideUpgrades; + +//--- Mobile Respawn. +if (paramMobileRespawn && !_isForcedRespawn) then { + _mobileRespawns = Format ["WFBE_%1AMBULANCES",_sideText] Call GetNamespace; + _range = (Format["WFBE_RESPAWNMOBILERANGE%1",(_upgrades select 7)] Call GetNamespace); + _checks = _deathLoc nearEntities[_mobileRespawns,_range]; + if (count _checks > 0) then { + {if (alive _x) then {_availableSpawn = _availableSpawn + [_x]}} forEach _checks; + }; +}; + +//--- Wait. +_i = _rd; +_skip = false; +while {_i > 0} do { + if (isPlayer(_respawnedUnit) || !(alive _respawnedUnit)) exitWith {_skip = true}; + + _i = _i - 1; + sleep 1; +}; + +//--- Make sure that the AI didn't die or that a player hasn't replaced him before going any further. +if !(_skip) then { + //--- Equip the AI. + _ran = 1 + round(random(2)); + [_respawnedUnit,Format ["WFBE_%1LEADERWEAPONS%2%3",_sideText,_upgrades select 13,_ran] Call GetNamespace, Format ["WFBE_%1LEADERAMMO%2%3",_sideText,_upgrades select 13,_ran] Call GetNamespace] Call EquipLoadout; + _hq = (_sideText) Call GetSideHQ; + _buildings = (_sideText) Call GetSideStructures; + + //--- Check whether AI has a spawn set or not. + _update = false; + switch (typeName _respawn) do { + case "STRING": { + //--- Not defined. + _update = true; + if (_isForcedRespawn) then {[_team,""] Call SetTeamRespawn}; + }; + case "OBJECT": { + //--- Defined. + _respawnLoc = _respawn; + if (!alive _respawn || isNull _respawn) then { + [_team, ""] Call SetTeamRespawn; + _update = true; + }; + }; + }; + + //--- Default respawn. + if (_update) then { + _respawnLoc = _hq; + if (count _buildings > 0) then { + _closestRespawn = [_hq,_buildings] Call SortByDistance; + _respawnLoc = _closestRespawn select 0; + }; + }; + + //--- Alternative spawn location. + if (count _availableSpawn > 0) then { + _respawnLoc = _availableSpawn select (round(random((count _availableSpawn)-1))); + }; + + diag_log format ["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_AdvancedRespawn: AI Team Leader %1 is respawning at: %2 (%3)",_respawnedUnit,typeOf _respawnLoc,_respawnLoc,diag_frameno,diag_tickTime]; + + _pos = [getPos _respawnLoc,20,30] Call GetRandomPosition; + _pos set [2,0]; + _respawnedUnit setPos _pos; + + //--- Assign fresh order if the AI is not on autonomous mode. + _autonomous = (_team) Call GetTeamAutonomous; + if !(_autonomous) then { + _moveMode = (_team) Call GetTeamMoveMode; + if (_moveMode == "towns") then {[_team,"resetTowns"] Call SetTeamMoveMode}; + if (_moveMode == "move") then {[_team,"resetMove"] Call SetTeamMoveMode}; + if (_moveMode == "patrol") then {[_team,"resetPatrol"] Call SetTeamMoveMode}; + if (_moveMode == "defense") then {[_team,"resetDefense"] Call SetTeamMoveMode}; + }; +}; \ No newline at end of file diff --git a/Server/AI/AI_Resistance.sqf b/Server/AI/AI_Resistance.sqf new file mode 100644 index 0000000..2fe1ce2 --- /dev/null +++ b/Server/AI/AI_Resistance.sqf @@ -0,0 +1,17 @@ +Private ["_action","_position","_range","_team"]; +_team = _this select 0; +_position = _this select 1; +_range = _this select 2; +_action = _this select 3; + +switch (_action) do { + case "Patrol": {[_team,_position,_range] Call BIS_fnc_taskPatrol}; + case "Defend": { + _team setFormation "STAG COLUMN"; + _team setBehaviour "AWARE"; + _team setSpeedMode "NORMAL"; + + [_team, true, [[_position, 'SAD', 40, 30, "", []]]] Call AIWPAdd; + }; + case "CPatrol": {[_team,_position,_range] Spawn AIPatrol}; +}; \ No newline at end of file diff --git a/Server/AI/AI_SquadRespawn.sqf b/Server/AI/AI_SquadRespawn.sqf new file mode 100644 index 0000000..08a32a2 --- /dev/null +++ b/Server/AI/AI_SquadRespawn.sqf @@ -0,0 +1,104 @@ +Private ["_availableSpawn","_autonomous","_buildings","_checks","_closestRespawn","_deathLoc","_enemySide","_hq","_isForcedRespawn","_leader","_mobileRespawns","_moveMode","_pos","_ran","_range","_rcm'","_rd","_respawn","_respawnLoc","_side","_sideText","_team","_update","_upgrades"]; +_side = _this select 0; +_team = _this select 1; +_sideText = str _side; +_deathLoc = objNull; +_respawnLoc = objNull; + +_rd = 'WFBE_RESPAWNDELAY' Call GetNamespace; +_rcm = 'WFBE_RESPAWNCAMPSMODE' Call GetNamespace; + +sleep (random 0.5); + +while {!gameOver} do { + if (isPlayer leader _team) exitWith {}; + [str _side,'UnitsCreated',1] Call UpdateStatistics; + waitUntil {!alive leader _team || isPlayer leader _team}; + _deathLoc = getPos (leader _team); + diag_log format ["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_SquadRespawn: AI Team Leader '%1' (Team '%2') is dead at %3",leader _team,_team,_deathLoc,diag_frameno,diag_tickTime]; + if (isPlayer leader _team) exitWith {}; + waitUntil {alive leader _team || isPlayer leader _team}; + if (isPlayer leader _team) exitWith {}; + + _respawn = (_team) Call GetTeamRespawn; + + //--- Place the AI. + _leader = leader _team; + _leader removeAllEventHandlers "Killed"; + Call Compile Format ["_leader addEventHandler ['Killed',{[_this select 0,_this select 1,%1] Spawn UnitKilled}]",_side]; + _leader setPos getMarkerPos Format["%1TempRespawnMarker",_sideText]; + + _availableSpawn = []; + _isForcedRespawn = false; + if (typeName _respawn == 'STRING') then {if (_respawn == "forceRespawn") then {_isForcedRespawn = true}}; + + //--- Towns. + if (_rcm > 0 && !_isForcedRespawn) then { + _availableSpawn = _availableSpawn + ([_deathLoc, _side] Call GetRespawnCamps); + }; + + _upgrades = (_sideText) Call GetSideUpgrades; + + //--- Mobile Respawn. + if (paramMobileRespawn && !_isForcedRespawn) then { + _mobileRespawns = Format ["WFBE_%1AMBULANCES",_sideText] Call GetNamespace; + _range = (Format["WFBE_RESPAWNMOBILERANGE%1",(_upgrades select 7)] Call GetNamespace); + _checks = _deathLoc nearEntities[_mobileRespawns,_range]; + if (count _checks > 0) then { + {if (alive _x) then {_availableSpawn = _availableSpawn + [_x]}} forEach _checks; + }; + }; + + sleep _rd; + + //--- Equip the AI. + _ran = 1 + round(random(2)); + [_leader,Format ["WFBE_%1LEADERWEAPONS%2%3",_sideText,_upgrades select 13,_ran] Call GetNamespace, Format ["WFBE_%1LEADERAMMO%2%3",_sideText,_upgrades select 13,_ran] Call GetNamespace] Call EquipLoadout; + _hq = (_sideText) Call GetSideHQ; + _buildings = (_sideText) Call GetSideStructures; + + //--- Check whether AI has a spawn set or not. + _update = false; + switch (typeName _respawn) do { + case "STRING": { + _update = true; + if (_isForcedRespawn) then {[_team,""] Call SetTeamRespawn}; + }; //--- Not defined. + case "OBJECT": { + _respawnLoc = _respawn; + if (!alive _respawn || isNull _respawn) then { + [_team, ""] Call SetTeamRespawn; + _update = true; + }; //--- Defined. + }; + }; + + //--- Default respawn. + if (_update) then { + _respawnLoc = _hq; + if (count _buildings > 0) then { + _closestRespawn = [_hq,_buildings] Call SortByDistance; + _respawnLoc = _closestRespawn select 0; + }; + }; + + //--- Alternative spawn location. + if (count _availableSpawn > 0) then { + _respawnLoc = _availableSpawn select (round(random((count _availableSpawn)-1))); + }; + + diag_log format ["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_SquadRespawn: AI Team Leader %1 is respawning at: %2 (%3)",leader _team,typeOf _respawnLoc,_respawnLoc,diag_frameno,diag_tickTime]; + _pos = [getPos _respawnLoc,20,30] Call GetRandomPosition; + _pos set [2,0]; + _leader setPos _pos; + + //--- Assign fresh order (tbc). + _autonomous = (_team) Call GetTeamAutonomous; + if !(_autonomous) then { + _moveMode = (_team) Call GetTeamMoveMode; + if (_moveMode == "towns") then {[_team,"resetTowns"] Call SetTeamMoveMode}; + if (_moveMode == "move") then {[_team,"resetMove"] Call SetTeamMoveMode}; + if (_moveMode == "patrol") then {[_team,"resetPatrol"] Call SetTeamMoveMode}; + if (_moveMode == "defense") then {[_team,"resetDefense"] Call SetTeamMoveMode}; + }; +}; \ No newline at end of file diff --git a/Server/AI/AI_TLWPHandler.sqs b/Server/AI/AI_TLWPHandler.sqs new file mode 100644 index 0000000..c94a6a8 --- /dev/null +++ b/Server/AI/AI_TLWPHandler.sqs @@ -0,0 +1,39 @@ +Private ["_group","_i","_timeSince","_unit","_units","_waitForMembers","_wpPos"] +_group = _this select 0 +_wpPos = _this select 1 + +_timeSince = 0 + +if (vehicle (leader _group) isKindOf "Air") then {Goto "Exit";} + +#Main + ~5 + + _timeSince = _timeSince + 5 + + ;Check for the group's status. + _units = ((units _group) Call GetLiveUnits) - [leader _group] + + ;Exit if the leader is the only member. + if (count _units < 2) then {Goto "Exit";} + + _i = 0 + _waitForMembers = false + + ;Iterate through all members. + #Loop + _unit = _units select _i + + if (_unit distance (leader _group) > 150 && !(_unit isKindOf 'Air')) then {_waitForMembers = true; if (_timeSince > 240) then {[vehicle _unit,getPos (leader _group),75] Call PlaceSafe;};} + + _i = _i + 1 + + if (_i == count _units) then {if (_waitForMembers) then {Goto "Main";} else {Goto "Exit";}}; + + Goto "Loop" + + Goto "Main" + +#Exit + + Exit \ No newline at end of file diff --git a/Server/AI/AI_UpdateSupplyTruck.sqf b/Server/AI/AI_UpdateSupplyTruck.sqf new file mode 100644 index 0000000..9083ed7 --- /dev/null +++ b/Server/AI/AI_UpdateSupplyTruck.sqf @@ -0,0 +1,24 @@ +Private ["_AITrucks","_destinations","_driver","_full","_hq","_isDeployed","_maist","_side","_sideText","_team","_type","_vehicle"]; +_side = _this select 0; +_sideText = str _side; +_maist = 'WFBE_MAXAISUPPLYTRUCKS' Call GetNamespace; + +sleep ((Random 200) / 100); +sleep ((Random 200) / 100); + +waitUntil {townInit}; + +while {!gameOver} do { + sleep 60; + _AITrucks = Format ["WFBE_%1_AISupplyTrucks",_sideText] Call GetNamespace; + _full = false; + if (count _AITrucks >= _maist) then {_full = true}; + if (!_full) then { + _isDeployed = (_sideText) Call GetSideHQDeployed; + _hq = (_sideText) Call GetSideHQ; + if ((_isDeployed)&&(alive _hq)&&(!isNull _hq)) then { + diag_log Format["[WFBE (INFORMATION)][frameno:%2 | ticktime:%3] AI_UpdateSupplyTruck: A %1 Supply truck has been created",_side,diag_frameno,diag_tickTime]; + [_side] ExecFSM "Server\FSM\supplytruck.fsm"; + }; + }; +}; diff --git a/Server/AI/AI_Upgrade.sqf b/Server/AI/AI_Upgrade.sqf new file mode 100644 index 0000000..dabac71 --- /dev/null +++ b/Server/AI/AI_Upgrade.sqf @@ -0,0 +1,32 @@ +Private ["_index","_index2","_name","_side","_sideText","_time","_upgrades","_upgrades_old"]; +_time = _this select 0; +_index = _this select 1; +_index2 = _this select 2; +_name = _this select 3; +_side = _this select 4; +_sideText = Str _side; + +Call Compile Format ["WFBE_%1_Upgrading = true; publicVariable 'WFBE_%1_Upgrading';",_sideText]; + +_upgrades_old = (_sideText) Call GetSideUpgrades; + +sleep _time; + +_upgrades = (_sideText) Call GetSideUpgrades; + +//--- Failover due to faulty pv. +for '_i' from 0 to count _upgrades_old do { + if ((_upgrades_old select _i) != (_upgrades select _i)) then {_upgrades set [_i, (_upgrades_old select _i)]}; +}; + +_upgrades set [_index2,_index + 1]; +Call Compile Format ["%1Upgrades = _upgrades; publicVariable '%1Upgrades';",_sideText]; + +WFBE_LocalizeMessage = [_side,'CLTFNCLOCALIZEMESSAGE',['UpgradeComplete',_index2,(_index + 1)]]; +publicVariable 'WFBE_LocalizeMessage'; +if (isHostedServer) then {[_side,'CLTFNCLOCALIZEMESSAGE',['UpgradeComplete',_index2,(_index + 1)]] Spawn HandlePVF}; +[Format["WFBE_%1_Upgrading",_sideText],false,true] Call SetNamespace; + +["NewIntelAvailable","",_side,""] Spawn SideMessage; + +Call Compile Format ["WFBE_%1_Upgrading = false; publicVariable 'WFBE_%1_Upgrading';",_sideText]; diff --git a/Server/AI/Orders/AI_MoveTo.sqf b/Server/AI/Orders/AI_MoveTo.sqf new file mode 100644 index 0000000..e372393 --- /dev/null +++ b/Server/AI/Orders/AI_MoveTo.sqf @@ -0,0 +1,17 @@ +private ["_destination","_mission","_radius","_team","_update"]; +_team = _this select 0; +_destination = _this select 1; +_mission = _this select 2; +_radius = if (count _this > 3) then {_this select 3} else {30}; + +_update = true; +if (side _team == west || side _team == east) then { + _update = (_team) Call CanUpdateTeam; +}; + +//--- Override. +if (_update) then {_team Call UpdateTeam}; + +diag_log Format["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_MoveTo: The %1 %2 Team is moving to %3",side _team,_team,_destination,diag_frameno,diag_tickTime]; + +[_team,true,[[_destination, _mission, _radius, 20, "", []]]] Call AIWPAdd; \ No newline at end of file diff --git a/Server/AI/Orders/AI_Patrol.sqf b/Server/AI/Orders/AI_Patrol.sqf new file mode 100644 index 0000000..8cff904 --- /dev/null +++ b/Server/AI/Orders/AI_Patrol.sqf @@ -0,0 +1,34 @@ +Private ["_destination","_maxWaypoints","_pos","_radius","_rand1","_rand2","_team","_type","_update","_wps","_z"]; +_team = _this select 0; +_destination = _this select 1; +_radius = if (count _this > 2) then {_this select 2} else {30}; +if (typeName _destination == 'OBJECT') then {_destination = getPos _destination}; + +_update = true; +if (side _team == west || side _team == east) then { + _update = (_team) Call CanUpdateTeam; +}; + +//--- Override. +if (_update) then {_team Call UpdateTeam}; + +_maxWaypoints = 8; +_wps = []; +for [{_z=0},{_z<=_maxWaypoints},{_z=_z+1}] do { + _rand1 = (random _radius) - (random _radius); + _rand2 = (random _radius) - (random _radius); + _pos = [(_destination select 0)+_rand1,(_destination select 1)+_rand2,0]; + _tries = 100; + while {surfaceIsWater _pos && _tries > 0} do { + _tries = _tries - 1; + _rand1 = (random _radius) - (random _radius); + _rand2 = (random _radius) - (random _radius); + _pos = [(_destination select 0)+_rand1,(_destination select 1)+_rand2,0]; + }; + _type = if (_z != _maxWaypoints) then {'MOVE'} else {'CYCLE'}; + _wps = _wps + [[_pos,_type,35,40,"",[]]]; +}; + +diag_log Format["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_Patrol: The %1 %2 Team is patrolling at %3",side _team,_team,_destination,diag_frameno,diag_tickTime]; + +[_team, true, _wps] Call AIWPAdd; \ No newline at end of file diff --git a/Server/AI/Orders/AI_TownPatrol.sqf b/Server/AI/Orders/AI_TownPatrol.sqf new file mode 100644 index 0000000..15122d3 --- /dev/null +++ b/Server/AI/Orders/AI_TownPatrol.sqf @@ -0,0 +1,71 @@ +/* + Author: Benny + Name: AI_TownPatrol.sqf + Parameters: + 0 - Team + 1 - Town + 2 - (Radius) + Description: + This file is called upon a resistance / occupation patrol, AI will randomly patrol in towns, including the camps and the depots. +*/ + +Private ['_camps','_insert','_insertObject','_insertStep','_maxWaypoints','_pos','_radius','_rand1','_rand2','_team','_town','_townPos','_type','_update','_usable','_wpcompletionRadius','_wpradius','_wps','_z']; +_team = _this select 0; +_town = _this select 1; +_radius = if (count _this > 2) then {_this select 2} else {30}; +if (typeName _town != 'OBJECT') exitWith {diag_log Format ["[WFBE (ERROR)] AI_TownPatrol: Object expected, %1 given",_town]}; +if (isNull _team) exitWith {diag_log Format ["[WFBE (ERROR)] AI_TownPatrol: Null Groups cannot be used (Town: %1)",_town]}; +_townPos = getPos _town; + +_camps = _town getVariable 'camps'; + +_usable = [_town] + _camps; +_maxWaypoints = ('WFBE_TOWNPATROLHOPS' Call GetNamespace) + count(_usable); +_wps = []; + +//--- Randomize the behaviours. +if (random 100 > 50) then {_team setFormation "DIAMOND"} else {_team setFormation "STAG COLUMN"}; +if (random 100 > 50) then {_team setCombatMode "YELLOW"} else {_team setCombatMode "RED"}; +if (random 100 > 50) then {_team setBehaviour "AWARE"} else {_team setBehaviour "COMBAT"}; +if (random 100 > 50) then {_team setSpeedMode "NORMAL"} else {_team setSpeedMode "LIMITED"}; + +//--- Dyn insert. +_insertStep = if (count(_usable) != 0) then {floor(_maxWaypoints / count(_usable))} else {-1}; +_insert = _insertStep; +_insertObject = objNull; +_wpradius = -1; +_wpcompletionRadius = -1; + +for [{_z=0},{_z<=_maxWaypoints},{_z=_z+1}] do { + if (_z == _insert && count _usable > 0) then { + _insert = _insert + _insertStep; + _insertObject = _usable select (round(random((count _usable)-1))); + _usable = _usable - [_insertObject]; + }; + + if (isNull _insertObject) then { + _rand1 = random _radius; + _rand2 = random _radius; + _pos = [(_townPos select 0)+_rand1,(_townPos select 1)+_rand2,0]; + _tries = 100; + while {surfaceIsWater _pos && _tries > 0} do { + _tries = _tries - 1; + _rand1 = random _radius; + _rand2 = random _radius; + _pos = [(_townPos select 0)+_rand1,(_townPos select 1)+_rand2,0]; + }; + _wpradius = 32; + _wpcompletionRadius = 44; + } else { + _pos = getPos _insertObject; + _wpradius = 35; + _wpcompletionRadius = 68; + }; + + _type = if (_z != _maxWaypoints) then {'MOVE'} else {'CYCLE'}; + _wps = _wps + [[_pos,_type,_wpradius,_wpcompletionRadius, "", []]]; +}; + +diag_log Format["[WFBE (INFORMATION)][frameno:%4 | ticktime:%5] AI_TownPatrol: The %1 %2 Team is patrolling the %3 town",side _team,_team,_town,diag_frameno,diag_tickTime]; + +[_team, true, _wps] Call AIWPAdd; \ No newline at end of file diff --git a/Server/AI/Orders/AI_WPAdd.sqf b/Server/AI/Orders/AI_WPAdd.sqf new file mode 100644 index 0000000..ad04518 --- /dev/null +++ b/Server/AI/Orders/AI_WPAdd.sqf @@ -0,0 +1,39 @@ +/* + Author: Benny + Name: AI_WPAdd.sqf + Parameters: + 0 - Team + 1 - Clear (Remove WPs) + 2 - Waypoints (given in an Array) + Description: + This file is used to give a detailed WP system. + Exemple: + [_team, true, [[getPos _camp, 'MOVE', 10, 20, "", []],[[1560,2560,0], 'SAD', 50, 70, "", ["canComplete", "this sidechat 'lets roll'"]]...]] Call AddWP; +*/ + +Private ['_clear','_completionRadius','_position','_radius','_scripted','_statements','_team','_type','_waypoint','_waypoints','_WPCount']; +_team = _this select 0; +_clear = _this select 1; +_waypoints = _this select 2; + +if (_clear) then {_team Call AIWPRemove}; + +{ + _position = _x select 0; + _type = _x select 1; + _radius = _x select 2; + _completionRadius = _x select 3; + _scripted = _x select 4; + _statements = _x select 5; + if (typeName _position == 'OBJECT') then {_position = getPos _position}; + + _WPCount = count (waypoints _team); + + _team addWaypoint [_position,_radius]; + [_team, _WPCount] setWaypointType _type; + [_team, _WPCount] setWaypointCompletionRadius _completionRadius; + if (_type == 'SCRIPTED') then {[_team, _WPCount] setWaypointScript _scripted}; + if (count _statements > 0) then {[_team, _WPCount] setWaypointStatements [_statements select 0, _statements select 1]}; + + if (_WPCount == 0) then {_team setCurrentWaypoint [_team, _WPCount]}; +} forEach _waypoints; \ No newline at end of file diff --git a/Server/AI/Orders/AI_WPRemove.sqf b/Server/AI/Orders/AI_WPRemove.sqf new file mode 100644 index 0000000..a02a1e2 --- /dev/null +++ b/Server/AI/Orders/AI_WPRemove.sqf @@ -0,0 +1,6 @@ +Private ['_team','_z']; +_team = _this; + +for [{_z = (count (waypoints _team))-1},{_z > -1},{_z = _z - 1}] do { + deleteWaypoint [_team, _z]; +}; \ No newline at end of file -- cgit v1.3.1