Rework death messages

MPHit does not always fire when a player is killed:
https://community.bistudio.com/wiki/ArmA_2:_Event_Handlers#MPHit

Using either MPHit or MPKilled is not a good idea here. There is already
a local 'killed' event handler which fires on player death
(player_death.sqf). That script sends a PV (priority message) to the
server which triggers server_playerDied. That means fnc_plyrHit needed
to finish sending its data to the server via public setVariables
(non-priority messages) before server_playerDied executed. Triggering
both these scripts at the same time was a bad idea.

Instead of sending the data to the server via setVariable I just
included it in PVDZ_plr_Death. This also lets us pass extra information
from the damage handler like ammo type, cause of death, etc. Still need
to test, but it should be more reliable and performant than
fnc_playerHit called from MPHit or MPKilled.
This commit is contained in:
ebaydayz
2016-03-23 19:52:04 -04:00
parent debb714277
commit 3ed4a95c14
14 changed files with 188 additions and 246 deletions

View File

@@ -1,113 +1,76 @@
#include "\z\addons\dayz_server\compile\server_toggle_debug.hpp"
private ["_characterID","_minutes","_newObject","_playerID","_infected","_victim","_victimName","_killer","_killerName","_weapon","_distance","_message","_loc_message","_key","_death_record"];
private ["_characterID","_minutes","_newObject","_playerID","_key","_pos","_infected","_killerName","_killerWeapon","_distance","_message","_killerMethod"];
//[unit, weapon, muzzle, mode, ammo, magazine, projectile]
_characterID = _this select 0;
_minutes = _this select 1;
_newObject = _this select 2;
_playerID = _this select 3;
_infected = _this select 4;
_victimName = toString (_this select 5); // Sent as array to avoid publicVariable value restrictions
_victim = _newObject;
_newObject setVariable ["bodyName", _victimName, true];
_characterID = _this select 0;
_minutes = _this select 1;
_newObject = _this select 2;
_playerID = _this select 3;
_playerName = toString (_this select 4); //Sent as array to avoid publicVariable value restrictions
_infected = _this select 5;
_killerName = toString (_this select 6);
_killerWeapon = toString (_this select 7);
_distance = _this select 8;
_killerMethod = toString (_this select 9);
_killer = _victim getVariable["AttackedBy", "nil"];
_killerName = _victim getVariable["AttackedByName", "nil"];
// when a zombie kills a player _killer, _killerName && _weapon will be "nil"
// we can use this to determine a zombie kill && send a customized message for that. right now no killmsg means it was a zombie.
if ((typeName _killer) != "STRING") then
{
_weapon = _victim getVariable["AttackedByWeapon", "nil"];
_distance = _victim getVariable["AttackedFromDistance", "nil"];
if ((owner _victim) == (owner _killer)) then
{
_message = format["%1 killed himself",_victimName];
_loc_message = format["PKILL: %1 killed himself", _victimName];
}
else
{
_message = format["%1 was killed by %2 with weapon %3 from %4m",_victimName, _killerName, _weapon, _distance];
_loc_message = format["PKILL: %1 was killed by %2 with weapon %3 from %4m", _victimName, _killerName, _weapon, _distance];
};
diag_log _loc_message;
if(DZE_DeathMsgGlobal) then {
[nil, nil, rspawn, [_killer, _message], { (_this select 0) globalChat (_this select 1) }] call RE;
};
/* needs customRemoteMessage
if(DZE_DeathMsgGlobal) then {
customRemoteMessage = ['globalChat', _message, _killer];
publicVariable "customRemoteMessage";
};
*/
if(DZE_DeathMsgSide) then {
[nil, nil, rspawn, [_killer, _message], { (_this select 0) sideChat (_this select 1) }] call RE;
};
if(DZE_DeathMsgTitleText) then {
[nil,nil,"per",rTITLETEXT,_message,"PLAIN DOWN"] call RE;
};
// build array to store death messages to allow viewing at message board in trader citys.
_death_record = [
_victimName,
_killerName,
_weapon,
_distance,
ServerCurrentTime
];
PlayerDeaths set [count PlayerDeaths,_death_record];
// Cleanup
_victim setVariable["AttackedBy", "nil", true];
_victim setVariable["AttackedByName", "nil", true];
_victim setVariable["AttackedByWeapon", "nil", true];
_victim setVariable["AttackedFromDistance", "nil", true];
};
// Might not be the best way...
/*
if (isnil "dayz_disco") then {
dayz_disco = [];
};
*/
//Mark player as dead so we bypass the ghost system
dayz_died set [count dayz_died, _playerID];
// dayz_disco = dayz_disco - [_playerID];
_newObject setVariable["processedDeath",diag_tickTime];
_newObject setVariable ["bodyName", _victimName, true];
_newObject setVariable ["processedDeath",diag_tickTime];
_newObject setVariable ["bodyName",_playerName,true];
_pos = getPosATL _newObject;
if (_pos select 2 < 0.1) then { _pos set [2,0]; };
_newObject setVariable [ "deathPos", _pos];
if (typeName _minutes == "STRING") then
{
_minutes = parseNumber _minutes;
};
// force to follow the terrain slope in sched_corpses.sqf
if (_pos select 2 < 0.1) then {_pos set [2,0];};
_newObject setVariable ["deathPos",_pos];
diag_log ("PDEATH: Player Died " + _playerID);
if (typeName _minutes == "STRING") then {_minutes = parseNumber _minutes;};
if (_characterID != "0") then
{
if (_characterID != "0") then {
_key = format["CHILD:202:%1:%2:%3:",_characterID,_minutes,_infected];
#ifdef DZE_SERVER_DEBUG_HIVE
diag_log ("HIVE: WRITE: "+ str(_key));
#endif
//diag_log ("HIVE: WRITE: "+ str(_key));
_key call server_hiveWrite;
}
else
{
deleteVehicle _newObject;
};
#ifdef PLAYER_DEBUG
diag_log format ["Player UID#%3 CID#%4 %1 as %5 died at %2",
_newObject call fa_plr2str, (getPosATL _newObject) call fa_coor2str,
_newObject call fa_plr2str, _pos call fa_coor2str,
getPlayerUID _newObject,_characterID,
typeOf _newObject
];
#endif
// EPOCH DEATH MESSAGES
if (_killerWeapon == "Throw") then {_killerWeapon = "Grenade";};
if (_killerMethod in ["starve","dehyd","sick","bled","crushed","rad","zombie"]) then {
if (_killerMethod == "zombie") then {
_message = format[localize "str_player_death_zombie",_playerName];
} else {
_methodStr = localize format["str_death_%1",_killerMethod];
_message = format[localize "str_player_death_message",_playerName,_methodStr];
};
} else {
if (_killerName == _playerName) then {
_message = format[localize "str_player_death_suicide",_playerName];
} else {
_message = format[localize "str_player_death_killed",_playerName,_killerName,_killerWeapon,_distance];
};
};
if ((_killerWeapon != "unknown weapon") or {_killerMethod != "unknown"} or {_killerName != "unknown"}) then {
diag_log _message;
//if (DZE_DeathMsgGlobal) then {customRemoteMessage = ['globalChat',_message,_newObject]; publicVariable "customRemoteMessage";};
if (DZE_DeathMsgGlobal) then {[nil,nil,rspawn,[_newObject,_message],{(_this select 0) globalChat (_this select 1)}] call RE;};
if (DZE_DeathMsgSide) then {[nil,nil,rspawn,[_newObject,_message],{(_this select 0) sideChat (_this select 1)}] call RE;};
if (DZE_DeathMsgTitleText) then {[nil,nil,"per",rTITLETEXT,_message,"PLAIN DOWN"] call RE;};
// Store death messages to allow viewing at message board in trader citys.
PlayerDeaths set [count PlayerDeaths,[_playerName,_killerName,_killerWeapon,_distance,ServerCurrentTime]];
};
_newObject setDamage 1;
_newObject setOwner 0;
//dead_bodyCleanup set [count dead_bodyCleanup,_newObject];