This commit is contained in:
2022-04-21 16:15:41 +03:00
commit 9d4fc88901
601 changed files with 66252 additions and 0 deletions

View File

@ -0,0 +1,186 @@
/*
=======================================================================================================================
Script: BIN_taskPatrol.sqf v1.3
Author(s): Binesi
Partly based on original code by BIS
Description:
Creates a continually randomized patrol path which circles and intersects a given position.
Parameter(s):
_this select 0: the group to which to assign the waypoints (Group)
_this select 1: the position on which to base the patrol (Array)
_this select 2: the maximum distance between waypoints (Number)
_this select 3: (optional) debug markers on or off (Number)
_this select 4: (optional) blacklist of areas (Array)
Returns:
Boolean - success flag
Example(s):
null = [group this,(getPos this),250] execVM "BIN_taskPatrol.sqf"
null = [group this,(getPos this),250,1] execVM "BIN_taskPatrol.sqf" // Same with debug markers
-----------------------------------------------------------------------------------------------------------------------
Notes: Wolffy.au
If anyone is interested, I've made some additions to Binesi's BIN_taskPatrol script.
Random initial patrol direction - I noticed every patrol started off in the same direction, so I've randomised it.
Fixed the 2D position / findSafePos errors
Added building positions as possible patrol locations using Random Building Position Script v1.0 by Tophe of <20>stg<74>ta Ops
Added check that BIS Functions has been initialized
ArmaIIholic
-- added JTD direction normalization function
-- changed numbers for waypoints to match previous waypoints
-- randomized initial direction - Wolffy.au added only the offset
-- fixed error with building position format
-- randomized initial direction -- Wolffy.au added only the offset which had to be reduced to 180
- however this script is making full circle from wherever it starts
Edited version for DZAI (https://github.com/dayzai/DZAI)
=======================================================================================================================
*/
if (isServer) then
{
//waitUntil {!isNil "bis_fnc_init"};
_grp = _this select 0;
_pos = _this select 1;
_max_dist = _this select 2;
//_debug = if ((count _this) > 3) then {_this select 3} else {((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled})};
_unitType = _grp getVariable ["unitType",""];
_allowWater = (_unitType == "aircustom");
_searchLoot = _unitType in ["static","dynamic"];
_isVehicle = (_unitType == "landcustom");
//_grp setBehaviour "AWARE";
if (_max_dist < 75) then {_grp setSpeedMode "LIMITED"};
//_grp setCombatMode "RED";
_wpStatements = if ((_max_dist >= 100) && {_searchLoot}) then {"if ((random 3) > 2) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];} else {_nul = [(group this),100] spawn DZAI_findLootPile;};"} else {"if ((random 3) > 2) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];};"};
_wpTimeouts = if (_max_dist >= 100) then {[0, 3, 10]} else {[5, 10, 15]};
_center_x = (_pos) select 0;
_center_y = (_pos) select 1;
_center_z = (_pos) select 2;
if(isNil "_center_z")then{_center_z = 0;};
_wp_count = 4 + (floor random 3) + (floor (_max_dist / 100 ));
_angle = (360 / (_wp_count -1));
_newangle = 0;
_wp_array = [];
_slack = _max_dist / 5.5;
_completionRadius = if (_isVehicle) then {(5 + _slack) max 75} else {(5 + _slack)};
if ( _slack < 20 ) then { _slack = 20 };
_angle_offset = random 180;
while {count _wp_array < _wp_count} do
{
private ["_x1","_y1","_wp_pos", "_prepos","_bldgpos","_bldgs","_a","_b"];
_newangle = (count _wp_array * _angle) + _angle_offset;
if ((_newangle > 360) || (_newangle < 0)) then
{
_newangle = abs (abs (_newangle) - 360);
};
if ((random 1) < 0.5) then
{
_newangle = -_newangle;
if ((_newangle > 360) || (_newangle < 0)) then
{
_newangle = abs (abs (_newangle) - 360);
};
};
_x1 = _center_x - (sin _newangle * _max_dist);
_y1 = _center_y - (cos _newangle * _max_dist);
_prepos = [_x1, _y1, _center_z];
if ( isNil "_center_z" ) then {
_prepos = [_x1, _y1];
};
_wp_pos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
_a = 0 + (_wp_pos select 0);
_b = 0 + (_wp_pos select 1);
if (_searchLoot) then {
//////////////////////////////////////////////////////////////////
// The following code is an extract from Random Building Position Script v1.0 by Tophe of <20>stg<74>ta Ops
//////////////////////////////////////////////////////////////////
_bldgpos = [];
_bldgs = nearestObjects [[_a,_b,0], ["HouseBase"], 50];
{
private["_i","_y"];
_i = 0;
_y = _x buildingPos _i;
while {format["%1", _y] != "[0,0,0]"} do {
_bldgpos = _bldgpos + [_y];
_i = _i + 1;
_y = _x buildingPos _i;
};
} forEach _bldgs;
if(count _bldgpos != 0) then {_wp_pos = _bldgpos call BIS_fnc_selectRandom2;};
} else {
if (_isVehicle) then {
_nearRoads = _wp_pos nearRoads ((_max_dist/2) min 100);
_roadsCount = count _nearRoads;
_returnPos = [];
if (_roadsCount > 0) then {
_returnPos = getPosASL (_nearRoads select 0);
if (_roadsCount > 1) then {
for "_i" from 1 to (_roadsCount -1) do {
_comparePos = getPosASL (_nearRoads select _i);
if ((_comparePos distance _wp_pos) < (_returnPos distance _wp_pos)) then {
_returnPos = _comparePos;
};
};
};
_wp_pos = _returnPos;
};
};
};
_wp_array = _wp_array + [_wp_pos];
uiSleep 0.5;
};
uiSleep 1;
for "_i" from 1 to (_wp_count - 1) do
{
private ["_wp","_cur_pos"];
_cur_pos = (_wp_array select _i);
if ((!(surfaceIsWater _cur_pos)) or {_allowWater}) then {
_wp = _grp addWaypoint [_cur_pos, 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius _completionRadius;
_wp setWaypointTimeout [_wpTimeouts select 0, _wpTimeouts select 1, _wpTimeouts select 2];
_wp setWaypointStatements ["true", _wpStatements];
};
uiSleep 0.25;
};
if (_searchLoot) then {
// End back near start point and then pick a new random point
_wp1 = _grp addWaypoint [_pos, 0];
_wp1 setWaypointType "SAD";
_wp1 setWaypointCompletionRadius (_max_dist max 100);
[_grp,(count waypoints _grp)] setWaypointStatements ["true", "group this setCurrentWaypoint [(group this), (round (random 2) + 1)];"];
};
// Cycle in case we reach the end
_wp2 = _grp addWaypoint [_pos, 0];
_wp2 setWaypointType "CYCLE";
_wp2 setWaypointCompletionRadius (_max_dist max 100);
true
};

View File

@ -0,0 +1,26 @@
private["_unit","_distance","_i","_listTalk","_zombie","_targets","_pos"];
//Alert Zed's to noise of shot
_unit = _this select 0;
_distance = _this select 1;
_doRun = _this select 2;
_pos = _this select 3;
_listTalk = _pos nearEntities ["zZombie_Base",_distance];
{
if ((_unit distance _x) > 10) then {
if (_doRun) then {
_localtargets = _x getVariable ["localtargets",[]];
_remotetargets = _x getVariable ["remotetargets",[]];
_epochtargets = _x getVariable ["targets",[]];
_targets = _localtargets + _remotetargets + _epochtargets;
if (!(_unit in _targets)) then {
_remotetargets set [count _remotetargets,_unit];
_x setVariable ["remotetargets",_remotetargets,true];
_x setVariable ["targets",_remotetargets,true];
};
} else {
_x setVariable ["myDest",_pos,true];
};
};
} count _listTalk;

View File

@ -0,0 +1,104 @@
/*
DZAI_unitDeath
Description: Called when AI unit blood level drops below zero to process unit death.
Usage: [_unit,_killer] call DZAI_unitDeath;
*/
private["_coins","_values","_victim","_killer","_unitGroup","_unitType","_launchWeapon","_launchAmmo","_deathType","_groupIsEmpty","_unitsAlive","_vehicle","_groupSize"];
_victim = _this select 0;
_killer = _this select 1;
_deathType = if ((count _this) > 2) then {_this select 2} else {"bled"};
if (_victim getVariable ["deathhandled",false]) exitWith {};
_victim setVariable ["deathhandled",true];
_vehicle = (vehicle _victim);
_unitGroup = (group _victim);
_victim setDamage 1;
_victim removeAllEventHandlers DZAI_healthType;
//Check number of units alive, preserve group immediately if empty.
_unitsAlive = ({alive _x} count (units _unitGroup));
_groupIsEmpty = if (_unitsAlive == 0) then {_unitGroup call DZAI_protectGroup; true} else {false};
//Update group size counter
_groupSize = (_unitGroup getVariable ["GroupSize",0]);
if (_groupSize > 0) then {_unitGroup setVariable ["GroupSize",(_groupSize - 1)]};
//Retrieve group type
_unitType = _unitGroup getVariable ["unitType",""];
call {
if (_unitType == "static") exitWith {
[_victim,_killer,_unitGroup,_groupIsEmpty] call DZAI_AI_killed_static;
0 = [_victim,_killer,_unitGroup,_unitType,_unitsAlive] call DZAI_AI_killed_all;
};
if (_unitType == "dynamic") exitWith {
[_victim,_killer,_unitGroup,_groupIsEmpty] call DZAI_AI_killed_dynamic;
0 = [_victim,_killer,_unitGroup,_unitType,_unitsAlive] call DZAI_AI_killed_all;
};
if (_unitType == "randomspawn") exitWith {
[_victim,_killer,_unitGroup,_groupIsEmpty] call DZAI_AI_killed_random;
0 = [_victim,_killer,_unitGroup,_unitType,_unitsAlive] call DZAI_AI_killed_all;
};
if (_unitType in ["air","aircustom"]) exitWith {
[_victim,_unitGroup] call DZAI_AI_killed_air;
};
if (_unitType in ["land","landcustom"]) exitWith {
0 = [_victim,_killer,_unitGroup,_unitType] call DZAI_AI_killed_all;
[_victim,_unitGroup,_groupIsEmpty] call DZAI_AI_killed_land;
};
if (_unitType == "aircrashed") exitWith {};
if (_groupIsEmpty) then {
_unitGroup setVariable ["GroupSize",-1];
};
};
if !(isNull _victim) then {
//_launchWeapon = (secondaryWeapon _victim);
//if (_launchWeapon in DZAI_launcherTypes) then {
// _launchAmmo = getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
// _victim removeWeapon _launchWeapon;
// _victim removeMagazines _launchAmmo;
//};
if (_deathType == "shothead") then { //no need for isplayer check since "shothead" is only possible if killer is a player
_nul = _killer spawn {
_headshots = _this getVariable ["headShots",0];
_headshots = _headshots + 1;
_this setVariable ["headShots",_headshots,true];
};
};
if (_victim getVariable ["removeNVG",true]) then {
_victim removeWeapon "NVGoggles";
};
_victim spawn DZAI_deathFlies;
_bodyName = _victim getVariable ["bodyName","unknown"];
_victim setVariable ["bodyName",_bodyName];
_victim setVariable ["deathType",_deathType,true];
_victim setVariable ["DZAI_deathTime",diag_tickTime];
_victim setVariable ["unconscious",true];
if (Z_SingleCurrency && {DZAI_hasCoins select 0}) then {
_values = DZAI_hasCoins select 1;
_coins = ceil(random (_values select 1)) max (_values select 0);
_victim setVariable ["cashMoney",_coins,true];
};
if (_vehicle == (_unitGroup getVariable ["assignedVehicle",objNull])) then {
_victim setPosASL (getPosASL _victim);
};
if ((combatMode _unitGroup) == "BLUE") then {_unitGroup setCombatMode "RED"};
//[_victim] joinSilent grpNull;
if (DZAI_deathMessages && {isPlayer _killer}) then {
_nul = [_killer,_bodyName] spawn DZAI_sendKillMessage;
};
};
_victim

View File

@ -0,0 +1,16 @@
private["_unit","_ammo","_audible","_distance"];
//[unit, weapon, muzzle, mode, ammo, magazine]
_unit = _this select 0;
_ammo = _this select 4;
if ((diag_tickTime - (_unit getVariable ["lastFired",0])) > 5) then {
//Calculate audible range of fired bullet
_audible = getNumber (configFile >> "CfgAmmo" >> _ammo >> "audibleFire");
_caliber = getNumber (configFile >> "CfgAmmo" >> _ammo >> "caliber");
_distance = round(_audible * 10 * _caliber);
[_unit,_distance/2,true,(ASLtoATL getPosASL _unit)] spawn DZAI_alertZombies;
_unit setVariable ["lastFired",diag_tickTime];
};
true

View File

@ -0,0 +1,111 @@
private ["_unit","_pistol","_pistols","_weapongrade","_magazine","_currentWeapon","_toolselect","_chance","_tool","_toolsArray","_loot"];
_unit = _this select 0;
_weapongrade = _this select 1;
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: AI killed by player at %1. Generating loot with weapongrade %2.",mapGridPosition _unit,_weapongrade];};
_loot = [];
if (_unit getVariable ["CanGivePistol",true]) then {
_pistols = missionNamespace getVariable ["DZAI_Pistols"+str(_weapongrade),DZAI_Pistols0+DZAI_Pistols1+DZAI_Pistols2+DZAI_Pistols3];
_pistol = _pistols call BIS_fnc_selectRandom2;
_magazine = getArray (configFile >> "CfgWeapons" >> _pistol >> "magazines") select 0;
_unit addMagazine _magazine;
_unit addWeapon _pistol;
if (DZAI_debugLevel > 1) then {
_loot set [count _loot,_pistol];
_loot set [count _loot,_magazine];
};
};
//Add consumables, medical items, and miscellaneous items
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Clear backpack cargo in case there are items
clearMagazineCargoGlobal _unit;
//Add one guaranteed Bandage to inventory
_unit addMagazine "ItemBandage";
//Add edible items to inventory
for "_i" from 1 to DZAI_invedibles do {
if (DZAI_chanceEdibles call DZAI_chance) then {
_invedible = DZAI_Edibles call BIS_fnc_selectRandom2;
_unit addMagazine _invedible;
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_invedible];};
};
};
//Add edible items to backpack
for "_i" from 1 to DZAI_bpedibles do {
if (DZAI_chanceEdibles call DZAI_chance) then {
_bpedible = DZAI_Edibles call BIS_fnc_selectRandom2;
(unitBackpack _unit) addMagazineCargoGlobal [_bpedible, 1];
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_bpedible];};
};
};
//Chance to add miscellaneous item (Small) to backpack
for "_i" from 1 to DZAI_numMiscItemS do {
if (DZAI_chanceMiscItemS call DZAI_chance) then {
_miscItemS = DZAI_MiscItemS call BIS_fnc_selectRandom2;
(unitBackpack _unit) addMagazineCargoGlobal [_miscItemS,1];
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_miscItemS];};
};
};
if (_weapongrade > 0) then {
//Chance to add miscellaneous item (Large) to backpack - only if backpack capacity greater than 6
if ((getNumber (configFile >> "CfgVehicles" >> (str (unitBackpack _unit)) >> "transportMaxMagazines")) > 6) then {
for "_i" from 1 to DZAI_numMiscItemL do {
if (DZAI_chanceMiscItemL call DZAI_chance) then {
_miscItemL = DZAI_MiscItemL call BIS_fnc_selectRandom2;
(unitBackpack _unit) addMagazineCargoGlobal [_miscItemL,1];
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_miscItemL];};
};
};
};
//Add medical items to backpack
for "_i" from 1 to DZAI_bpmedicals do {
if (DZAI_chanceMedicals call DZAI_chance) then {
_bpmedical = DZAI_Medicals2 call BIS_fnc_selectRandom2;
(unitBackpack _unit) addMagazineCargoGlobal [_bpmedical, 1];
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_bpmedical];};
};
};
//Add medical items to inventory
for "_i" from 1 to DZAI_invmedicals do {
if (DZAI_chanceMedicals call DZAI_chance) then {
_invmedical = DZAI_Medicals1 call BIS_fnc_selectRandom2;
_unit addMagazine _invmedical;
if (DZAI_debugLevel > 1) then {_loot set [count _loot,_invmedical];};
};
};
if (DZAI_modName == "epoch") then {
_barsAdded = 0;
{
if (_barsAdded >= DZAI_metalBarNum) exitWith {};
if (((_x select 1) call DZAI_chance) && {[(_x select 0),"magazine"] call DZAI_checkClassname}) then {
_unit addMagazine (_x select 0);
_barsAdded = _barsAdded + 1;
if (DZAI_debugLevel > 1) then {_loot set [count _loot,(_x select 0)];};
}
} count DZAI_metalBars;
};
};
//Add tool items
////////////////////////////////////////////////////////////////////////////////////////////////////////////
_toolsArray = if (_weapongrade < 2) then {DZAI_tools0} else {DZAI_tools1};
{
if (((_x select 1) call DZAI_chance) && {[(_x select 0),"weapon"] call DZAI_checkClassname}) then {
_unit addWeapon (_x select 0);
if (DZAI_debugLevel > 1) then {_loot set [count _loot,(_x select 0)];};
}
} count _toolsArray;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Generated loot for AI death: %1",_loot];};

View File

@ -0,0 +1,25 @@
private ["_vehicle","_victim","_unitGroup","_parachuted"];
_victim = _this select 0;
_unitGroup = _this select 1;
_vehicle = (_unitGroup getVariable ["assignedVehicle",objNull]);
if (alive _vehicle) then {
if (_victim getVariable ["isDriver",false]) then {
_unitGroup setVariable ["unitType","aircrashed"]; //prevent this case from being run for ejected non-pilot units
_parachuted = [_vehicle] call DZAI_parachuteOut;
if (_parachuted) then {
_nul = _vehicle spawn {
_this setFuel 0;
_this setVehicleAmmo 0;
uiSleep 2.5;
_this setDamage 1;
};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI %1 pilot unit %2 killed, ejecting surving crew.",(typeOf _vehicle),(typeOf _victim)];};
};
} else {
0 = [_victim,(_unitGroup getVariable ["weapongrade",1])] spawn DZAI_addLoot;
};
};
true

View File

@ -0,0 +1,46 @@
/*
fnc_banditAIKilled
Description: Adds loot to AI corpse if killed by a player. Script is shared between all infantry-type AI units.
Usage: [_victim,_killer,_unitGroup,_unitType] call DZAI_AI_killed_all;
*/
private["_victim","_killer","_unitGroup","_unitType","_groupSize","_unitsAlive"];
_victim = _this select 0;
_killer = _this select 1;
_unitGroup = _this select 2;
_unitType = _this select 3;
_unitsAlive = if ((count _this) > 4) then {_this select 4} else {0};
if (isPlayer _killer) then {
_weapongrade = _unitGroup getVariable ["weapongrade",1];
0 = [_victim,_weapongrade] spawn DZAI_addLoot;
0 = [_killer,_victim,"banditKills"] call DZAI_countKills;
if (_unitsAlive > 0) then {
_unitGroup reveal [vehicle _killer,4];
_unitGroup setFormDir ([(leader _unitGroup),_killer] call BIS_fnc_dirTo);
(units _unitGroup) doTarget (vehicle _killer);
(units _unitGroup) doFire (vehicle _killer);
if (DZAI_findKiller) then {0 = [_killer,_unitGroup] spawn DZAI_huntKiller};
if (DZAI_lastManStanding && {_unitsAlive == 1}) then {0 = _unitGroup spawn DZAI_skillBoost;}; //"Last man standing" mode on
if (DZAI_debugLevel > 0) then {diag_log format["DZAI Debug: AI group %1 killed, %2 units left alive in group.",_unitGroup,_unitsAlive];};
};
} else {
if (_killer == _victim) then {
removeAllWeapons _victim; //Clear unit inventory if death is caused by collision.
{_victim removeMagazines _x} count (magazines _victim);
removeBackpack _victim;
};
};
//Force death animation if unit has pistol and conscious to avoid "standing while dead" bug.
if ((vehicle _victim) == _victim) then {
if !((_victim getVariable ["CanGivePistol",true]) && {(_victim getVariable ["unconscious",false])}) then {
_anim = if ((animationState _victim) in ["amovppnemrunsnonwnondf","amovppnemstpsnonwnondnon","amovppnemstpsraswrfldnon","amovppnemsprslowwrfldf","aidlppnemstpsnonwnondnon0s","aidlppnemstpsnonwnondnon01"]) then {"adthppnemstpsraswpstdnon_2"} else {"adthpercmstpslowwrfldnon_4"};
_nul = [objNull, _victim, rSWITCHMOVE, _anim] call RE;
};
};
true

View File

@ -0,0 +1,14 @@
private ["_victim","_killer","_groupIsEmpty","_trigger","_unitGroup"];
_victim = _this select 0;
_killer = _this select 1;
_unitGroup = _this select 2;
_groupIsEmpty = _this select 3;
_trigger = _unitGroup getVariable ["trigger",DZAI_defaultTrigger];
if (_groupIsEmpty) then {
[_trigger,true] spawn fnc_despawnBandits_dynamic; //force despawning even if players are present in trigger area.
};
true

View File

@ -0,0 +1,37 @@
private ["_victim","_vehicle","_unitGroup","_groupIsEmpty"];
_victim = _this select 0;
_unitGroup = _this select 1;
_groupIsEmpty = _this select 2;
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
if (_groupIsEmpty) then {
if (_vehicle isKindOf "LandVehicle") then {
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","Killed"];
[_unitGroup,_vehicle] call DZAI_respawnAIVehicle;
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI vehicle patrol destroyed, adding vehicle %1 to cleanup queue.",(typeOf _vehicle)];};
};
_unitGroup setVariable ["GroupSize",-1];
} else {
if (_victim getVariable ["isDriver",false]) then {
_groupUnits = (units _unitGroup) - [_victim];
_newDriver = _groupUnits call BIS_fnc_selectRandom2; //Find another unit to serve as driver
if (!isNil "_newDriver") then {
_nul = [_newDriver,_vehicle] spawn {
private ["_newDriver","_vehicle"];
_newDriver = _this select 0;
_vehicle = _this select 1;
unassignVehicle _newDriver;
_newDriver assignAsDriver _vehicle;
if (_newDriver in _vehicle) then {
_newDriver moveInDriver _vehicle;
};
[_newDriver] orderGetIn true;
_newDriver setVariable ["isDriver",true];
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Replaced driver unit for group %1 vehicle %2.",(group _newDriver),(typeOf _vehicle)];};
};
};
};
};
true

View File

@ -0,0 +1,14 @@
private ["_victim","_killer","_groupIsEmpty","_trigger","_unitGroup"];
_victim = _this select 0;
_killer = _this select 1;
_unitGroup = _this select 2;
_groupIsEmpty = _this select 3;
_trigger = _unitGroup getVariable ["trigger",DZAI_defaultTrigger];
if (_groupIsEmpty) then {
[_trigger,true] spawn fnc_despawnBandits_random; //force despawning even if players are present in trigger area.
};
true

View File

@ -0,0 +1,55 @@
/*
fnc_staticAIDeath
Usage: [_victim,_killer,_unitGroup] call DZAI_AI_killed_static;
Description: Script is called when an AI unit is killed, and waits for the specified amount of time before respawning the unit into the same group it was part of previously.
If the killed unit was the last surviving unit of its group, a dummy AI unit is created to occupy the group until a dead unit in the group is respawned.
*/
private ["_victim","_killer","_unitGroup","_trigger","_dummy","_groupIsEmpty"];
_victim = _this select 0;
_killer = _this select 1;
_unitGroup = _this select 2;
_groupIsEmpty = _this select 3;
_trigger = _unitGroup getVariable ["trigger",DZAI_defaultTrigger];
if (_groupIsEmpty) then {
if (_trigger getVariable ["respawn",true]) then {
_respawnCount = _trigger getVariable ["respawnLimit",-1];
if (_respawnCount != 0) then {
[0,_trigger,_unitGroup] call fnc_respawnHandler; //If there are still respawns possible... respawn the group
if (_respawnCount > -1) then {
_trigger setVariable ["respawnLimit",(_respawnCount - 1)]; //If respawns are limited, decrease respawn counter
if (DZAI_debugLevel > 0) then {diag_log format["DZAI Debug: Respawns remaining for group %1: %2.",_unitGroup,(_unitGroup getVariable ["respawnLimit",-1])];};
};
} else {
_trigger setVariable ["permadelete",true]; //deny respawn and delete trigger on next despawn.
};
} else {
if ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled}) then {deleteMarker str(_trigger)};
_nul = _trigger spawn {
_trigger = _this;
_trigger setTriggerStatements ["this","true","false"]; //Disable trigger from activating or deactivating while cleanup is performed
if (DZAI_debugLevel > 0) then {diag_log format["DZAI Debug: Deleting custom-defined AI spawn %1 at %2 in 30 seconds.",triggerText _trigger, mapGridPosition _trigger];};
uiSleep 30;
{
//_x call DZAI_deleteGroup;
_x setVariable ["GroupSize",-1];
} forEach (_trigger getVariable ["GroupArray",[]]);
deleteMarker (_trigger getVariable ["spawnmarker",""]);
[_trigger,"DZAI_staticTriggerArray"] call DZAI_updateSpawnCount;
deleteVehicle _trigger;
};
};
} else {
if (!(_trigger getVariable ["respawn",true])) then {
_maxUnits = _trigger getVariable ["maxUnits",[0,0]]; //Reduce maximum AI for spawn trigger for each AI killed for non-respawning spawns.
_maxUnits set [0,(_maxUnits select 0) - 1];
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: MaxUnits variable for group %1 set to %2.",_unitGroup,_maxUnits];};
};
};
true

View File

@ -0,0 +1,57 @@
private ["_unit","_weapongrade","_weapons","_weapon","_magazine","_backpacks","_gadgetsArray","_backpack","_gadget","_inventory"];
_unit = _this select 0;
_weapongrade = _this select 1;
if (_unit getVariable ["loadoutDone",false]) exitWith {diag_log format ["DZAI Error: Unit already has loadout! (%1)",__FILE__];};
if !(_weapongrade in DZAI_weaponGradesAll) then {
_weapongradeInvalid = _weapongrade;
_weapongrade = DZAI_weaponGrades call BIS_fnc_selectRandom2;
diag_log format ["DZAI Error: Invalid weapongrade provided: %1. Generating new weapongrade value: %2. (%3)",_weapongradeInvalid,_weapongrade,__FILE__];
};
if ((count (weapons _unit)) > 0) then {
removeAllWeapons _unit;
{_unit removeWeapon _x} count ["ItemMap","ItemGPS","ItemCompass","ItemRadio","ItemWatch"];
};
_weapons = missionNamespace getVariable ["DZAI_Rifles"+str(_weapongrade),DZAI_Rifles1+DZAI_Rifles2+DZAI_Rifles3];
if ((_weapongrade == 0) && {(0.25 call DZAI_chance)}) then {
_weapons = missionNamespace getVariable ("DZAI_Pistols" + str(floor(random 2)));
};
_backpacks = missionNamespace getVariable ["DZAI_Backpacks"+str(_weapongrade),DZAI_Backpacks1+DZAI_Backpacks2+DZAI_Backpacks3];
//Select weapon and backpack
_weapon = _weapons call BIS_fnc_selectRandom2;
_backpack = _backpacks call BIS_fnc_selectRandom2;
//Add weapon, ammunition, and backpack
_magazine = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines") select 0;
_unit addMagazine _magazine;
_unit addWeapon _weapon;
_unit selectWeapon _weapon;
_unit addBackpack _backpack;
if ((getNumber (configFile >> "CfgWeapons" >> _weapon >> "type")) == 2) then {_unit setVariable ["CanGivePistol",false]};
if ((getNumber (configFile >> "CfgMagazines" >> _magazine >> "count")) < 8) then {_unit addMagazine _magazine};
_gadgetsArray = if (_weapongrade > 1) then {DZAI_gadgets1} else {DZAI_gadgets0};
for "_i" from 0 to ((count _gadgetsArray) - 1) do {
if (((_gadgetsArray select _i) select 1) call DZAI_chance) then {
_gadget = ((_gadgetsArray select _i) select 0);
_unit addWeapon _gadget;
};
};
//If unit has weapongrade 2 or 3 and was not given NVGs, give the unit temporary NVGs which will be removed at death. Set DZAI_tempNVGs to true in variables config to enable temporary NVGs.
if (DZAI_tempNVGs) then {
if (!(_unit hasWeapon "NVGoggles") && {(_weapongrade > 0)} && {(daytime < 6 || daytime > 20)}) then {
_nvg = _unit call DZAI_addTempNVG;
if (DZAI_debugLevel > 1) then {diag_log "DZAI Extended Debug: Generated temporary NVGs for AI.";};
};
};
_unit setVariable ["loadoutDone",true];
_unit setVariable ["loadout",[[_weapon],[_magazine]]];
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Created loadout for unit %1 (weapongrade: %2): [%3,%4,%5].",_unit,_weapongrade,_weapon,_magazine,_backpack];};
true

View File

@ -0,0 +1,45 @@
//Knocks an AI unit unconscious for x seconds - determines the correct animation to use, and returns unit to standing state after waking.
private ["_unit","_anim","_hit","_knockoutTime","_launchWeapon","_launchAmmo"];
_unit = _this select 0;
_hit = _this select 1;
if ((vehicle _unit) == _unit) then { //do not allow vehicle AI to be knocked unconscious.
if ((animationState _unit) in ["amovppnemrunsnonwnondf","amovppnemstpsnonwnondnon","amovppnemstpsraswrfldnon","amovppnemsprslowwrfldf","aidlppnemstpsnonwnondnon0s","aidlppnemstpsnonwnondnon01"]) then {
_anim = "adthppnemstpsraswpstdnon_2";
} else {
_anim = "adthpercmstpslowwrfldnon_4";
};
_unit switchMove _anim;
_nul = [objNull, _unit, rSWITCHMOVE, _anim] call RE;
{_unit disableAI _x} forEach ["TARGET","MOVE","FSM"];
//diag_log "DEBUG :: AI unit is unconscious.";
//_launchWeapon = (secondaryWeapon _unit);
//if (_launchWeapon in DZAI_launcherTypes) then {
// _launchAmmo = getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
// _unit removeWeapon _launchWeapon;
// _unit removeMagazines _launchAmmo;
// _loadout = _unit getVariable ["loadout",[]];
// (_loadout select 0) resize 1;
// (_loadout select 1) resize 1;
// //if (_launchWeapon in (weapons _unit)) then {diag_log format ["Warning: Unable to remove launcher weapon %1 from unit %2.",_launchWeapon,_unit]};
// //if (_launchAmmo in (magazines _unit)) then {diag_log format ["Warning: Unable to remove launcher ammo %1 from unit %2.",_launchWeapon,_unit]};
// //if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Unit %1 knocked out, removed launcher weapon %2 and ammo %3.",_unit,_launchWeapon,_launchAmmo]};
//};
_knockoutTime = if (_hit == "head_hit") then {40} else {20};
//diag_log format ["DEBUG :: Knocked out AI %1 for %2 seconds.",_unit,_knockoutTime];
uiSleep _knockoutTime;
if (alive _unit) then {
_nul = [objNull, _unit, rSWITCHMOVE, "AmovPpneMstpSnonWnonDnon_healed"] call RE;
_unit switchMove "AmovPpneMstpSnonWnonDnon_healed";
uiSleep 1.75;
{_unit enableAI _x} forEach ["TARGET","MOVE","FSM"];
_unit setVariable ["unconscious",false];
};
} else {
uiSleep 10;
_unit setVariable ["unconscious",false];
};

View File

@ -0,0 +1,55 @@
private ["_maxRandomSpawns","_debugMarkers","_triggerArea","_attempts","_trigPos","_trigger","_markername","_marker"];
_maxRandomSpawns = _this;
_debugMarkers = ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled});
_triggerArea = 600;
//waitUntil {sleep 1; !isNil "DZAI_locations_ready"};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Attempting to place %1 random spawns on the map...",_maxRandomSpawns];};
for "_i" from 1 to _maxRandomSpawns do {
_attempts = 0;
_keepSearching = true;
_trigPos = [0,0,0];
while {
_keepSearching
} do {
_trigPos = ["DZAI_centerMarker",false,DZAI_randAreaBlacklist] call SHK_pos;
_attempts = _attempts + 1;
_keepSearching = ((count ((nearestLocations [_trigPos, ["Strategic"], 650])) > 0) && {_attempts < 3});
if (_keepSearching) then {uiSleep 0.25};
};
if (_attempts < 3) then {
_trigger = createTrigger ["EmptyDetector",_trigPos];
_location = createLocation ["Strategic",(getPosASL _trigger),600,600]; //Create temporary dynamic spawn blacklist area
_trigger setVariable ["triggerLocation",_location];
[_trigger,"DZAI_randTriggerArray"] call DZAI_updateSpawnCount;
_trigger setTriggerArea [_triggerArea, _triggerArea, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [5, 5, 5, true];
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;","0 = [300,thisTrigger,thisList] call fnc_spawnBandits_random;", "[thisTrigger] spawn fnc_despawnBandits_random;"];
if (_debugMarkers) then {
_markername = str(_trigger);
_marker = createMarker[_markername,_trigPos];
_marker setMarkerShape "ELLIPSE";
_marker setMarkerType "Flag";
_marker setMarkerBrush "SOLID";
_marker setMarkerSize [_triggerArea, _triggerArea];
_marker setMarkerColor "ColorYellow";
_marker setMarkerAlpha 0.6;
DZAI_mapMarkerArray set [(count DZAI_mapMarkerArray),_marker];
};
_trigger setTriggerText format ["Random Spawn at %1",(mapGridPosition _trigger)];
_trigger setVariable ["timestamp",diag_tickTime];
if (DZAI_debugLevel > 0) then {diag_log format["DZAI Debug: Random spawn %1 of %2 placed at %3 (Retries: %4).",_i,_maxRandomSpawns,_trigPos,_attempts];};
//DZAI_randTriggerArray set [(count DZAI_randTriggerArray),_trigger];
} else {
if (DZAI_debugLevel > 0) then {diag_log format["DZAI Debug: Could not find suitable location to place random spawn %1 of %2.",_i,_maxRandomSpawns];};
};
uiSleep 3;
};

View File

@ -0,0 +1,9 @@
private["_trigger"];
_trigger = _this;
DZAI_dynTriggerArray = DZAI_dynTriggerArray - [_trigger];
if ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled}) then {deleteMarker str(_trigger)};
deleteVehicle _trigger;
false

View File

@ -0,0 +1,14 @@
private["_trigger","_triggerLocation"];
_trigger = _this;
[_trigger,"DZAI_randTriggerArray"] call DZAI_updateSpawnCount;
if ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled}) then {deleteMarker (str _trigger)};
_triggerLocation = _trigger getVariable "triggerLocation";
deleteLocation _triggerLocation;
//_triggerLocation setVariable ["deletetime",(diag_tickTime + 900)];
//DZAI_tempBlacklist set [(count DZAI_tempBlacklist),_triggerLocation];
deleteVehicle _trigger;
false

View File

@ -0,0 +1,63 @@
private ["_classname","_checkType","_result","_config","_banString","_check","_configIndex"];
_classname = _this select 0;
_checkType = _this select 1;
_result = false;
_configIndex = -1;
_checkType = (toLower _checkType);
_startTime = diag_tickTime;
call {
if (_checkType == "weapon") exitWith {
if (_classname in (DZAI_checkedClassnames select 0)) then {
_result = true;
} else {
if (!(_classname in (DZAI_invalidClassnames select 0))) then {
_config = "CfgWeapons";
_banString = "bin\config.bin/CfgWeapons/FakeWeapon";
_configIndex = 0;
};
};
};
if (_checkType == "magazine") exitWith {
if (_classname in (DZAI_checkedClassnames select 1)) then {
_result = true;
} else {
if (!(_classname in (DZAI_invalidClassnames select 0))) then {
_config = "CfgMagazines";
_banString = "bin\config.bin/CfgMagazines/FakeMagazine";
_configIndex = 1;
};
};
};
if (_checkType == "vehicle") exitWith {
if (_classname in (DZAI_checkedClassnames select 2)) then {
_result = true;
} else {
if (!(_classname in (DZAI_invalidClassnames select 0))) then {
_config = "CfgVehicles";
_banString = "bin\config.bin/CfgVehicles/Banned";
_configIndex = 2;
};
};
};
diag_log format ["DZAI Error: Attempted to check %1 as an invalid classname type! Provided type: %2. Valid types: weapon, magazine, vehicle.",_checkType];
};
if (_configIndex > -1) then {
_check = (str(inheritsFrom (configFile >> _config >> _classname)));
_classnameArray = [];
if ((_check != "") && {(_check != _banString)} && {(getNumber (configFile >> _config >> _classname >> "scope")) != 0}) then {
_classnameArray = DZAI_checkedClassnames;
_result = true;
} else {
_classnameArray = DZAI_invalidClassnames;
diag_log format ["DZAI Warning: %1 is an invalid %2 classname!",_classname,_checkType];
};
(_classnameArray select _configIndex) set [(count (_classnameArray select _configIndex)),_classname]; //Classname now known to be either valid or invalid, no need to check it again
//;diag_log format ["DEBUG :: Classname check result: %1. ClassnameArray: %2.",_result,_classnameArray];
};
//diag_log format ["DEBUG :: Classname %1 (check result: %2) completed in %3 seconds.",_classname,_result,diag_tickTime - _startTime];
_result

View File

@ -0,0 +1,13 @@
private ["_killer","_victim","_killType","_killCount"];
_killer = _this select 0;
_victim = _this select 1;
_killType = _this select 2;
_killCount = _killer getVariable [_killType,0];
_killer setVariable [_killType,(_killCount +1),true];
if (DZAI_humanityGain != 0) then {
_humanity = _killer getVariable["humanity",0];
_humanity = _humanity + DZAI_humanityGain;
_killer setVariable["humanity",_humanity,true];
};

View File

@ -0,0 +1,52 @@
/*Syntax: [
_spawnMarker, //Circular marker defining patrol radius.
[_minAI,_addAI], //(Optional, default [1,1]) Minimum and maximum bonus amount of AI units per group.
_positionArray, //(Optional, default []): Array of markers defining possible spawn points. If omitted or left empty, nearby buildings within 250m radius will be used as spawn points.
_equipType, //(Optional, default 1): Number between 0-3. Defines AI weapon selection and skill parameters.
_numGroups //(Optional, default 1): Number of AI groups to spawn using the above parameters.
] call DZAI_static_spawn;
*/
private ["_spawnMarker","_minAI","_addAI","_positionArray","_equipType","_numGroups","_patrolDist","_onActStatements","_trigger","_abort"];
_spawnMarker = _this select 0;
if ((getMarkerColor _spawnMarker) == "") exitWith {diag_log format ["DZAI Error: Static spawn marker %1 does not exist!",_spawnMarker];};
if ((markerAlpha _spawnMarker) > 0) then {_spawnMarker setMarkerAlpha 0};
_abort = true;
if ((count _this) > 1) then {
_minAI = (_this select 1) select 0;
_addAI = (_this select 1) select 1;
if ((_minAI + _addAI) > 0) then {
_abort = false;
};
} else {
_minAI = 1;
_addAI = 1;
};
if (_abort) exitWith {
diag_log format ["DZAI Error: Zero AI amount for spawn area %1. Spawn area not created. (%2)",_spawnMarker,__FILE__];
objNull
};
_positionArray = if ((count _this) > 2) then {_this select 2} else {[]};
_equipType = if ((count _this) > 3) then {_this select 3} else {1};
_numGroups = if ((count _this) > 4) then {_this select 4} else {1};
_patrolDist = (getMarkerSize _spawnMarker) select 0;
if !(_equipType in [0,1,2,3]) then {_equipType = 1};
_onActStatements = format ["_nul = [%1,%2,%3,thisTrigger,%4,%5,%6] call DZAI_spawnBandits_init;",_minAI,_addAI,_patrolDist,_positionArray,_equipType,_numGroups];
_trigger = createTrigger ["EmptyDetector", getMarkerPos(_spawnMarker)];
_trigger setTriggerArea [600, 600, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [10, 10, 10, true];
_trigger setTriggerText _spawnMarker;
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;",_onActStatements,""];
deleteMarker _spawnMarker;
_trigger

View File

@ -0,0 +1,30 @@
private ["_spawnMarker","_patrolRadius","_trigStatements","_trigger","_respawn","_weapongrade","_totalAI","_respawnTime"];
_spawnMarker = _this select 0;
if ((typeName _spawnMarker) != "STRING") exitWith {diag_log "DZAI Error: Marker string not given!"};
_totalAI = if ((typeName (_this select 1)) == "SCALAR") then {_this select 1} else {1};
_weapongrade = if ((typeName (_this select 2)) == "SCALAR") then {_this select 2} else {1};
_respawn = if ((count _this) > 3) then {if ((typeName (_this select 3)) == "BOOL") then {_this select 3} else {true}} else {true};
_respawnTime = if ((count _this) > 4) then {if ((typeName (_this select 4)) == "SCALAR") then {_this select 4} else {0}} else {0};
_patrolRadius = ((((getMarkerSize _spawnMarker) select 0) min ((getMarkerSize _spawnMarker) select 1)) min 300);
_trigStatements = format ["0 = [%1,0,%2,thisTrigger,%3,%4] call fnc_spawnBandits_custom;",_totalAI,_patrolRadius,_weapongrade,_spawnMarker];
_trigger = createTrigger ["EmptyDetector", getMarkerPos(_spawnMarker)];
_trigger setTriggerArea [600, 600, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [5, 5, 5, true];
_trigger setTriggerText _spawnMarker;
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;",_trigStatements,"0 = [thisTrigger] spawn fnc_despawnBandits;"];
_trigger setVariable ["respawn",_respawn];
_trigger setVariable ["spawnmarker",_spawnMarker];
if (_respawnTime > 0) then {_trigger setVariable ["respawnTime",_respawnTime];};
//diag_log format ["DEBUG :: %1",_trigStatements];
if ((markerAlpha _spawnMarker) > 0) then {
_spawnMarker setMarkerAlpha 0;
};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Created custom spawn area %1 at %2 with %3 AI units, weapongrade %4, respawn %5, respawn time %6.",_spawnMarker,mapGridPosition _trigger,_totalAI,_weapongrade,_respawn,_respawnTime];};
_trigger

View File

@ -0,0 +1,83 @@
private["_unit","_hit","_damage","_source","_ammo","_unithealth","_scale","_blooddamage","_newbloodlevel","_headShots","_partdamage","_deathType","_headHit"];
/*
Damage Handler script modified for DZAI
Simulates DayZ's player health system for individual AI units
*/
_unit = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
_source = _this select 3; //The source unit that caused the damage.
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
if ((group _unit) == (group _source)) then {_damage = (_damage/10)}; //Reduce friendly fire and collision damage.
//if (isNil {_unit getVariable "unithealth"}) then {_unit setVariable ["unithealth",[12000,0,false]]}; //Reset initial health stats if not found
_unithealth = _unit getVariable "unithealth"; // Retrieve unit's health statistics
_scale = 300;
_deathType = "bled";
_headHit = (_hit == "head_hit");
if (_damage > 0.4) then {
//Calculate locational damage
call {
if (_hit == "legs") exitWith {
_partdamage = (_unithealth select 1) + (_damage/2);
_unithealth set [1,_partdamage]; //Record leg damage internally
if ((_partdamage > 0.99) && {!(_unithealth select 2)}) then {
_nul = _unit spawn {_this setHit["legs",1]}; //Break legs when enough damage taken
[nil,_unit,rSAY,["z_fracture_1",40]] call RE;
_unithealth set [2,true];
};
};
if (_headHit) exitWith {
_scale = _scale + 500;
};
};
//additional damage if attacker is a player
if (isPlayer _source) then {
_scale = _scale + 800;
if (_headHit) then {
if (_damage > 1.5) then {
_deathType = "shothead";
_scale = 12000; //sufficient head shot damage causes instant death
} else {
_scale = _scale + 500;
};
};
};
//special death types
call {
if (_ammo isKindOf "GrenadeBase") exitWith {
_scale = _scale + 200;
if (_damage > 4) then {
_deathType = "explosion";
_scale = 12000; //sufficient grenade damage causes instant death
};
};
if ((_ammo isKindOf "B_127x107_Ball") or (_ammo isKindOf "B_127x99_Ball")) exitWith {
_scale = _scale + 200;
if (_damage > 4) then {
_deathType = "shotheavy";
_scale = 12000; //sufficient high calibre damage causes instant death
};
};
};
_blooddamage = (_damage * _scale);
_newbloodlevel = (_unithealth select 0) - _blooddamage;
_unithealth set [0,_newbloodlevel];
//Uncomment the following line to report blood damage to rpt log
//diag_log format ["DEBUG :: Unit %1 took %2 blood damage in part %3 by ammo %4 (Blood level: %5).",_unit,_blooddamage,_hit,_ammo,_newbloodlevel];
if (_newbloodlevel < 0) then {
_nul = [_unit,_source,_deathType] call DZAI_unitDeath;
//diag_log format ["DEBUG :: %1 was killed by %2 from %3m. Cause: %4.",_unit,_source,(_unit distance _source),_deathType];
} else {
if (!(_unit getVariable ["unconscious",false]) && {((_damage > 2) || {((_damage > 0.5) && (_hit == "head_hit"))})}) then {_nul = [_unit,_hit] spawn DZAI_unconscious; _unit setVariable ["unconscious",true];};
};
};
0

View File

@ -0,0 +1,149 @@
/*
fn_findKiller
Description: If an AI unit is killed, surviving members of their group will aggressively pursue the killer for a set amount of time. After this amount of time has passed, the group will return to their patrol state.
Last updated: 2:00 AM 7/1/2014
*/
private ["_unitGroup","_targetPlayer","_startPos","_chaseDistance"];
_targetPlayer = _this select 0;
_unitGroup = _this select 1;
//Disable killer-finding for dynamic AI in hunting mode
if (_unitGroup getVariable ["seekActive",false]) exitWith {};
//If group is already pursuing player and target player has killed another group member, then extend pursuit time.
if (((_unitGroup getVariable ["pursuitTime",0]) > 0) && {((_unitGroup getVariable ["targetKiller",""]) == (name _targetPlayer))}) exitWith {
_unitGroup setVariable ["pursuitTime",((_unitGroup getVariable ["pursuitTime",0]) + 20)];
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Pursuit time +20 sec for Group %1 (Target: %2) to %3 seconds (fn_findKiller).",_unitGroup,name _targetPlayer,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime]};
};
_startPos = _unitGroup getVariable ["trigger",(getPosASL (leader _unitGroup))];
_chaseDistance = _unitGroup getVariable ["patrolDist",250];
#define TRANSMIT_RANGE 50 //distance to broadcast radio text around target player
#define RECEIVE_DIST 150 //distance requirement to receive message from AI group leader
if ((_startPos distance _targetPlayer) < _chaseDistance) then {
private ["_targetPlayerPos","_leader","_ableToChase","_debugMarkers","_marker"];
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Group %1 has entered pursuit state for 180 seconds. Target: %2. (fn_findKiller)",_unitGroup,_targetPlayer];};
//Temporarily cancel patrol state.
_unitGroup lockWP true;
//Set pursuit timer
_unitGroup setVariable ["pursuitTime",diag_tickTime+180];
_unitGroup setVariable ["targetKiller",name _targetPlayer];
_debugMarkers = ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled});
if (_debugMarkers) then {
_markername = format ["%1 Target",_unitGroup];
if ((getMarkerColor _markername) != "") then {deleteMarker _markername; uiSleep 0.5;};
_marker = createMarker [_markername,getPosASL _targetPlayer];
_marker setMarkerText _markername;
_marker setMarkerType "Attack";
_marker setMarkerColor "ColorRed";
_marker setMarkerBrush "Solid";
};
//Begin pursuit state.
_ableToChase = true;
while {
_ableToChase &&
{alive _targetPlayer} &&
{((_startPos distance _targetPlayer) < _chaseDistance)} &&
{(!((vehicle _targetPlayer) isKindOf "Air"))}
} do {
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
_targetPlayerPos = ASLtoATL getPosASL _targetPlayer;
(units _unitGroup) doMove _targetPlayerPos;
(units _unitGroup) doTarget _targetPlayer;
(units _unitGroup) doFire _targetPlayer;
{
if (alive _x) then {
_x moveTo _targetPlayerPos
};
} count (units _unitGroup);
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: AI group %1 in pursuit state. Pursuit time remaining: %2 seconds.",_unitGroup,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime];};
if (DZAI_radioMsgs) then {
_leader = (leader _unitGroup);
if (((_targetPlayer distance _leader) <= RECEIVE_DIST) && {!(_leader getVariable ["unconscious",false])}) then {
private ["_nearbyUnits","_radioSpeech"];
_nearbyUnits = _targetPlayerPos nearEntities [["LandVehicle","CAManBase"],TRANSMIT_RANGE];
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then {
{
if ((isPlayer _x)&& {((driver (vehicle _x)) hasWeapon "ItemRadio")}) then {
_speechIndex = (floor (random 3));
_radioSpeech = call {
if (_speechIndex == 0) exitWith {
format ["[RADIO] %1 (Bandit Leader): %2 is nearby. That's our target!",(name _leader),(name _targetPlayer)]
};
if (_speechIndex == 1) exitWith {
format ["[RADIO] %1 (Bandit Leader): Target looks like a %2. Find him!",(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]
};
if (_speechIndex == 2) exitWith {
format ["[RADIO] %1 (Bandit Leader): Target's distance is %2 meters. Search the area!",(name _leader),round (_leader distance _targetPlayer)]
};
"" //Default radio message: empty string (this case should never happen)
};
[_x,_radioSpeech] call DZAI_radioSend;
};
} count _nearbyUnits;
} else {
_radioSpeech = "[RADIO] Your radio is picking up a signal nearby.";
{
if ((isPlayer _x)&& {((driver (vehicle _x)) hasWeapon "ItemRadio")}) then {
[_x,_radioSpeech] call DZAI_radioSend;
};
} count _nearbyUnits;
};
};
};
if (_debugMarkers) then {
_marker setMarkerPos (getPosASL _targetPlayer);
};
uiSleep 19.5;
_ableToChase = ((!isNull _unitGroup) && {diag_tickTime < (_unitGroup getVariable ["pursuitTime",0])} && {(_unitGroup getVariable ["GroupSize",0]) > 0});
if (_ableToChase && {isNull _targetPlayer}) then {
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Group %1 is attempting to re-establish contact with target %2.",_unitGroup,_unitGroup getVariable "targetKiller"];};
_nearUnits = _targetPlayerPos nearEntities ["CAManBase",100];
{
if ((isPlayer _x) && {((name _x) == _unitGroup getVariable "targetKiller")}) exitWith {_targetPlayer = _x};
} forEach _nearUnits;
};
uiSleep 0.5;
};
if !(isNull _unitGroup) then {
//End of pursuit state. Re-enable patrol state.
_unitGroup setVariable ["pursuitTime",0];
_unitGroup setVariable ["targetKiller",""];
_unitGroup lockWP false;
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
_waypoints = (waypoints _unitGroup);
_unitGroup setCurrentWaypoint (_waypoints call BIS_fnc_selectRandom2);
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Pursuit state ended for group %1. Returning to patrol state. (fn_findKiller)",_unitGroup];};
if (DZAI_radioMsgs) then {
_leader = (leader _unitGroup);
if (((_targetPlayer distance _leader) <= RECEIVE_DIST) && {((_unitGroup getVariable ["GroupSize",0]) > 1)} && {!(_leader getVariable ["unconscious",false])} && {!(isNull _targetPlayer)}) then {
private ["_nearbyUnits","_radioSpeech","_radioText"];
_radioText = if (alive _targetPlayer) then {"%1 (Bandit Leader): Lost contact with target. Breaking off pursuit."} else {"%1 (Bandit Leader): Target has been eliminated."};
_radioSpeech = format [_radioText,(name (leader _unitGroup))];
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle","CAManBase"],TRANSMIT_RANGE];
{
if ((isPlayer _x)&&{((driver (vehicle _x)) hasWeapon "ItemRadio")}) then {
[_x,_radioSpeech] call DZAI_radioSend;
};
} count _nearbyUnits;
};
};
};
};
if (_debugMarkers) then {
deleteMarker _marker;
};
};

View File

@ -0,0 +1,23 @@
//Finds a position that does not have a player within a certain distance.
private ["_spawnPos","_attempts","_continue","_spawnpool","_maxAttempts"];
_attempts = 0;
_continue = true;
_spawnPos = [];
_spawnpool = +_this;
_maxAttempts = ((count _spawnpool) min 5); //5: Maximum number of attempts
while {_continue && {(_attempts < _maxAttempts)}} do {
_index = floor (random (count _spawnpool));
_spawnPosSelected = _spawnpool select _index;
if (({isPlayer _x} count (_spawnPosSelected nearEntities [["CAManBase","LandVehicle"],75])) == 0) then {
_spawnPos = _spawnPosSelected;
_continue = false;
} else {
_spawnpool set [_index,objNull];
_spawnpool = _spawnpool - [objNull];
_attempts = _attempts + 1;
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Player found within 75 meters of chosen spawn position. (attempt %1/%2).",_attempts,_maxAttempts];};
};
};
_spawnPos

View File

@ -0,0 +1,49 @@
private["_trigger","_mode"];
_mode = _this select 0;
_trigger = _this select 1;
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["GroupArray",(_this select 2)];
call {
if (_mode == 0) exitWith {
//Static spawns
_trigger setVariable ["patrolDist",(_this select 3)];
_trigger setVariable ["equipType",(_this select 4)];
_trigger setVariable ["locationArray",(_this select 5)];
_trigger setVariable ["maxUnits",(_this select 6)];
_trigger setVariable ["spawnChance",missionNamespace getVariable [format ["DZAI_spawnChance%1",(_this select 4)],1]];
//DZAI_locations set [(count DZAI_locations),[(triggerText _trigger),(getPosASL _trigger),"NameLocal"]]; //Add helicopter patrol WP pointing to static spawn location
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Initialized static spawn at %1. GroupArray: %2, PatrolDist: %3. equipType: %4. %LocationArray %5 positions, MaxUnits %6.",triggerText _trigger,(_this select 2),(_this select 3),(_this select 4),count (_this select 5),(_this select 6)];};
};
if (_mode == 1) exitWith {
//Dynamic spawns
_location = createLocation ["Strategic",(getPosASL _trigger),600,600]; //Create temporary dynamic spawn blacklist area
_trigger setVariable ["triggerLocation",_location];
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Initialized dynamic spawn at %1. GroupArray: %2.",triggerText _trigger,(_this select 2)];};
};
if (_mode == 2) exitWith {
//Random spawns
_triggerPos = getPosASL _trigger;
_location = _trigger getVariable ["triggerLocation",_triggerPos];
if ((_triggerPos distance _location) > 0) then {
_location setPosition _triggerPos;
};
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Initialized random spawn at %1. GroupArray: %2.",triggerText _trigger,(_this select 2)];};
};
if (_mode == 3) exitWith {
//Static spawns (custom)
_trigger setVariable ["patrolDist",(_this select 3)];
_trigger setVariable ["equipType",(_this select 4)];
_trigger setVariable ["locationArray",(_this select 5)];
_trigger setVariable ["maxUnits",(_this select 6)];
_trigger setVariable ["spawnChance",1];
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Initialized custom spawn at %1. GroupArray: %2, PatrolDist: %3. equipType: %4. %LocationArray %5 positions, MaxUnits %6.",triggerText _trigger,(_this select 2),(_this select 3),(_this select 4),count (_this select 5),(_this select 6)];};
};
};
_trigger setVariable ["triggerStatements",+(triggerStatements _trigger)];
_trigger setVariable ["initialized",true];
true

View File

@ -0,0 +1,17 @@
private ["_trigger","_marker"];
_trigger = _this select 0;
_marker = str (_trigger);
if ((getMarkerColor _marker) == "") then {
_marker = createMarker [_marker, (getPosASL _trigger)];
_marker setMarkerType "Defend";
_marker setMarkerBrush "Solid";
};
_marker setMarkerText "STATIC TRIGGER (ACTIVE)";
_marker setMarkerColor "ColorRed";
while {!((getMarkerColor _marker) in ["ColorGreen",""])} do {
_marker setMarkerPos (getMarkerPos _marker);
uiSleep 30;
};

View File

@ -0,0 +1,135 @@
/*
DZAI_dyn_huntPlayer
Description: Used for dynamically spawned AI. Creates a MOVE waypoint directing AI to a random player's position, then uses BIN_taskPatrol to create a circular patrol path around initial spawn position.
Last updated: 2:12 AM 1/11/2014
*/
#define TRANSMIT_RANGE 50 //distance to broadcast radio text around target player (target player will also recieve messages)
#define SEEK_RANGE 450 //distance to chase player from initial group spawn location
private ["_unitGroup","_spawnPos","_waypoint","_patrolDist","_statement","_targetPlayer","_triggerPos","_leader","_nearbyUnits","_radioSpeech","_radioText","_ableToChase"];
_unitGroup = _this select 0;
_spawnPos = _this select 1;
_patrolDist = _this select 2;
_targetPlayer = _this select 3;
_triggerPos = _this select 4;
_unitGroup setVariable ["seekActive",true];
_waypoint = [_unitGroup,0]; //Group will move to waypoint index 0 (first waypoint).
_waypoint setWaypointType "MOVE";
_waypoint setWaypointCompletionRadius 35;
_waypoint setWaypointTimeout [10,12,15];
_waypoint setWPPos (ASLtoATL getPosASL _targetPlayer);
_unitGroup setCurrentWaypoint _waypoint;
if (DZAI_radioMsgs) then {
_leader = (leader _unitGroup);
if (((_unitGroup getVariable ["GroupSize",0]) > 1) && {!(_leader getVariable ["unconscious",false])}) then {
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle","CAManBase"],TRANSMIT_RANGE];
{
if (isPlayer _x) then {
if ((driver (vehicle _x)) hasWeapon "ItemRadio") then {
_radioSpeech = [
"[RADIO] You hear static coming from your Radio...",
"[RADIO] Your Radio is picking up a signal..."
] call BIS_fnc_selectRandom2;
[_x,_radioSpeech] call DZAI_radioSend;
} else {
if (0.10 call DZAI_chance) then {
_radioSpeech = [
"You feel as if you are being watched...",
"You feel as if you are being followed...",
"You feel something isn't quite right..."
] call BIS_fnc_selectRandom2;
[_x,_radioSpeech] call DZAI_radioSend;
};
};
}
} count _nearbyUnits;
};
};
uiSleep 10;
//Begin hunting phase
_ableToChase = true;
while {
_ableToChase &&
{alive _targetPlayer} &&
{((_targetPlayer distance _triggerPos) < SEEK_RANGE)}
} do {
if !(_unitGroup getVariable ["inPursuit",false]) then {
_leader = (leader _unitGroup);
if (((getWPPos [_unitGroup,0]) distance _targetPlayer) > 25) then {
_waypoint setWPPos (ASLtoATL getPosASL _targetPlayer);
_unitGroup setCurrentWaypoint _waypoint;
_unitGroup setFormDir ([_leader,_targetPlayer] call BIS_fnc_dirTo);
_unitGroup reveal [_targetPlayer,4];
};
(units _unitGroup) doTarget _targetPlayer;
(units _unitGroup) doFire _targetPlayer;
if (DZAI_radioMsgs) then {
//Warn player of AI bandit presence if they have a radio.
if (((_unitGroup getVariable ["GroupSize",0]) > 1) && {!(_leader getVariable ["unconscious",false])} && {(_leader distance _targetPlayer) < 150}) then {
_nearbyUnits = (ASLtoATL getPosASL _targetPlayer) nearEntities [["LandVehicle","CAManBase"],TRANSMIT_RANGE];
{
if ((isPlayer _x)&&{((driver (vehicle _x)) hasWeapon "ItemRadio")}) then {
_index = (floor (random 10));
_radioSpeech = call {
if (_index == 0) exitWith {format ["[RADIO] %1 (Bandit Leader): Target's name is %2. Find him!",(name _leader),(name _targetPlayer)]};
if (_index == 1) exitWith {format ["[RADIO] %1 (Bandit Leader): Target is a %2. Find him!",(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]};
if (_index == 2) exitWith {format ["[RADIO] %1 (Bandit Leader): Target's distance is %2 meters. Find him!",(name _leader),round (_leader distance _targetPlayer)]};
if (_index > 2) exitWith {"[RADIO] ??? (Bandit): .... (static)"};
"[RADIO] ??? : ..."
};
//diag_log format ["DEBUG :: %1",_radioSpeech];
[_x,_radioSpeech] call DZAI_radioSend;
};
} count _nearbyUnits;
};
};
};
uiSleep 19.5;
_ableToChase = ((!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",0]) > 0});
if (_ableToChase && {isNull _targetPlayer}) then {
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Group %1 is attempting to search for a new target.",_unitGroup];};
_nearUnits = (leader _unitGroup) nearEntities ["CAManBase",200];
{
if (isPlayer _x) exitWith {
_targetPlayer = _x;
_unitGroup reveal [_targetPlayer,4];
};
} forEach _nearUnits;
};
uiSleep 0.5;
};
if ((isNull _unitGroup) or {(_unitGroup getVariable ["GroupSize",0]) < 1}) exitWith {};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Group %1 has exited hunting phase. Moving to patrol phase. (fn_seekPlayer)",_unitGroup];};
//Begin patrol phase
_waypoint setWaypointStatements ["true","if ((random 1) < 0.50) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];};"];
0 = [_unitGroup,_triggerPos,_patrolDist] spawn DZAI_BIN_taskPatrol;
_unitGroup setVariable ["seekActive",nil];
uiSleep 5;
if (DZAI_radioMsgs) then {
_leader = (leader _unitGroup);
if (((_unitGroup getVariable ["GroupSize",0]) > 1) && {!(_leader getVariable ["unconscious",false])} && {!(isNull _targetPlayer)}) then {
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle","CAManBase"],TRANSMIT_RANGE];
{
if ((isPlayer _x)&&{((driver (vehicle _x)) hasWeapon "ItemRadio")}) then {
_radioText = if (alive _targetPlayer) then {"%1 (Bandit Leader): We've lost contact with the target. Let's move out."} else {"%1 (Bandit Leader): The target has been killed."};
_radioSpeech = format [_radioText,(name _leader)];
[_x,_radioSpeech] call DZAI_radioSend;
};
} count _nearbyUnits;
};
};
true

View File

@ -0,0 +1,22 @@
//scriptName "Functions\arrays\fn_selectRandom.sqf";
/************************************************************
Random Select
By Andrew Barron
Parameters: array
This returns a randomly selected element from the passed array.
Example: [1,2,3] call BIS_fnc_selectRandom
Returns: 1, 2, or 3
************************************************************/
private "_ret";
if(count _this > 0) then
{
_ret = count _this; //number of elements in the array
_ret = floor (random _ret); //floor it first
_ret = _this select _ret; //get the element, return it
};
_ret

View File

@ -0,0 +1,60 @@
//scriptName "Functions\arrays\fn_selectRandomWeighted.sqf";
/*
File: fn_selectRandomWeighted.sqf
Author: Joris-Jan van 't Land
Description:
Function to select a random item from an array, taking into account item weights.
The weights should be Numbers between 0 and 1, with a maximum precision of hundreds.
Parameter(s):
_this select 0: source Array (Array of Any Value)
_this select 1: weights (Array of Number)
Returns:
Any Value selected item
TODO:
[*] Algorithm is inefficient?
*/
private ["_array", "_weights","_index","_weighted","_i"];
_array = _this select 0;
_weights = _this select 1;
//_amount = if ((count _this) > 2) then {_this select 2} else {1};
//Parameter validation.
if ((typeName _array) != (typeName [])) exitWith {debugLog "Log: [selectRandomWeighted] Array (0) must be an Array!"; nil};
if ((typeName _weights) != (typeName [])) exitWith {debugLog "Log: [selectRandomWeighted] Weights (1) must be an Array!"; nil};
if ((count _array) > (count _weights)) exitWith {debugLog "Log: [selectRandomWeighted] There must be at least as many elements in Weights (1) as there are in Array (0)!"; nil};
//Created weighted array of indices.
private ["_weighted"];
_weighted = [];
for "_i" from 0 to ((count _weights) - 1) do
{
private ["_weight"];
_weight = _weights select _i;
//Ensure the weight is a Number.
//If it's not, set weight to 0 to exclude it.
if ((typeName _weight) != (typeName 0)) then {debugLog "Log: [selectRandomWeighted] Weights should be Numbers; weight set to 0!"; _weight = 0};
//The weight should be a Number between 0 and 1.
if (_weight < 0) then {debugLog "Log: [selectRandomWeighted] Weights should be more than or equal to 0; weight set to 0!"; _weight = 0};
//if (_weight > 1) then {debugLog "Log: [selectRandomWeighted] Weights should be less than or equal to 1; weight set to 1!"; _weight = 1};
//Normalize the weight for a precision of hundreds.
_weight = round(_weight * 100);
for "_k" from 0 to (_weight - 1) do
{
_weighted = _weighted + [_i];
};
};
//Randomly select an index from the weighted array and therefore an element.
private ["_index"];
_index = _weighted call BIS_fnc_selectRandom2;
_array select _index

View File

@ -0,0 +1,14 @@
{
_unit = _x;
if (alive _x) exitWith {
{
_skillLevel = _unit skill _x;
_skillLevel = (_skillLevel * 1.1) min 1;
_unit setSkill [_x,_skillLevel];
uiSleep 0.01;
} count ["aimingAccuracy","aimingShake","aimingSpeed","endurance","spotDistance","spotTime","courage","reloadSpeed","general"];
_bandageAmount = _x getVariable ["bandageAmount",0];
_x setVariable ["bandageAmount",(_bandageAmount+1)];
};
uiSleep 0.05;
} forEach (units _this);

View File

@ -0,0 +1,88 @@
/*
fnc_createGroup
Description: Spawns a group of AI units. Used for spawning of DZAI's static, dynamic, and custom AI units.
_totalAI = Number of AI units to spawn in the group
_spawnPos: Position to create AI unit.
_trigger: The trigger object responsible for spawning the AI unit.
_weapongrade: weapongrade to be used for generating equipment. Influences weapon quality and skill level.
Last updated: 10:33 PM 5/14/2014
*/
private ["_totalAI","_spawnPos","_unitGroup","_trigger","_attempts","_baseDist","_dummy","_weapongrade"];
if (!isServer) exitWith {};
_totalAI = _this select 0;
_spawnPos = _this select 2;
_trigger = _this select 3;
_weapongrade = _this select 4;
_pos = [];
_attempts = 0;
_baseDist = 25;
while {((count _pos) < 1) && {(_attempts < 3)}} do {
_pos = _spawnPos findEmptyPosition [0.5,_baseDist,"Misc_cargo_cont_small_EP1"];
if ((count _pos) > 1) then {
_pos = _pos isFlatEmpty [0,0,0.75,5,0,false,objNull];
};
if ((count _pos) < 1) then {
_baseDist = (_baseDist + 25); _attempts = (_attempts + 1);
if (_attempts == 3) then {
_pos = [_trigger,random (_trigger getVariable ["patrolDist",125]),random(360),0] call SHK_pos;
_attempts = (_attempts + 1);
};
};
};
_pos set [2,0];
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Found spawn position at %3 meters away at position %1 after %2 retries.",_pos,_attempts,(_pos distance _spawnPos)]};
_unitGroup = if (isNull (_this select 1)) then {[] call DZAI_createGroup} else {_this select 1};
if (({isPlayer _x} count (_pos nearEntities ["CAManBase",100])) == 0) then {
_unitGroup setCombatMode "RED";
} else {
_unitGroup setCombatMode "BLUE";
_nul = _unitGroup spawn {
uiSleep 10;
_this setCombatMode "RED"; //Activate AI group hostility after 5 seconds
};
};
for "_i" from 1 to _totalAI do {
private ["_type","_unit"];
_type = DZAI_BanditTypes call BIS_fnc_selectRandom2; // Select skin of AI unit
_unit = _unitGroup createUnit [_type, _pos, [], 0, "FORM"]; // Spawn the AI unit
_unit setPos _pos;
[_unit] joinSilent _unitGroup; // Add AI unit to group
_unit setVariable ["bodyName",(name _unit)]; // Set unit body name (will be PVed upon death).
_unit setVariable ["unithealth",[(DZAI_baseBlood + (random DZAI_bonusBlood)),0,false]]; // Set unit health (blood, legs health, legs broken)
_unit setVariable ["unconscious",false]; // Set unit consciousness
_unit addEventHandler [DZAI_healthType, DZAI_healthStatements];
0 = [_unit, _weapongrade] call DZAI_setupLoadout; // Assign unit loadout
0 = [_unit, _weapongrade] call DZAI_setSkills; // Set AI skill
if (DZAI_weaponNoise) then {_unit addEventHandler ["Fired", {_this call DZAI_aiFired;}];}; // Unit firing causes zombie aggro in the area, like player.
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Spawned AI Type %1 with weapongrade %2 for group %3 (fnc_createGroup).",_type,_weapongrade,_unitGroup];};
};
//Delete dummy if it exists, and clear group's "dummy" variable.
_dummy = _unitGroup getVariable "dummyUnit";
if (!isNil "_dummy") then {
deleteVehicle _dummy;
_unitGroup setVariable ["dummyUnit",nil];
if (DZAI_debugLevel > 1) then {diag_log format["DZAI Extended Debug: Deleted 1 dummy AI unit for group %1. (fnc_createGroup)",_unitGroup];};
};
_unitGroup selectLeader ((units _unitGroup) select 0);
_unitGroup setVariable ["trigger",_trigger];
_unitGroup setVariable ["GroupSize",_totalAI];
_unitGroup setVariable ["weapongrade",_weapongrade];
if (isNull _trigger) then {_unitGroup setVariable ["spawnPos",_spawnPos]}; //If group was spawned directly by scripting instead of a trigger object, record spawn position instead of trigger position as anchoring point
//(DZAI_numAIUnits + _totalAI) call DZAI_updateUnitCount;
0 = [_unitGroup,_weapongrade] spawn DZAI_autoRearm_group; //start group-level manager
_unitGroup setFormDir (random 360);
_unitGroup

View File

@ -0,0 +1,350 @@
private ["_unitGroup","_weapongrade","_vehicle","_lastRearmTime","_useLaunchers","_isArmed","_debugMarkers","_marker","_marker2","_antistuckTime","_antistuckPos","_lastReinforceTime","_vehicleMoved"];
if (!isServer) exitWith {};
_unitGroup = _this select 0;
_weapongrade = _this select 1;
if (_unitGroup getVariable ["rearmEnabled",false]) exitWith {};
_unitGroup setVariable ["rearmEnabled",true];
_vehicle = if ((_unitGroup getVariable ["unitType",""]) in ["static","dynamic"]) then {objNull} else {(vehicle (leader _unitGroup))};
_useLaunchers = (((count DZAI_launcherTypes) > 0) && {(_weapongrade in DZAI_launcherLevels)});
_isArmed = _vehicle getVariable ["isArmed",false];
_antistuckPos = (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
if (isNil {_unitGroup getVariable "GroupSize"}) then {_unitGroup setVariable ["GroupSize",(count (units _unitGroup))]};
_vehicleMoved = true;
//set up debug variables
_debugMarkers = ((!isNil "DZAI_debugMarkersEnabled") && {DZAI_debugMarkersEnabled});
_marker = "";
_marker2 = "";
//Set up timer variables
_lastRearmTime = diag_tickTime;
_antistuckTime = diag_tickTime + 900;
_lastReinforceTime = diag_tickTime + 600;
//Set up individual group units
{
if (isNil {_x getVariable "unithealth"}) then {_x setVariable ["unithealth",[((9000 + (random 3000)) min 12000),0,false]]};
if (isNil {_x getVariable "unconscious"}) then {_x setVariable ["unconscious",false]};
_x setVariable ["bandageAmount",((_weapongrade + 1) min 3)];
_x setVariable ["lastBandage",0];
_x setVariable ["needsHeal",false];
_x setVariable ["rearmEnabled",true]; //prevent DZAI_autoRearm loop from executing on unit.
_loadout = _x getVariable "loadout";
if (isNil "_loadout") then {
_weapon = primaryWeapon _x;
_magazine = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines") select 0;
_loadout = [[_weapon],[_magazine]];
_x setVariable ["loadout",_loadout];
};
if ((getNumber (configFile >> "CfgMagazines" >> ((_loadout select 1) select 0) >> "count")) <= 8) then {_x setVariable ["extraMag",true]};
if (_useLaunchers) then {
_maxLaunchers = (DZAI_launchersPerGroup min _weapongrade);
if (_forEachIndex < _maxLaunchers) then {
_launchWeapon = DZAI_launcherTypes call BIS_fnc_selectRandom2;
_launchAmmo = [] + getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
_x addMagazine _launchAmmo; (_loadout select 1) set [1,_launchAmmo];
_x addWeapon _launchWeapon; (_loadout select 0) set [1,_launchWeapon];
};
};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Unit %1 loadout: %2. Weapongrade %3. Blood: %4.",_x,_x getVariable ["loadout",[]],_weapongrade,((_x getVariable ["unithealth",[12000,0,false]]) select 0)];};
} forEach (units _unitGroup);
if (_debugMarkers) then {
_markername = format ["%1-1",_unitGroup];
if ((getMarkerColor _markername) != "") then {deleteMarker _markername; uiSleep 0.5}; //Delete the previous marker if it wasn't deleted for some reason.
_marker = createMarker [_markername,getPosASL (leader _unitGroup)];
_marker setMarkerType "Attack";
_marker setMarkerBrush "Solid";
_marker setMarkerColor "ColorBlack";
if (isNull _vehicle) then {
_marker setMarkerText format ["%1 (AI L%2)",_unitGroup,_weapongrade];
} else {
_marker setMarkerText format ["%1 (AI L%2 %3)",_unitGroup,_weapongrade,(typeOf (vehicle (leader _unitGroup)))];
};
_markername2 = format ["%1-2",_unitGroup];
if ((getMarkerColor _markername2) != "") then {deleteMarker _markername2; uiSleep 0.5;}; //Delete the previous marker if it wasn't deleted for some reason.
_marker2 = createMarker [_markername2,(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
_marker2 setMarkerText format ["%1 WP",_unitGroup];
_marker2 setMarkerType "Waypoint";
_marker2 setMarkerColor "ColorBlue";
_marker2 setMarkerBrush "Solid";
{
_x spawn {
private ["_mark","_markname"];
_markname = str(_this);
if ((getMarkerColor _markname) != "") then {deleteMarker _markname; uiSleep 0.5};
_mark = createMarker [_markname,getPosASL _this];
_mark setMarkerShape "ELLIPSE";
_mark setMarkerType "Dot";
_mark setMarkerColor "ColorRed";
_mark setMarkerBrush "SolidBorder";
_mark setMarkerSize [3,3];
waitUntil {uiSleep 15; (!(alive _this))};
//diag_log format ["DEBUG :: Deleting unit marker %1.",_mark];
deleteMarker _mark;
};
uiSleep 0.1;
} count (units _unitGroup);
} else {
_marker = nil;
_marker2 = nil;
};
//Main loop
while {(!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
private ["_unitType"];
_unitType = (_unitGroup getVariable ["unitType",""]);
call {
//Zed hostility check
if (_unitType in ["static","dynamic"]) exitWith {
if (DZAI_zombieEnemy) then {
if (_unitGroup getVariable ["detectReady",true]) then {
_unitGroup setVariable ["detectReady",false];
_nul = _unitGroup spawn {
_unitGroup = _this;
if !(isNull _unitGroup) then {
_detectRange = if ((_unitGroup getVariable ["pursuitTime",0]) == 0) then {DZAI_zDetectRange} else {DZAI_zDetectRange/2}; //Reduce detection range of new zombies while searching for killer unit
_leader = (leader _unitGroup);
if (alive _leader) then {
_nearbyZeds = _leader nearEntities ["zZombie_Base",_detectRange];
_hostileZedsNew = [];
{
if (rating _x > -30000) then {
_hostileZedsNew set [count _hostileZedsNew,_x];
};
if ((_forEachIndex % 5) == 0) then {uiSleep 0.05};
} forEach _nearbyZeds;
if ((count _hostileZedsNew) > 0) then {
DZAI_ratingModify = [_hostileZedsNew,-30000];
(owner (_hostileZedsNew select 0)) publicVariableClient "DZAI_ratingModify";
};
};
_unitGroup setVariable ["detectReady",true];
};
};
};
};
};
//If any units have left vehicle then allow re-entry
if (_unitType in ["land","landcustom"]) exitWith {
if (alive _vehicle) then {
if (_unitGroup getVariable ["regrouped",true]) then {
if (({(_x distance _vehicle) > 175} count (assignedCargo _vehicle)) > 0) then {
_unitGroup setVariable ["regrouped",false];
[_unitGroup,_vehicle] call DZAI_vehRegroup;
};
};
};
};
if (_unitType == "air") exitWith {
if ((alive _vehicle) && {!(_vehicle getVariable ["heli_disabled",false])}) then {
if (((diag_tickTime - _lastReinforceTime) > 900) && {((count DZAI_reinforcePlaces) > 0)}) then {
[_unitGroup,_vehicle] call DZAI_heliReinforce;
_lastReinforceTime = diag_tickTime;
};
};
};
};
{
//Check infantry-type units
if (((vehicle _x) == _x) && {!(_x getVariable ["unconscious",false])} && {_x getVariable ["canCheckUnit",true]}) then {
_x setVariable ["canCheckUnit",false];
_nul = _x spawn {
if (!alive _this) exitWith {};
_unit = _this;
_loadout = _unit getVariable ["loadout",[[],[]]];
if (!isNil "_loadout") then {
_currentMagazines = (magazines _unit);
for "_i" from 0 to ((count (_loadout select 0)) - 1) do {
if (((_unit ammo ((_loadout select 0) select _i)) == 0) || {!((((_loadout select 1) select _i) in _currentMagazines))}) then {
_unit removeMagazines ((_loadout select 1) select _i);
_unit addMagazine ((_loadout select 1) select _i);
if ((_i == 0) && {_unit getVariable ["extraMag",false]}) then {_unit addMagazine ((_loadout select 1) select _i)};
};
};
};
_bandages = _unit getVariable ["bandageAmount",0];
if (_bandages > 0) then {
_health = _unit getVariable ["unithealth",[12000,0,false]];
if (_unit getVariable ["needsHeal",false]) then {
_nearestEnemy = _unit findNearestEnemy _unit;
_isSafe = ((_unit distance _nearestEnemy) > 35);
if (_isSafe) then {
_bandages = _bandages - 1;
_unit setVariable ["bandageAmount",_bandages];
{_unit disableAI _x} forEach ["TARGET","MOVE","FSM"];
_unit playActionNow "Medic";
_healTimes = 0;
while {(!(_unit getVariable ["unconscious",false])) && {(_healTimes < 3)}} do {
uiSleep 3;
if (!(_unit getVariable ["unconscious",false])) then {
_health set [0,(((_health select 0) + (DZAI_unitHealAmount/3)) min 12000)];
_healTimes = _healTimes + 1;
if ((alive _unit) && {(_healTimes == 3)}) then {
_health set [1,0];
_health set [2,false];
_unit setHit ["legs",0];
};
};
};
_unit setVariable ["lastBandage",diag_tickTime];
_unit setVariable ["needsHeal",false];
uiSleep 1.75;
{_unit enableAI _x} forEach ["TARGET","MOVE","FSM"];
};
} else {
_lowblood = ((_health select 0) < DZAI_lowBloodLevel);
_brokenbones = (_health select 2);
if ((_lowblood or _brokenbones) && {((diag_tickTime - (_unit getVariable ["lastBandage",diag_tickTime])) > 60)}) then {
_unit setVariable ["needsHeal",true];
};
};
};
_unit setVariable ["canCheckUnit",true];
};
};
uiSleep 0.1;
} forEach (units _unitGroup);
//Vehicle ammo/fuel check
if (alive _vehicle) then { //If _vehicle is objNull (if no vehicle was assigned to the group) then nothing in this bracket should be executed
if ((_isArmed) && {someAmmo _vehicle}) then { //Note: someAmmo check is not reliable for vehicles with multiple turrets
_lastRearmTime = diag_tickTime; //Reset rearm timestamp if vehicle still has some ammo
} else {
if ((diag_tickTime - _lastRearmTime) > 180) then { //If ammo is depleted, wait 3 minutes until rearm is possible.
_vehicle setVehicleAmmo 1; //Rearm vehicle. Rearm timestamp will be reset durng the next loop cycle.
};
};
if ((fuel _vehicle) < 0.25) then {_vehicle setFuel 1};
};
//Antistuck detection
if ((diag_tickTime - _antistuckTime) > 900) then {
_wpPos = (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
_unitType = (_unitGroup getVariable ["unitType",""]);
call {
if (_unitType in ["static","aircustom","landcustom"]) exitWith {
//Static and custom air/land vehicle patrol anti stuck routine
if ((_antistuckPos distance _wpPos) == 0) then {
_currentWP = (currentWaypoint _unitGroup);
_allWP = (waypoints _unitGroup);
_nextWP = _currentWP + 1;
if ((count _allWP) == _nextWP) then {_nextWP = 1}; //Cycle back to first added waypoint if group is currently on last waypoint.
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Antistuck detection triggered for AI group %1. Forcing next waypoint.",_unitGroup];};
_antistuckTime = diag_tickTime + 300;
} else {
_antistuckPos = _wpPos;
_antistuckTime = diag_tickTime;
};
};
if (_unitType == "air") exitWith {
//Mapwide air vehicle patrol anti stuck routine
if ((canMove _vehicle) && {(_antistuckPos distance _wpPos) < 300}) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (DZAI_locations call BIS_fnc_selectRandom2) select 1;
if (((waypointPosition [_unitGroup,0]) distance _wpSelect) < 300) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,50+(random 900),(random 360),1] call SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,1] setWPPos _wpSelect;
_vehicle doMove _wpSelect;
_antistuckPos = _wpSelect;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Antistuck detection triggered for AI vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
_antistuckTime = diag_tickTime + 300;
} else {
_antistuckPos = _wpPos;
_antistuckTime = diag_tickTime;
};
};
if (_unitType == "land") exitWith {
//Mapwide land vehicle patrol anti stuck routine
if ((_antistuckPos distance _wpPos) < 300) then {
if (_vehicleMoved && {canMove _vehicle}) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (DZAI_locationsLand call BIS_fnc_selectRandom2) select 1;
if (((waypointPosition [_unitGroup,0]) distance _wpSelect) < 300) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,random(300),random(360),0,[1,300]] call SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
_antistuckPos = _wpSelect;
_vehicleMoved = false;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Antistuck prevention triggered for AI vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
_antistuckTime = diag_tickTime + 300;
} else {
if (!(_vehicle getVariable ["veh_disabled",false])) then {
[_vehicle] call DZAI_vehDestroyed;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: AI vehicle %1 (Group: %2) is immobilized. Respawning vehicle patrol group.",(typeOf _vehicle),_unitGroup];};
};
};
} else {
_antistuckPos = _wpPos;
if (!_vehicleMoved) then {
_vehicleMoved = true;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Antistuck check passed for AI vehicle %1 (Group: %2). Reset vehicleMoved flag.",(typeOf _vehicle),_unitGroup];};
};
_antistuckTime = diag_tickTime;
};
};
};
};
if (_debugMarkers) then {
_marker setMarkerPos (getPosASL (vehicle (leader _unitGroup)));
_marker2 setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
{
if (alive _x) then {
(str (_x)) setMarkerPos (getPosASL _x);
};
if ((_forEachIndex % 3) == 0) then {uiSleep 0.05};
} forEach (units _unitGroup);
};
//diag_log format ["DEBUG: Group Manager cycle time for group %1: %2 seconds.",_unitGroup,(diag_tickTime - _debugStartTime)];
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {uiSleep 15};
};
_unitGroup setVariable ["rearmEnabled",false]; //allow group manager to run again on group respawn.
if (isEngineOn _vehicle) then {_vehicle engineOn false};
if (_debugMarkers) then {
deleteMarker _marker;
deleteMarker _marker2;
};
//Wait until group is either respawned or marked for deletion. A dummy unit should be created to preserve group.
while {(_unitGroup getVariable ["GroupSize",-1]) == 0} do {
uiSleep 5;
};
//GroupSize value of -1 marks group for deletion
if ((_unitGroup getVariable ["GroupSize",-1]) == -1) then {
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Deleting %2 group %1.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])]};
_unitGroup call DZAI_deleteGroup;
};

View File

@ -0,0 +1,65 @@
/*
DZAI_airLanding
Description: Called when AI air vehicle performs a landing. Converts onboard AI crew into static-type units.
Last updated: 12:11 AM 6/17/2014
*/
private ["_helicopter","_trigger","_heliPos","_unitsAlive","_unitGroup","_waypointCount"];
_helicopter = _this select 0;
if (_helicopter getVariable ["heli_disabled",false]) exitWith {};
_helicopter setVariable ["heli_disabled",true];
{_helicopter removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed"];
_unitGroup = _helicopter getVariable ["unitGroup",(group (_this select 2))];
[_unitGroup,_helicopter] call DZAI_respawnAIVehicle;
_unitsAlive = {alive _x} count (units _unitGroup);
if (_unitsAlive > 0) then {
//Convert helicrew units to ground units
{
if (alive _x) then {
_health = _x getVariable ["unithealth",[]];
if ((_health select 1) > 0) then {
_health set [1,0]; //If unit has any leg damage, heal it
_health set [2,false];
_x setHit["legs",0];
};
unassignVehicle _x;
};
} count (units _unitGroup);
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
deleteWaypoint [_unitGroup,_i];
};
_heliPos = ASLtoATL getPosASL _helicopter;
0 = [_unitGroup,_heliPos,75] spawn DZAI_BIN_taskPatrol;
//(DZAI_numAIUnits + _unitsAlive) call DZAI_updateUnitCount;
//Create area trigger
_trigger = createTrigger ["EmptyDetector",_heliPos];
_trigger setTriggerArea [600, 600, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [5, 5, 5, true];
_trigger setTriggerText (format ["HeliLandingArea_%1",mapGridPosition _helicopter]);
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;","","0 = [thisTrigger] spawn fnc_despawnBandits;"];
//Set required trigger variables and begin despawn
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["GroupArray",[_unitGroup]];
_trigger setVariable ["equipType",DZAI_heliUnitLevel];
_trigger setVariable ["maxUnits",[_unitsAlive,0]];
_trigger setVariable ["respawn",false]; //landed AI units should never respawn
_trigger setVariable ["permadelete",true]; //units should be permanently despawned
[_trigger,"DZAI_staticTriggerArray"] call DZAI_updateSpawnCount;
0 = [_trigger] spawn fnc_despawnBandits;
_unitGroup setVariable ["unitType","static"]; //convert units to static type
_unitGroup setVariable ["trigger",_trigger]; //attach trigger object reference to group
_unitGroup setVariable ["GroupSize",_unitsAlive]; //set group size
_unitGroup setBehaviour "AWARE";
_unitGroup allowFleeing 0;
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI helicopter %1 landed at %2.",typeOf _helicopter,mapGridPosition _helicopter];};
};

View File

@ -0,0 +1,26 @@
if (!isServer) exitWith {};
private ["_helicopter","_unitGroup"];
_helicopter = _this select 0;
_unitGroup = _this select 1;
uiSleep 60;
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: Starting helicopter awareness script for AI vehicle %1 (Group: %2).",typeOf _helicopter,_unitGroup];};
while {!(_helicopter getVariable ["heli_disabled",false]) && {alive _helicopter}} do {
_detectOrigin = [getPosASL _helicopter,200,getDir _helicopter,1] call SHK_pos;
_detectOrigin set [2,0];
_detected = _detectOrigin nearEntities [["CAManBase","LandVehicle"],225];
{
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 1.5}) then {
_heliAimPos = aimPos _helicopter;
_playerAimPos = aimPos _x;
if (!(terrainIntersectASL [_heliAimPos,_playerAimPos]) && {!(lineIntersects [_heliAimPos,_playerAimPos,_helicopter,_x])}) then { //if no intersection of terrain and objects between helicopter and player, then reveal player
_unitGroup reveal [_x,2.5];
};
};
uiSleep 0.1;
} forEach _detected;
uiSleep 20;
};

View File

@ -0,0 +1,37 @@
/*
DZAI_heliDestroyed
Description: Called when AI air vehicle is destroyed by collision damage.
Last updated: 12:11 AM 6/17/2014
*/
private ["_helicopter","_unitGroup","_weapongrade"];
_helicopter = _this select 0;
if (_helicopter getVariable ["heli_disabled",false]) exitWith {false};
_helicopter setVariable ["heli_disabled",true];
{_helicopter removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed"];
_unitGroup = _helicopter getVariable "unitGroup";
[_unitGroup,_helicopter] call DZAI_respawnAIVehicle;
if !(surfaceIsWater (getPosASL _helicopter)) then {
_weapongrade = _unitGroup getVariable ["weapongrade",1];
_unitGroup setVariable ["unitType","aircrashed"]; //Recategorize group as "aircrashed" to prevent AI inventory from being cleared since death is considered suicide.
{
if (alive _x) then {
_x action ["eject",_helicopter];
_nul = [_x,_x] call DZAI_unitDeath;
0 = [_x,_weapongrade] spawn DZAI_addLoot;
} else {
[_x] joinSilent grpNull;
};
} count (units _unitGroup);
} else {
//_unitGroup call DZAI_deleteGroup;
};
_unitGroup setVariable ["GroupSize",-1];
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI helicopter patrol destroyed at %1",mapGridPosition _helicopter];};
true

View File

@ -0,0 +1,40 @@
private ["_unitGroup","_detectBase","_detectFactor","_detectRange","_helicopter"];
_unitGroup = _this select 0;
_helicopter = vehicle (leader _unitGroup);
//_detectDelay = if ((waypointType [_unitGroup,1]) == "MOVE") then {5} else {20};
_detectRange = if (_unitGroup getVariable ["DetectPlayersWide",false]) then {_unitGroup setVariable ["DetectPlayersWide",false]; 375} else {250};
//uiSleep (round (random _detectDelay));
uiSleep 2;
if (_unitGroup getVariable ["HeliDetectReady",true]) then {
_unitGroup setVariable ["HeliDetectReady",false];
_detectStartPos = getPosASL _helicopter;
while {!(_helicopter getVariable ["heli_disabled",false])} do {
private ["_detected","_detectOrigin","_detectedCount","_startPos"];
_startPos = getPosASL _helicopter;
_detectOrigin = [_startPos,100,getDir _helicopter,1] call SHK_pos;
_detectOrigin set [2,0];
_detected = _detectOrigin nearEntities [["CAManBase","LandVehicle"],_detectRange];
_detectedCount = (count _detected);
if (_detectedCount > 0) then {
if (_detectedCount > 15) then {_detected resize 15};
{
if (isPlayer _x) then {
_heliAimPos = aimPos _helicopter;
_playerAimPos = aimPos _x;
if (!(terrainIntersectASL [_heliAimPos,_playerAimPos]) && {!(lineIntersects [_heliAimPos,_playerAimPos,_helicopter,_x])}) then { //if no intersection of terrain and objects between helicopter and player, then reveal player
_unitGroup reveal [_x,2.5];
};
};
uiSleep 0.1;
} forEach _detected;
if (((_helicopter distance _detectStartPos) > 700) or {_helicopter getVariable ["heli_disabled",false]}) exitWith {_unitGroup setVariable ["HeliDetectReady",true]};
uiSleep 15;
} else {
uiSleep 7.5;
};
};
};

View File

@ -0,0 +1,45 @@
private["_unit","_hit","_damage","_source","_ammo","_partdamage","_durability"];
_unit = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
_source = _this select 3; //The source unit that caused the damage.
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
_durability = _unit getVariable "durability";
if ((_ammo != "")&&{!isNil "_durability"}) then {
call {
if (_hit == "") exitWith {
//Structural damage
_partdamage = (_durability select 0) + _damage;
_durability set [0,_partdamage];
if (((_partdamage >= 0.9) or {((_durability select 1) >= 0.9)}) && {(alive _unit)}) then {
0 = [_unit] call DZAI_parachuteOut;
_nul = _unit spawn {
uiSleep 3;
_this setVehicleAmmo 0;
_this setFuel 0;
_this setDamage 1;
};
{_unit removeAllEventHandlers _x} forEach ["HandleDamage","GetOut","Killed"];
};
};
if (_hit == "motor") exitWith {
_partdamage = (_durability select 1) + _damage;
_durability set [1,_partdamage];
if ((_partdamage > 0.88) && {alive _unit}) then {
_damage = 0.88; //Intercept fatal damage to helicopter engine - next hit will destroy the helicopter.
};
};
if (_hit == "mala vrtule") exitWith {
_partdamage = (_durability select 2) + _damage;
_durability set [2,_partdamage];
if ((_partdamage >= 0.9) && {_unit getVariable ["tailRotorFunctional",true]}) then {
_unit setHit ["mala vrtule",1]; //Knock out helicopter tail rotor when sufficiently damaged
_unit setVariable ["tailRotorFunctional",false];
};
};
};
};
_damage

View File

@ -0,0 +1,90 @@
/*
DZAI_parachuteOut
Description: Called when AI air vehicle suffers critical damage. Onboard units are ejected if the vehicle is not above water.
Last updated: 12:11 AM 6/17/2014
*/
private ["_helicopter","_vehPos","_unitGroup"];
_helicopter = _this select 0;
if (_helicopter getVariable ["heli_disabled",false]) exitWith {false};
_helicopter setVariable ["heli_disabled",true];
{_helicopter removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed"];
_unitGroup = _helicopter getVariable "unitGroup";
[_unitGroup,_helicopter] call DZAI_respawnAIVehicle;
_vehPos = ASLtoATL getPosASL _helicopter;
if (!surfaceIsWater _vehPos) then {
private ["_unitsAlive","_trigger","_weapongrade","_units","_waypointCount"];
_weapongrade = _unitGroup getVariable ["weapongrade",1];
_units = units _unitGroup;
if (((_vehPos select 2) > 60) or {(0.40 call DZAI_chance)}) then {
{
if (alive _x) then {
_health = _x getVariable ["unithealth",[]];
if ((_health select 1) > 0) then {
_health set [1,0]; //If unit has any leg damage, heal it
_health set [2,false];
_x setHit["legs",0];
};
_x action ["eject",_helicopter];
unassignVehicle _x;
} else {
0 = [_x,_weapongrade] spawn DZAI_addLoot;
};
} forEach _units;
_unitsAlive = {alive _x} count _units;
//(DZAI_numAIUnits + _unitsAlive) call DZAI_updateUnitCount;
if (_unitsAlive > 0) then {
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
deleteWaypoint [_unitGroup,_i];
};
0 = [_unitGroup,_vehPos,75] spawn DZAI_BIN_taskPatrol;
_unitGroup allowFleeing 0;
//Create area trigger
_trigger = createTrigger ["EmptyDetector",_vehPos];
_trigger setTriggerArea [600, 600, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [5, 5, 5, true];
_trigger setTriggerText (format ["Heli AI Parachute %1",mapGridPosition _helicopter]);
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;","","0 = [thisTrigger] spawn fnc_despawnBandits;"];
//Set required trigger variables and begin despawn
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["GroupArray",[_unitGroup]];
_trigger setVariable ["equipType",DZAI_heliUnitLevel];
_trigger setVariable ["maxUnits",[_unitsAlive,0]];
_trigger setVariable ["respawn",false]; //landed AI units should never respawn
_trigger setVariable ["permadelete",true]; //units should be permanently despawned
[_trigger,"DZAI_staticTriggerArray"] call DZAI_updateSpawnCount;
0 = [_trigger] spawn fnc_despawnBandits;
_unitGroup setVariable ["unitType","static"];
_unitGroup setVariable ["trigger",_trigger];
_unitGroup setVariable ["groupSize",_unitsAlive];
_unitGroup setBehaviour "AWARE";
};
} else {
_unitGroup setVariable ["unitType","aircrashed"];
{
_x action ["eject",_helicopter];
_nul = [_x,_x] call DZAI_unitDeath;
0 = [_x,_weapongrade] spawn DZAI_addLoot;
} forEach _units;
_unitGroup setVariable ["GroupSize",-1];
};
} else {
//_unitGroup call DZAI_deleteGroup;
_unitGroup setVariable ["GroupSize",-1];
};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI helicopter %1 evacuated at %2.",typeOf _helicopter,mapGridPosition _helicopter];};
true

View File

@ -0,0 +1,31 @@
private ["_unitGroup","_tooClose","_wpSelect"];
_unitGroup = _this select 0;
_tooClose = true;
while {_tooClose} do {
_wpSelect = (DZAI_locations call BIS_fnc_selectRandom2) select 1;
if (((waypointPosition [_unitGroup,0]) distance _wpSelect) > 300) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,50+(random 900),(random 360),1] call SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,1] setWPPos _wpSelect;
if ((waypointType [_unitGroup,1]) == "MOVE") then {
if (0.275 call DZAI_chance) then {
[_unitGroup,1] setWaypointType "SAD";
[_unitGroup,1] setWaypointTimeout [20,25,30];
_unitGroup setVariable ["DetectPlayersWide",true];
};
} else {
[_unitGroup,1] setWaypointType "MOVE";
[_unitGroup,1] setWaypointTimeout [3,6,9];
};
//[_unitGroup,0] setWaypointCompletionRadius 150;
//_unitGroup setCurrentWaypoint [_unitGroup,0];
//(vehicle (leader _unitGroup)) flyInHeight (100 + (random 40));
_unitGroup setCurrentWaypoint [_unitGroup,0];
(vehicle (leader _unitGroup)) flyInHeight (100 + (random 40));

View File

@ -0,0 +1,31 @@
/*
*/
private ["_index","_trigger","_targetPlayer","_unitGroup","_reinforcePos","_lastRedirectTime","_helicopter"];
_unitGroup = _this select 0;
_helicopter = _this select 1;
_index = floor (random (count DZAI_reinforcePlaces));
_trigger = DZAI_reinforcePlaces select _index;
if (!isNull _trigger) then {
_targetPlayer = _trigger getVariable "targetplayer";
if (!isNil "_targetPlayer") then {_unitGroup reveal [_targetPlayer,4]};
_reinforcePos = (getPosASL _trigger);
DZAI_reinforcePlaces set [_index,objNull];
DZAI_reinforcePlaces = DZAI_reinforcePlaces - [objNull];
[_unitGroup,0] setWPPos _reinforcePos;
[_unitGroup,1] setWPPos _reinforcePos;
[_unitGroup,1] setWaypointType "SAD";
[_unitGroup,1] setWaypointTimeout [40,50,60];
_unitGroup setVariable ["DetectPlayersWide",true];
_unitGroup setCurrentWaypoint [_unitGroup,0];
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Helicopter %1 (%2) redirected to dynamic spawn area at %3.",_helicopter,(typeOf _helicopter),mapGridPosition _reinforcePos]};
};
DZAI_reinforcePlaces set [_index,objNull];
DZAI_reinforcePlaces = DZAI_reinforcePlaces - [objNull];
true

View File

@ -0,0 +1,62 @@
/*
DZAI_vehDestroyed
Description: Called when AI land vehicle is destroyed
Last updated: 12:11 AM 6/17/2014
*/
private ["_vehicle","_unitGroup","_unitsAlive"];
_vehicle = _this select 0;
if (_vehicle getVariable ["veh_disabled",false]) exitWith {};
_vehicle setVariable ["veh_disabled",true];
_unitGroup = _vehicle getVariable "unitGroup";
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","Killed"];
[_unitGroup,_vehicle] call DZAI_respawnAIVehicle;
_unitsAlive = {alive _x} count (units _unitGroup);
if (_unitsAlive > 0) then {
//Restrict patrol area to vehicle wreck
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
deleteWaypoint [_unitGroup,_i];
};
_vehPos = ASLToATL getPosASL _vehicle;
0 = [_unitGroup,_vehPos,100] spawn DZAI_BIN_taskPatrol;
//Create area trigger
_trigger = createTrigger ["EmptyDetector",_vehPos];
_trigger setTriggerArea [600, 600, 0, false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [5, 5, 5, true];
_trigger setTriggerText (format ["Abandoned AI Vehicle %1",mapGridPosition _vehicle]);
_trigger setTriggerStatements ["{isPlayer _x} count thisList > 0;","","0 = [thisTrigger] spawn fnc_despawnBandits;"];
//Set required trigger variables and begin despawn
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["GroupArray",[_unitGroup]];
_trigger setVariable ["equipType",DZAI_vehUnitLevel];
_trigger setVariable ["maxUnits",[_unitsAlive,0]];
_trigger setVariable ["respawn",false]; //landed AI units should never respawn
_trigger setVariable ["permadelete",true]; //units should be permanently despawned
//DZAI_actTrigs = DZAI_actTrigs + 1;
[_trigger,"DZAI_staticTriggerArray"] call DZAI_updateSpawnCount;
//(DZAI_numAIUnits + _unitsAlive) call DZAI_updateUnitCount;
0 = [_trigger] spawn fnc_despawnBandits;
_unitGroup setVariable ["unitType","static"];
_unitGroup setVariable ["trigger",_trigger];
_unitGroup setVariable ["groupSize",_unitsAlive];
_unitGroup setBehaviour "AWARE";
{
unassignVehicle _x;
} forEach (assignedCargo _vehicle);
} else {
_unitGroup setVariable ["GroupSize",-1];
};
if (DZAI_debugLevel > 0) then {diag_log format ["DZAI Debug: AI land vehicle patrol destroyed at %1",mapGridPosition _vehicle];};

View File

@ -0,0 +1,10 @@
private["_unit","_hit","_damage","_source","_ammo"];
//_unit = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
//_source = _this select 3; //The source unit that caused the damage.
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
if (_ammo == "") then {_damage = 0};
_damage

View File

@ -0,0 +1,17 @@
private ["_unitGroup","_tooClose","_wpSelect"];
_unitGroup = _this select 0;
_tooClose = true;
while {_tooClose} do {
_wpSelect = (DZAI_locationsLand call BIS_fnc_selectRandom2) select 1;
if (((waypointPosition [_unitGroup,0]) distance _wpSelect) > 300) then {
_tooClose = false;
};
};
_wpSelect = [_wpSelect,random(300),random(360),0,[1,300]] call SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,0] setWaypointCompletionRadius 150;
if ((count (waypoints _unitGroup)) == 1) then {
_unitGroup setCurrentWaypoint [_unitGroup,0];
};

View File

@ -0,0 +1,15 @@
private ["_unitGroup","_vehicle","_loadWP","_loadWPCond"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_loadWP = _unitGroup addWaypoint [(ASLtoATL getPosASL _vehicle),0];
_loadWP setWaypointType "LOAD";
_loadWPCond = "_vehicle = (group this) getVariable ['assignedVehicle',objNull]; ({_x == (vehicle _x)} count (assignedCargo _vehicle)) == 0";
_loadWP setWaypointStatements [_loadWPCond,(format ["_unitGroup = (group this); deleteWaypoint [_unitGroup,%1]; _unitGroup setVariable ['regrouped',true]; _unitGroup setCurrentWaypoint [_unitGroup,0];",(_loadWP select 1)])];
_loadWP setWaypointCompletionRadius 20;
_unitGroup setCurrentWaypoint _loadWP;
if (DZAI_debugLevel > 1) then {diag_log format ["DZAI Extended Debug: Regroup order issued for AI group %1 to vehicle %2. Check WP count: %3.",_unitGroup,typeOf _vehicle,(count (waypoints _unitGroup))];};
true