DMS_Exile/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf
eraser1 afb4833a65 Fixes + Tweaks + Features
#### September 13, 2015 (11:45 PM CST-America):
* NEW CONFIG VALUES: DMS_MaxAIDistance and DMS_AIDistanceCheckFrequency
* You can now use the above config values to kill AI that flee from
their spawn position. Only "Soldier" AI will be killed.
* Removed "O_HMG_01_F" from AI Static Weapons. AI were pretty useless on
it... unless the AI were facing the right direction.
* Reduced AI count and removed the "playerNear" parameter from
testmission for easier testing.
* NEW: When an AI vehicle gunner is killed, and the driver is still
alive, after a little delay, the driver is then switched to the gunner
seat. You should no longer have AI vehicles with a dead gunner that's
driving around aimlessly :) There is a 5-8 second delay to simulate
reaction time. Then the driver is ejected, then after 1.5 seconds the AI
is then forced into the  gunner seat.
* NOTE: The above feature only works when the AI is still local (not
offloaded). If the AI is offloaded, the AI is simply ejected and becomes
a foot soldier.
* AI assigned vehicles are destroyed when the crew is empty. Simulation
is also disabled on them.
* Reduced some of the "params" RPT spam, from DMS_fnc_SetGroupBehavior.
* Tweaked AI Vehicle spawning logic. The AI are initially assigned to a
temporary group and then behavior is set, then they join the assigned
group to prevent overriding behavior of other ground units.
* Non-persistent vehicles should now be fit properly to the terrain.
2015-09-16 22:37:17 -05:00

235 lines
6.3 KiB
Plaintext

/*
DMS_fnc_OnKilled
Created by eraser1 and Defent
Influenced by WAI
Usage:
[
[
_killedUnit,
_killer
],
_side, // "bandit" only for now
_type // Type of AI: "soldier","static","vehicle","heli", etc.
] call DMS_fnc_OnKilled;
*/
private ["_unit", "_player", "_side", "_type", "_launcher", "_playerObj", "_rockets", "_grpUnits", "_av", "_memCount", "_gunner", "_driver", "_veh", "_moneyGain", "_repGain", "_money", "_respect"];
if (DMS_DEBUG) then
{
diag_log format ["DMS_DEBUG OnKilled :: Logging AI death with parameters: %1",_this];
};
_unit = _this select 0 select 0;
_player = _this select 0 select 1;
_side = _this select 1;
_type = _this select 2;
_launcher = secondaryWeapon _unit;
_playerObj = objNull;
// Some of the previously used functions work with non-local argument. Some don't. BIS is annoying
_removeAll =
{
{_this removeWeaponGlobal _x;} forEach (weapons _this);
{_this unlinkItem _x;} forEach (assignedItems _this);
{_this removeItem _x;} forEach (items _this);
removeAllItemsWithMagazines _unit;
removeHeadgear _unit;
removeUniform _unit;
removeVest _unit;
removeBackpackGlobal _unit;
};
// Remove gear according to configs
if (DMS_clear_AI_body && {(random 100) <= DMS_clear_AI_body_chance}) then
{
_unit call _removeAll;
};
if(DMS_ai_remove_launchers && {_launcher != ""}) then
{
_rockets = _launcher call DMS_fnc_selectMagazine;
_unit removeWeaponGlobal _launcher;
{
if(_x == _rockets) then
{
_unit removeMagazineGlobal _x;
};
} forEach magazines _unit;
};
if(DMS_RemoveNVG) then
{
_unit unlinkItem "NVGoggles";
};
// Give the AI a new leader if the killed unit was the leader
// credit: https://github.com/SMVampire/VEMF/
if (((count (units group _unit)) > 1) && {(leader group _unit) == _unit}) then
{
_grpUnits = units group _unit;
_grpUnits = _grpUnits - [_unit];
(group _unit) selectLeader (_grpUnits call BIS_fnc_selectRandom);
};
_av = _unit getVariable ["DMS_AssignedVeh",objNull];
if (!isNull _av) then
{
// Determine whether or not the vehicle has any active crew remaining.
_memCount = {alive _x} count (crew _av);
// Destroy the vehicle and add it to cleanup if there are no active crew members of the vehicle.
if (_memCount<1) then
{
moveOut _unit;
_av setDamage 1;
DMS_CleanUpList pushBack [_av,diag_tickTime,DMS_AIVehCleanUpTime];
_av spawn {sleep 1;_this enableSimulationGlobal false;};
if (DMS_DEBUG) then
{
diag_log format["DMS_DEBUG OnKilled :: Destroying used AI vehicle %1, disabling simulation, and adding to cleanup.",typeOf _av];
};
}
else
{
// Only check for this stuff for ground vehicles that have guns...
if ((_av isKindOf "LandVehicle") && {(count (weapons _av))>0}) then
{
_gunner = gunner _av;
_driver = driver _av;
// If the gunner is dead but the driver is alive, then the driver becomes the gunner.
// Helps with troll AI vehicles driving around aimlessly after the gunner is shot off. More realistic imo
if (((isNull _gunner) || {!(alive _gunner)}) && {!(isNull _driver) && {alive _driver}}) then
{
[_driver,_av] spawn
{
_driver = _this select 0;
_av = _this select 1;
_av setVehicleAmmoDef 1;
sleep 5+(random 3); // 3 to 6 seconds delay after gunner death, to simulate reaction/switching time.
// The unit has to be local or else some of the commands won't work. Might as well eject the driver from the vehicle and make him useful.
moveOut _driver;
if (!local _driver) exitWith {};
//doGetOut _driver;
//unassignVehicle _driver;
waitUntil {(vehicle _driver)==_driver};
_driver assignAsGunner _av;
[_driver] orderGetIn true;
sleep 1.5;
_driver moveInGunner _av;
if (DMS_DEBUG) then
{
diag_log format["DMS_DEBUG OnKilled :: Switching driver of AI Vehicle (%1) to gunner.",typeOf _av];
};
};
};
};
};
};
if (isPlayer _player) then
{
_veh = vehicle _player;
_playerObj = _player;
// Reveal the killer to the AI units
if (DMS_ai_share_info) then
{
{
if (((position _x) distance2D (position _unit)) <= DMS_ai_share_info_distance ) then
{
_x reveal [_player, 4.0];
};
} forEach allUnits;
};
// Fix for players killing AI from mounted vehicle guns
if (!(_player isKindOf "Exile_Unit_Player") && {!isNull (gunner _player)}) then
{
_playerObj = gunner _player;
};
if (!(_veh isEqualTo _player) && {(driver _veh) isEqualTo _player}) then
{
_playerObj = driver _veh;
// Don't reward players with poptabs/respect if configured to do so
if !(DMS_credit_roadkill) then
{
_playerObj = objNull;
};
// Remove gear from roadkills if configured to do so
if (DMS_remove_roadkill && {(random 100) <= DMS_remove_roadkill_chance}) then
{
_unit call _removeAll;
};
};
};
if ((!isNull _playerObj) && {((getPlayerUID _playerObj) != "") && {_playerObj isKindOf "Exile_Unit_Player"}}) then
{
_moneyGain = missionNamespace getVariable [format ["DMS_%1_%2_MoneyGain",_side,_type],0];
_repGain = missionNamespace getVariable [format ["DMS_%1_%2_RepGain",_side,_type],0];
if ((_moneyGain>0) || (_repGain>0)) then
{
_money = _playerObj getVariable ["ExileMoney", 0];
_respect = _playerObj getVariable ["ExileScore", 0];
if (_moneyGain>0) then
{
// Set client's money
_money = _money + _moneyGain;
_playerObj setVariable ["ExileMoney",_money];
// Send notification and update client's money stats
// Somebody done fucked up so you don't see the sender for the money sending ;)
[_playerObj, "moneyReceivedRequest", [str _money, "killing AI"]] call ExileServer_system_network_send_to;
};
if (_repGain>0) then
{
// Set client's respect
_respect = _respect + _repGain;
_playerObj setVariable ["ExileScore",_respect];
// Send frag message
[_playerObj, "showFragRequest", [ [["AI KILL",_repGain]] ] ] call ExileServer_system_network_send_to;
// Send updated respect value to client
ExileClientPlayerScore = _respect;
(owner _playerObj) publicVariableClient "ExileClientPlayerScore";
ExileClientPlayerScore = nil;
};
// Update client database entry
format["setAccountMoneyAndRespect:%1:%2:%3", _money, _respect, (getPlayerUID _playerObj)] call ExileServer_system_database_query_fireAndForget;
};
};
DMS_CleanUpList pushBack [_unit,diag_tickTime,DMS_CompletedMissionCleanupTime];