From b312402c6c828860bf5855b1bafc0128cda478ef Mon Sep 17 00:00:00 2001 From: musurca Date: Mon, 13 May 2019 21:38:35 -0700 Subject: [PATCH] v1.23 --- README.md | 7 +++++- addons/GR/config.bin | Bin 1004 -> 1044 bytes addons/GR/config.cpp | 5 +++-- addons/GR/functions/fn_burybody.sqf | 10 ++------- addons/GR/functions/fn_exhumebody.sqf | 9 ++------ addons/GR/functions/fn_initCBA.sqf | 10 ++++++++- addons/GR/functions/fn_initClient.sqf | 3 +++ addons/GR/functions/fn_initServer.sqf | 21 +++++++++++++++--- addons/GR/functions/fn_localBodyBagged.sqf | 12 ++++++++++ ..._MPhint.sqf => fn_localNotifyCivDeath.sqf} | 12 ++++++++-- .../functions/fn_makeMissionDeliverBody.sqf | 13 +++++------ addons/GR/functions/fn_onClientCivKilled.sqf | 21 ++++++++++++++---- addons/GR/functions/fn_onLocalCivKilled.sqf | 18 ++++++++------- addons/GR/functions/fn_onUnitKilled.sqf | 7 ++++-- mod.cpp | 2 +- 15 files changed, 104 insertions(+), 46 deletions(-) create mode 100644 addons/GR/functions/fn_localBodyBagged.sqf rename addons/GR/functions/{fn_MPhint.sqf => fn_localNotifyCivDeath.sqf} (69%) diff --git a/README.md b/README.md index c825af0..c0afde6 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Requirements: [CBA_A3](https://github.com/CBATeam/CBA_A3), [ACE3](https://github **Features:** * When a player kills a civilian, a new task is generated requiring the player to deliver the body to a member of their family, who lives in a house in the AO (within 20km by default). * Alternatively, players may attempt to conceal the death by taking the body at least 300m away from a populated center, burying it, and striking off the dead civilian’s name from the grave marker. +* Civilian casualties are announced to everyone on the same side and marked on the map. * Any corpse in a body bag can now be buried or exhumed (requires an Entrenching Tool). * Burying any corpse produces a burial mound from which the dead person’s name and age can be read. * The items carried by the dead are transferred to the body bag, and persist through burial and exhumation. @@ -21,7 +22,7 @@ In order to deliver a dead civilian to their family member, you must first place You can also bury or exhume any body bags if you are carrying an Entrenching Tool. -You can change how your notifications for civilian casualties are displayed in your Addon Settings (listed under "Guilt & Remembrance."). Note that this setting may be overriden by the mission creator or server operator. +You can change how your notifications for civilian casualties are displayed in your Addon Options (listed under "Guilt & Remembrance."). Note that this setting may be overriden by the mission creator or server operator. **FOR MISSION CREATORS & SERVER OPERATORS:** This mod is fully signed for multiplayer use, and has been tested on both local and dedicated servers. It must be run on both the client and server. @@ -76,6 +77,10 @@ For questions, comments, or bug reports, please contact me directly at nick.musu CHANGELOG: --------------------- +v1.23 (May 13, 2019): +* civilian casualties now marked on your map (but can be disabled from CBA settings) +* more reliable performance under heavy CPU load / adverse network conditions + v1.22 (May 13, 2019): * bugfix: now supports Antistasi (as well as other mods/game types where civilians are created on the client-side) diff --git a/addons/GR/config.bin b/addons/GR/config.bin index 110002c77fc9910f00b2102d55b74508e7b69841..da87b0ee4b019d658a4001c31720cf2450b30f1c 100644 GIT binary patch delta 539 zcmZutJxc>I7=Du$Egfp5E>f_dICXMza_oWLp%N&LS;X5k%VK*&nZ~3F^`k7Uy zTSn|pqO>2nDQp`gZ-P~u*NF+Fh6RwLl?MV?2n+b;7M~{!0+D44z zC`{zP`bl;;3N`~LwFw6 z9wTYS2#oQYNVahxz!1*$8(-nYoPOt(Da{6G7Em{4pz5|VP*GdWb^uBW9ddSQ6|_<` qn}Z(Co(5<4NCXWrmhgzia^B>D)>+T;ODOax*(<5~J~t?k34Py`jeD~I literal 1004 zcmZ`&O>fgc6dXH3f)f%F2gJp_@F9T&>Irc`N!kWfB84DMEwVQDOT6lOU3S-|E#kxv z<45o(dgTWoc)OdV3D8K6J@aw`j)3_aYAEhEhoQ6O0w*r zDbI1+*JiCbpLulGBRZ?vngYJ>amT|DN?y>yh>o!1IZ>9ZzemDVn*+l`Uo=!V9sRfd zbhWwR@d@>>!0v{?b!%QMMK=1_GV$t4gf%LuN5pOqsF`(vR8!V>0ebM+}q z^EICbYv0zz1SjD`f}B6vkv5*7$C;~0XJ4|T+*Q(MmJ}5(d-f#T!p}cue4bP`n&xv| Qh($ diff --git a/addons/GR/config.cpp b/addons/GR/config.cpp index 4e461c1..f021823 100644 --- a/addons/GR/config.cpp +++ b/addons/GR/config.cpp @@ -22,7 +22,7 @@ class CfgFunctions class initServer { postInit = 1; }; class onUnitKilled {}; class onLocalCivKilled {}; - class onClientCivKilled {}; + class onClientCivKilled {}; class makeMissionDeliverBody {}; class burybody {}; class exhumebody {}; @@ -33,7 +33,8 @@ class CfgFunctions class removeConcealDeathEventHandler {}; class addDeliverBodyEventHandler {}; class removeDeliverBodyEventHandler {}; - class MPhint {}; + class localNotifyCivDeath {}; + class localBodyBagged {}; }; }; }; diff --git a/addons/GR/functions/fn_burybody.sqf b/addons/GR/functions/fn_burybody.sqf index 2a0f987..a9f7ae5 100644 --- a/addons/GR/functions/fn_burybody.sqf +++ b/addons/GR/functions/fn_burybody.sqf @@ -31,11 +31,7 @@ if ((count _dogtagData) == 0) then { [_player, _target] call ace_dogtags_fnc_takeDogtag; }; -_cargo = objNull; -_cargoId = _target getVariable ["GR_CARGO",0]; -if (!(_cargoId isEqualTo 0)) then { - _cargo = _cargoId call BIS_fnc_objectFromNetId; -}; +_cargo = _target getVariable ["GR_CARGO",objNull]; if (!(_cargo isEqualTo objNull)) then { detach _cargo; _cargo setPos [0,0,0]; @@ -49,9 +45,7 @@ _grave setPos _posTarget; _grave setVariable ["CORPSE_ID", _cId]; _grave setVariable ["DOGTAG_DATA", _dogtagData, true]; _grave setVariable ["AGE",_vicAge, true]; -if(!(_cargoId isEqualTo 0)) then { - _grave setVariable ["GR_CARGO",_cargoId]; -}; +_grave setVariable ["GR_CARGO",_cargo]; if (_task != "") then { _grave setVariable ["GR_HIDEBODY_TASK",_task]; _grave setVariable ["GR_NEXTOFKIN",_nextOfKin]; diff --git a/addons/GR/functions/fn_exhumebody.sqf b/addons/GR/functions/fn_exhumebody.sqf index 4e140dc..ba4ecfc 100644 --- a/addons/GR/functions/fn_exhumebody.sqf +++ b/addons/GR/functions/fn_exhumebody.sqf @@ -22,7 +22,7 @@ _dogtagData = _target getVariable "DOGTAG_DATA"; _vicAge = _target getVariable "AGE"; _task = _target getVariable ["GR_HIDEBODY_TASK",""]; _nextOfKin = _target getVariable ["GR_NEXTOFKIN",objNull]; -_cargoId = _target getVariable ["GR_CARGO",0]; +_cargo = _target getVariable ["GR_CARGO",objNull]; deleteVehicle _target; _body = "ACE_bodyBagObject" createVehicle [0,0,0]; @@ -36,15 +36,10 @@ if (_task != "") then { _body setVariable ["GR_NEXTOFKIN",_nextOfKin]; }; -_cargo = objNull; -if (!(_cargoId isEqualTo 0)) then { - _cargo = _cargoId call BIS_fnc_objectFromNetId; -}; if (_cargo isEqualTo objNull) then { _cargo = "Supply500" createVehicle [0,0,0]; - _cargoId = _cargo call BIS_fnc_netId; }; _cargo attachTo [_body, [0,0,0.85]]; -_body setVariable ["GR_CARGO",_cargoId]; +_body setVariable ["GR_CARGO",_cargo]; \ No newline at end of file diff --git a/addons/GR/functions/fn_initCBA.sqf b/addons/GR/functions/fn_initCBA.sqf index cf12b8f..0a5a611 100644 --- a/addons/GR/functions/fn_initCBA.sqf +++ b/addons/GR/functions/fn_initCBA.sqf @@ -21,7 +21,15 @@ GR_NOTIFY_HINT=2; [ "GR_DEATHNOTIFY_STYLE", "LIST", - "Civilian Death Notification Style", + "Civilian death notification style", "Guilt & Remembrance", [[GR_NOTIFY_DIARY,GR_NOTIFY_SIDECHAT,GR_NOTIFY_HINT],["Diary Record Only","Side Chat (lower left)","Hint (top right)"],2] +] call CBA_fnc_AddSetting; + +[ + "GR_DEATHNOTIFY_MARKER", + "CHECKBOX", + "Mark civilian deaths on map", + "Guilt & Remembrance", + true ] call CBA_fnc_AddSetting; \ No newline at end of file diff --git a/addons/GR/functions/fn_initClient.sqf b/addons/GR/functions/fn_initClient.sqf index e9e454b..aeb7017 100644 --- a/addons/GR/functions/fn_initClient.sqf +++ b/addons/GR/functions/fn_initClient.sqf @@ -13,6 +13,9 @@ if(!hasInterface) exitWith{}; if (isNil "GR_DEATHNOTIFY_STYLE") then { GR_DEATHNOTIFY_STYLE=GR_NOTIFY_HINT; }; +if (isNil "GR_DEATHNOTIFY_MARKER") then { + GR_DEATHNOTIFY_MARKER=true; +}; // new ACE actions for body bags and graves GR_ace_burialAction = ["actionBury","Bury","",{ diff --git a/addons/GR/functions/fn_initServer.sqf b/addons/GR/functions/fn_initServer.sqf index c936e91..2d0d965 100644 --- a/addons/GR/functions/fn_initServer.sqf +++ b/addons/GR/functions/fn_initServer.sqf @@ -35,12 +35,26 @@ GR_PLAYER_TASKS = [[],[]] call CBA_fnc_hashCreate; // trace ID of corpse ["ace_placedInBodyBag", { params["_target","_bodybag"]; + if(!isServer) exitWith{}; + + _corpseId = _target getVariable "CORPSE_ID"; + _bodyTask = _target getVariable ["GR_HIDEBODY_TASK",""]; + if(_bodyTask != "") then { + // Tell everyone on side that the body has been bagged + _taskInfo = [GR_TASK_OWNERS,_bodyTask] call CBA_fnc_hashGet; + _taskSide = _taskInfo select 1; + [_corpseId] remoteExec ["GR_fnc_localBodyBagged",_taskSide]; + } else + { + // Just tell everyone because we're not sure who shot him + [_corpseId] remoteExec ["GR_fnc_localBodyBagged"]; + }; // Set up GR variables - _bodybag setVariable ["CORPSE_ID",_target call BIS_fnc_netId]; + _bodybag setVariable ["CORPSE_ID",_corpseId]; _bodybag setVariable ["AGE",_target getVariable ["AGE",0],true]; // only broadcast AGE to clients when in the bodybag _bodybag setVariable ["GR_NEXTOFKIN",_target getVariable ["GR_NEXTOFKIN",objNull]]; - _bodybag setVariable ["GR_HIDEBODY_TASK",_target getVariable ["GR_HIDEBODY_TASK",""]]; + _bodybag setVariable ["GR_HIDEBODY_TASK",_bodyTask]; // Transfer inventory _weaps = weapons _target; @@ -55,7 +69,7 @@ GR_PLAYER_TASKS = [[],[]] call CBA_fnc_hashCreate; _cargo = "Supply500" createVehicle [0,0,0]; _cargo attachTo [_bodybag, [0,0,0.85]]; - _bodybag setVariable ["GR_CARGO",_cargo call BIS_fnc_netId]; + _bodybag setVariable ["GR_CARGO",_cargo]; [_cargo,_items,_weaps,_mags] spawn { params["_cargo","_items","_weaps","_mags"]; @@ -66,6 +80,7 @@ GR_PLAYER_TASKS = [[],[]] call CBA_fnc_hashCreate; }; }] call CBA_fnc_addEventHandler; +// Add event handler for people killed on server ["CAManBase", "killed",GR_fnc_onUnitKilled] call CBA_fnc_addClassEventHandler; // Remove GR tasks from a player's responsibility 10 min after disconnect diff --git a/addons/GR/functions/fn_localBodyBagged.sqf b/addons/GR/functions/fn_localBodyBagged.sqf new file mode 100644 index 0000000..416f30c --- /dev/null +++ b/addons/GR/functions/fn_localBodyBagged.sqf @@ -0,0 +1,12 @@ +/* + + fn_localBodyBagged.sqf + by @musurca + + Callback from server notifying client that a corpse has been bagged. + +*/ + +params["_corpseId"]; + +deleteMarkerLocal format["GRmrk_%1",_corpseId]; \ No newline at end of file diff --git a/addons/GR/functions/fn_MPhint.sqf b/addons/GR/functions/fn_localNotifyCivDeath.sqf similarity index 69% rename from addons/GR/functions/fn_MPhint.sqf rename to addons/GR/functions/fn_localNotifyCivDeath.sqf index e1b78a2..39ad52f 100644 --- a/addons/GR/functions/fn_MPhint.sqf +++ b/addons/GR/functions/fn_localNotifyCivDeath.sqf @@ -1,6 +1,6 @@ /* - fn_MPhint.sqf + fn_localNotifyCivDeath.sqf by @musurca Function for printing text notifications from server. Depends on player/mission/server-determined notification style. @@ -8,7 +8,7 @@ */ -params["_killerName","_killedName","_killedAge"]; +params["_killerName","_killedName","_killedAge", "_killedPos", "_killedId"]; switch (GR_DEATHNOTIFY_STYLE) do { case GR_NOTIFY_HINT: { @@ -22,6 +22,14 @@ switch (GR_DEATHNOTIFY_STYLE) do { }; }; +if (GR_DEATHNOTIFY_MARKER) then { + _marker = createMarkerLocal [format["GRmrk_%1",_killedId],_killedPos]; + _marker setMarkerShapeLocal "ICON"; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorYellow"; + _marker setMarkerAlphaLocal 0.5; +}; + // Make diary record of killing _diaryText= format ["%1 killed %2 (age %3).", _killerName, _killedName, _killedAge]; player createDiaryRecord ["Diary", ["Civilian Deaths", _diaryText]]; \ No newline at end of file diff --git a/addons/GR/functions/fn_makeMissionDeliverBody.sqf b/addons/GR/functions/fn_makeMissionDeliverBody.sqf index d47bb45..bf04c07 100644 --- a/addons/GR/functions/fn_makeMissionDeliverBody.sqf +++ b/addons/GR/functions/fn_makeMissionDeliverBody.sqf @@ -42,15 +42,13 @@ if (count _bposlist == 0) exitWith { // no place for kin to spawn _spawnPos = (selectRandom _bposlist); _nextOfKinGrp = createGroup civilian; -_nextOfKinGrp = [_spawnPos, civilian, [selectRandom GR_CIV_TYPES]] call BIS_fnc_spawnGroup; -sleep 2; -_nextOfKin = (units _nextOfKinGrp) select 0; +_nextOfKin = _nextOfKinGrp createUnit [selectRandom GR_CIV_TYPES, _spawnPos, [],0, "NONE"]; _nextOfKin setPosATL _spawnPos; _nextOfKin setUnitPos "up"; _nextOfKin allowFleeing 0; doStop _nextOfKin; -_bigTask = format ["CivDead%1",_nextOfKin call BIS_fnc_netId]; +_bigTask = format ["GRtsk_%1",_nextOfKin call BIS_fnc_netId]; [side _killer,_bigTask,[format ["Deliver the body of %1 to his nearest relative.",name _killed],"Deal with Civilian Death","meet"], _nextOfKin,"CREATED",0,false,"meet"] call BIS_fnc_taskCreate; _nextOfKin setVariable ["GR_DELIVERBODY_TASK",_bigTask]; @@ -115,13 +113,14 @@ _deathArray pushBack _nextOfKin; if( ({_x distance _kin <= 20} count allPlayers) > 0 ) then { _objs = _kin nearObjects ["ACE_bodyBagObject", 5]; if (count _objs > 0) then { - _cId = _kin getVariable ["GR_CORPSE_ID",0]; + _cId = _kin getVariable ["GR_CORPSE_ID","0:0"]; + _bodyFound=false; _body = objNull; { - if ((_x getVariable ["CORPSE_ID",0]) == _cId) exitWith { _body = _x}; + if ((_x getVariable ["CORPSE_ID","-1:-1"]) == _cId) exitWith { _body = _x; _bodyFound=true }; } forEach _objs; - if (_body != objNull) then { + if (_bodyFound) then { _kin lookAt _body; [_task,"Succeeded",false] call BIS_fnc_taskSetState; diff --git a/addons/GR/functions/fn_onClientCivKilled.sqf b/addons/GR/functions/fn_onClientCivKilled.sqf index 7b52d1b..eba6b30 100644 --- a/addons/GR/functions/fn_onClientCivKilled.sqf +++ b/addons/GR/functions/fn_onClientCivKilled.sqf @@ -11,11 +11,24 @@ if (!isServer) exitWith {}; params["_killed", "_killer", "_name"]; -// Transfer ownership to server immediately -(group _killed) setGroupOwner 2; - -// Fix strange name transfer bug +/* Workaround for name bug in MP engine. + (Only last names of civilians created on the client + are given to the server when ownership is transferred.) +*/ _nameTokens = _name splitString " "; _killed setName [_name, _nameTokens select 0, _nameTokens select 1]; +// Call event handler as if civilian was killed on server [_killed, _killer] call GR_fnc_onUnitKilled; + +// Schedule a transfer of ownership to server. +// The short delay prevents strange rag-doll behavior. +[_killed] spawn { + params["_killed"]; + sleep 5; + (group _killed) setGroupOwner 2; + sleep 5; + if (isInRemainsCollector _killed) then { + removeFromRemainsCollector [_killed]; + }; +}; \ No newline at end of file diff --git a/addons/GR/functions/fn_onLocalCivKilled.sqf b/addons/GR/functions/fn_onLocalCivKilled.sqf index 5015621..6b70c71 100644 --- a/addons/GR/functions/fn_onLocalCivKilled.sqf +++ b/addons/GR/functions/fn_onLocalCivKilled.sqf @@ -9,15 +9,17 @@ params ["_killed", ["_killer", objNull]]; -if ((isNull _killer) || {_killer == _killed}) then { - _killer = _killed getVariable ["ace_medical_lastDamageSource", objNull]; -}; +if(side (group _killed) == civilian) then { + // Workaround for ACE medical + if ((isNull _killer) || {_killer == _killed}) then { + _killer = _killed getVariable ["ace_medical_lastDamageSource", objNull]; + }; -// See if it's a vehicle -if ((!isNull _killer) && {!(_killer isKindof "CAManBase")}) then { - _killer = effectiveCommander _killer; -}; + // Civilian killed by vehicle? + if ((!isNull _killer) && {!(_killer isKindof "CAManBase")}) then { + _killer = effectiveCommander _killer; + }; -if(side (group _killed) == civilian) then { + // Tell the server about killing and start transfer of ownership [_killed, _killer, name _killed] remoteExecCall ["GR_fnc_onClientCivKilled",2]; }; \ No newline at end of file diff --git a/addons/GR/functions/fn_onUnitKilled.sqf b/addons/GR/functions/fn_onUnitKilled.sqf index a7eded8..a571ba2 100644 --- a/addons/GR/functions/fn_onUnitKilled.sqf +++ b/addons/GR/functions/fn_onUnitKilled.sqf @@ -23,14 +23,17 @@ if ((!isNull _killer) && {!(_killer isKindof "CAManBase")}) then { if ((side group _killed) == civilian) then { _vicAge = round random [15,40,79]; _killed setVariable ["AGE",_vicAge]; + + _killedId = _killed call BIS_fnc_netId; + _killed setVariable ["CORPSE_ID",_killedId]; // Notify the players of the killing - [name _killer, name _killed, _vicAge] remoteExec ["GR_fnc_MPhint", side _killer]; + [name _killer, name _killed, _vicAge, position _killed, _killedId] remoteExec ["GR_fnc_localNotifyCivDeath", side _killer]; // Players get an "apology" mission if (isPlayer _killer) then { if( (random 100) < GR_MISSION_CHANCE ) then { - [_killer, _killed] spawn GR_fnc_makeMissionDeliverBody; + [_killer, _killed] call GR_fnc_makeMissionDeliverBody; } else { // Call custom event upon civilian murder by player anyway { diff --git a/mod.cpp b/mod.cpp index 496df1c..3ea935f 100644 --- a/mod.cpp +++ b/mod.cpp @@ -12,4 +12,4 @@ overview = "Civilian deaths, reparations, and war crimes. Deliver the bodies of author = "@musurca"; overviewText = "GR"; overviewPicture = "img\logomain.paa"; -overviewFootnote = "v122"; \ No newline at end of file +overviewFootnote = "v123"; \ No newline at end of file