2021-10-14 15:46:43 +00:00
|
|
|
#include "script_component.hpp"
|
|
|
|
/*
|
|
|
|
* Author: PabstMirror
|
|
|
|
* Tracks deaths/kills and logs to the end mission disaplay
|
|
|
|
* Attemps to log kills from Medical by using "ace_killed" event.
|
|
|
|
*
|
|
|
|
* Note: Requires config setup in a mission's description.ext
|
|
|
|
* Has no effect if mission is not setup correctly.
|
|
|
|
*
|
|
|
|
* Arguments:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Return Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Public: No
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((getText (missionconfigfile >> "CfgDebriefingSections" >> QUOTE(XADDON) >> "variable")) != QXGVAR(outputText)) exitWith {
|
|
|
|
TRACE_1("no mission debriefing config",_this);
|
|
|
|
};
|
2024-06-20 05:04:34 +00:00
|
|
|
|
|
|
|
if !(GETEGVAR(medical,enabled,false)) exitWith {
|
2021-11-06 23:00:45 +00:00
|
|
|
WARNING("No ACE-Medical");
|
|
|
|
XGVAR(outputText) = "No ACE-Medical";
|
|
|
|
};
|
2021-10-14 15:46:43 +00:00
|
|
|
|
2021-10-21 17:42:34 +00:00
|
|
|
private _global = missionNamespace getVariable [QGVAR(globalSync), false]; // Global Sync (e.g. for spectator)
|
2021-10-30 21:42:03 +00:00
|
|
|
INFO_1("Running Kill Tracking [Global: %1]",_global);
|
2021-10-14 15:46:43 +00:00
|
|
|
|
|
|
|
// Variables:
|
|
|
|
GVAR(eventsArray) = [];
|
|
|
|
XGVAR(outputText) = format ["%1 0", LLSTRING(TotalKills)];
|
|
|
|
GVAR(killCount) = 0;
|
|
|
|
|
|
|
|
// Add Event Handlers:
|
|
|
|
[QGVAR(kill), {
|
|
|
|
params ["_name", "_killInfo"];
|
|
|
|
TRACE_2("kill eh",_name,_killInfo);
|
|
|
|
// Increment kill counter
|
|
|
|
GVAR(killCount) = GVAR(killCount) + 1;
|
|
|
|
GVAR(eventsArray) pushBack format [LLSTRING(Kill), _name, _killInfo];
|
|
|
|
XGVAR(outputText) = (format ["%1 %2<br/>", LLSTRING(TotalKills), GVAR(killCount)]) + (GVAR(eventsArray) joinString "<br/>");
|
2021-10-21 17:42:34 +00:00
|
|
|
if (missionNamespace getVariable [QGVAR(globalSync), false]) then {
|
|
|
|
ACE_player setVariable [QGVAR(output), XGVAR(outputText), true];
|
|
|
|
};
|
2021-10-14 15:46:43 +00:00
|
|
|
}] call CBA_fnc_addEventHandler;
|
|
|
|
|
|
|
|
[QGVAR(death), {
|
|
|
|
params ["_name", "_killInfo"];
|
|
|
|
TRACE_2("death eh",_name,_killInfo);
|
|
|
|
GVAR(eventsArray) pushBack format [LLSTRING(Killer), _name, _killInfo];
|
|
|
|
XGVAR(outputText) = (format ["%1 %2<br/>", LLSTRING(TotalKills), GVAR(killCount)]) + (GVAR(eventsArray) joinString "<br/>");
|
2021-10-21 17:42:34 +00:00
|
|
|
if (missionNamespace getVariable [QGVAR(globalSync), false]) then {
|
|
|
|
ACE_player setVariable [QGVAR(output), XGVAR(outputText), true];
|
|
|
|
};
|
2021-10-14 15:46:43 +00:00
|
|
|
}] call CBA_fnc_addEventHandler;
|
|
|
|
|
|
|
|
["ace_killed", {
|
|
|
|
params ["_unit", "_causeOfDeath", "_killer", "_instigator"];
|
|
|
|
TRACE_4("ace_killed EH",_unit,_causeOfDeath,_killer,_instigator);
|
|
|
|
|
|
|
|
if (!local _unit) exitWith {};
|
|
|
|
|
|
|
|
private _killInfo = [];
|
|
|
|
|
|
|
|
if (!isNull _killer) then {
|
2024-06-20 05:04:34 +00:00
|
|
|
if !(_killer isKindof "CAManBase") then { // If killer is a vehicle log the vehicle type
|
2022-03-09 03:41:21 +00:00
|
|
|
_killInfo pushBack format [LLSTRING(Vehicle), getText ((configOf _killer) >> "displayName")];
|
2021-10-14 15:46:43 +00:00
|
|
|
};
|
|
|
|
if (isNull _instigator) then {
|
|
|
|
_instigator = effectiveCommander _killer;
|
|
|
|
TRACE_2("using effectiveCommander",_instigator,_killer);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
private _unitIsPlayer = hasInterface && {_unit in [player, ace_player]}; // isPlayer check will fail at this point
|
2024-06-20 05:04:34 +00:00
|
|
|
private _instigatorIsPlayer = (!isNull _instigator) && {_unit != _instigator} && {[_instigator] call EFUNC(common,isPlayer)};
|
|
|
|
TRACE_2("",_unitIsPlayer,_instigatorIsPlayer);
|
2021-10-14 15:46:43 +00:00
|
|
|
|
|
|
|
// Don't do anything if neither are players
|
2024-06-20 05:04:34 +00:00
|
|
|
if !(_unitIsPlayer || _instigatorIsPlayer) exitWith {};
|
2021-10-14 15:46:43 +00:00
|
|
|
|
|
|
|
// Log firendly fire
|
|
|
|
private _fnc_getSideFromConfig = {
|
|
|
|
params ["_object"];
|
2022-03-09 03:41:21 +00:00
|
|
|
switch (getNumber ((configOf _object) >> "side")) do {
|
2021-10-14 15:46:43 +00:00
|
|
|
case (0): {east};
|
|
|
|
case (1): {west};
|
|
|
|
case (2): {resistance};
|
|
|
|
default {civilian};
|
|
|
|
};
|
|
|
|
};
|
2024-06-20 05:04:34 +00:00
|
|
|
if (!isNull _instigator && {_unit != _instigator} && {_instigator isKindOf "CAManBase"}) then {
|
2021-10-14 15:46:43 +00:00
|
|
|
// Because of unconscious group switching/captives it's probably best to just use unit's config side
|
|
|
|
private _unitSide = [_unit] call _fnc_getSideFromConfig;
|
|
|
|
private _killerSide = [_instigator] call _fnc_getSideFromConfig;
|
|
|
|
if ([_unitSide, _killerSide] call BIS_fnc_areFriendly) then {
|
|
|
|
_killInfo pushBack format["<t color='#ff0000'>%1</t>", LLSTRING(FriendlyFire)];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// Rough cause of death from statemachine (e.g. "CardiacArrest:Timeout"), could parse this to be more human readable
|
|
|
|
_killInfo pushBack _causeOfDeath;
|
|
|
|
|
|
|
|
// Parse info into text
|
|
|
|
_killInfo = if (_killInfo isEqualTo []) then {
|
|
|
|
""
|
|
|
|
} else {
|
|
|
|
format [" - [%1]", (_killInfo joinString ", ")];
|
|
|
|
};
|
|
|
|
|
|
|
|
// If unit was player then send event to self
|
|
|
|
if (_unitIsPlayer) then {
|
2024-06-20 05:04:34 +00:00
|
|
|
private _instigatorName = "Self?";
|
|
|
|
if ((!isNull _instigator) && {_unit != _instigator}) then {
|
|
|
|
if (_instigatorIsPlayer) then {
|
|
|
|
_instigatorName = [_instigator, true, false] call EFUNC(common,getName);
|
2021-10-14 15:46:43 +00:00
|
|
|
} else {
|
2024-06-20 05:04:34 +00:00
|
|
|
_instigatorName = _instigator getVariable [QGVAR(aiName), ""]; // allow setting a custom AI name (e.g. VIP Target)
|
|
|
|
if (_instigatorName == "") then {
|
|
|
|
_instigatorName = format ["*AI* - %1", getText ((configOf _instigator) >> "displayName")];
|
2021-10-14 15:46:43 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2024-06-20 05:04:34 +00:00
|
|
|
TRACE_3("send death event",_unit,_instigatorName,_killInfo);
|
|
|
|
[QGVAR(death), [_instigatorName, _killInfo]] call CBA_fnc_localEvent;
|
2021-10-14 15:46:43 +00:00
|
|
|
};
|
|
|
|
|
2024-06-20 05:04:34 +00:00
|
|
|
// If shooter was player then send event to them (and optionally the whole crew)
|
|
|
|
if (_instigatorIsPlayer && {_unitIsPlayer || GVAR(trackAI)}) then {
|
2021-10-14 15:46:43 +00:00
|
|
|
private _unitName = "";
|
|
|
|
if (_unitIsPlayer) then {
|
|
|
|
_unitName = [_unit, true, false] call EFUNC(common,getName); // should be same as profileName
|
|
|
|
} else {
|
|
|
|
_unitName = _unit getVariable [QGVAR(aiName), ""]; // allow setting a custom AI name (e.g. VIP Target)
|
|
|
|
if (_unitName == "") then {
|
2022-03-09 03:41:21 +00:00
|
|
|
_unitName = format ["*AI* - %1", getText ((configOf _unit) >> "displayName")];
|
2021-10-14 15:46:43 +00:00
|
|
|
};
|
|
|
|
};
|
2024-06-20 05:04:34 +00:00
|
|
|
TRACE_3("send kill event",_instigator,_unitName,_killInfo);
|
|
|
|
[QGVAR(kill), [_unitName, _killInfo], _instigator] call CBA_fnc_targetEvent;
|
|
|
|
|
|
|
|
if (GVAR(showCrewKills) && {!(_killer isKindOf "CAManBase")}) then {
|
|
|
|
private _crew = [driver _killer, gunner _killer, commander _killer] - [_instigator];
|
|
|
|
_crew = _crew select {[_x] call EFUNC(common,isPlayer)};
|
|
|
|
_crew = _crew arrayIntersect _crew;
|
|
|
|
TRACE_1("showCrewKills",_crew);
|
|
|
|
_killInfo = format [" - [<t color='#99ff99'>%1</t>, %2", localize "str_a3_rscdisplaygarage_tab_crew", _killInfo select [4]];
|
|
|
|
{
|
|
|
|
[QGVAR(kill), [_unitName, _killInfo], _x] call CBA_fnc_targetEvent;
|
|
|
|
} forEach _crew;
|
2024-02-19 23:53:47 +00:00
|
|
|
};
|
2021-10-14 15:46:43 +00:00
|
|
|
};
|
|
|
|
}] call CBA_fnc_addEventHandler;
|