diff --git a/README.md b/README.md index b1777e9..04bf3cd 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ In order to use this script, you need to run these mods alongside it: Mount this mod and configure it in Eden editor. Any configuration will be done within Eden editor and in `Settings -> Addon Options -> Diwako's ACE Ragdoll` +Beginning with version 1.1 server only mode is available for the mod is avaiable. Script version has the option as well, but it is a rather useless thing there.\ +When server only mode is activated then only the server needs to run the mod, the drawback is that no custom animations will be supported! + ## Troubleshooting In any event, that something goes wrong, you can disable ragdolling by setting the variable `diwako_ragdoll_ragdolling` to `false` on all machines.\ Additionally for ingame error handling you can either run ACE's headbug fix or reapply unconsciousness and take it away again. @@ -24,6 +27,9 @@ Additionally for ingame error handling you can either run ACE's headbug fix or r ## Additional Discussion can be found in the [BI Thread](https://forums.bohemia.net/forums/topic/215720-release-ragdolling-on-player-ace-unconsciousness/), for bug reports please use the thread on the BI forums. +## Special thanks +Special thanks to KokaKolaA3 for donating animations! + ## License Copyright 2018 diwako diff --git a/ace_ragdoll_unconscious.VR/description.ext b/ace_ragdoll_unconscious.VR/description.ext index c4141ae..8f4fa31 100644 --- a/ace_ragdoll_unconscious.VR/description.ext +++ b/ace_ragdoll_unconscious.VR/description.ext @@ -10,6 +10,15 @@ class cfgFunctions { class functions { file = "scripts\diwako\ragdoll"; class initRagdoll{}; + class animChangedEH{}; }; }; -}; \ No newline at end of file +}; + +respawn = BASE; +respawnDelay = 2; +respawnDialog = 0; + +// Debug (and CBA target debug) +enableDebugConsole = 1; +enableTargetDebug = 1; \ No newline at end of file diff --git a/ace_ragdoll_unconscious.VR/mission.sqm b/ace_ragdoll_unconscious.VR/mission.sqm index 819cdf7..aa3de7f 100644 Binary files a/ace_ragdoll_unconscious.VR/mission.sqm and b/ace_ragdoll_unconscious.VR/mission.sqm differ diff --git a/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/cba_settings.sqf b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/cba_settings.sqf index a0033ea..f321df2 100644 --- a/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/cba_settings.sqf +++ b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/cba_settings.sqf @@ -8,10 +8,10 @@ false, // data for this setting true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer { - params ["_value"]; - if (_value isEqualTo true) then { - [] call diwako_ragdoll_fnc_initRagdoll; - }; + params ["_value"]; + if ((_value isEqualTo true) && !diwako_ragdoll_server_only) then { + [] call diwako_ragdoll_fnc_initRagdoll; + }; } // function that will be executed once on mission start and every time the setting is changed. ] call CBA_Settings_fnc_init; @@ -23,4 +23,27 @@ false, // data for this setting true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer {} // function that will be executed once on mission start and every time the setting is changed. +] call CBA_Settings_fnc_init; + +[ + "diwako_ragdoll_server_only", // Internal setting name, should always contain a tag! This will be the global variable which takes the value of the setting. + "CHECKBOX", // setting type + ["Server only mode", "Sets the mod only to be required to run on server. Only vanilla Arma3 animations wil be used! This mode is only useful for the mod version, leave it disabled for script version!"], // Pretty name of the category where the setting can be found. Can be stringtable entry. + SETTINGS, // Pretty name shown inside the ingame settings menu. Can be stringtable entry. + false, // data for this setting + true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer + { + params ["_value"]; + if ((_value isEqualTo true) && diwako_ragdoll_ragdolling && isServer) then { + publicVariable "diwako_ragdoll_fnc_initRagdoll"; + publicVariable "diwako_ragdoll_fnc_animChangedEH"; + publicVariable "diwako_ragdoll_server_only"; + publicVariable "diwako_ragdoll_ragdolling"; + publicVariable "diwako_ragdoll_ai"; + [0,{ + waitUntil { !(isNil "diwako_ragdoll_fnc_initRagdoll") && !(isNil "diwako_ragdoll_fnc_animChangedEH") && !(isNil "diwako_ragdoll_server_only") && !(isNil "diwako_ragdoll_ragdolling") && !(isNil "diwako_ragdoll_ai") }; + [] call diwako_ragdoll_fnc_initRagdoll; + }] remoteExec ["spawn",0,true]; + }; + } // function that will be executed once on mission start and every time the setting is changed. ] call CBA_Settings_fnc_init; \ No newline at end of file diff --git a/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_animChangedEH.sqf b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_animChangedEH.sqf new file mode 100644 index 0000000..10aa7cc --- /dev/null +++ b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_animChangedEH.sqf @@ -0,0 +1,119 @@ +/* + Author: diwako + + Description: + Code for AnimChanged eventhandler + + Parameter(s): + _unit - Ragdolled unit + _anim - Currentl changed animation + + Examples: + (begin) + [_unit,_anim] call diwako_ragdoll_fnc_animChangedEH; + (end) + + Returns: + none +*/ +params ["_unit","_anim"]; +if(!(_unit getVariable ["ACE_isUnconscious",false])) exitWith {}; // do not run if unit is conscious +if(!(alive _unit) && // do not run if unit is dead + {!(isNull objectParent _unit)}) exitWith {}; // do not run if unit in any vehicle + +_anim = toLower(_anim); + +if((_anim find "unconsciousrevive") != -1 || // catch ragdoll recovery animations + {_anim == "unconsciousoutprone" || // catch another ragdoll recovery animation + {(_anim find "amov") == 0 }} ) then { // catch any movement or stance type of animation (player specific clause) + _anim = "unconscious"; + + // figure out which position state is need + private _vRightShoulder = _unit selectionPosition "rightshoulder"; + private _vLeftShoulder = _unit selectionPosition "leftshoulder"; + private _heightDif = _vRightShoulder#2 - _vLeftShoulder#2; + + // array of array for each animation + private _animHolder = []; + + if(isNil "diwako_ragdoll_animHolder") then { + diwako_ragdoll_animHolder = []; + if(!diwako_ragdoll_server_only && {isClass(configFile >> "CfgPatches" >> "diwako_ragdoll")}) then { + // mod version found + diwako_ragdoll_animHolder pushBack ["kka3_unc_2"]; // 0 on their back + diwako_ragdoll_animHolder pushBack ["kka3_unc_1", "kka3_unc_3", "kka3_unc_4","unconscious","KIA_passenger_boat_holdleft"]; // 1 on their belly + diwako_ragdoll_animHolder pushBack ["kka3_unc_7","kka3_unc_8"]; // 2 on their right shoulder + diwako_ragdoll_animHolder pushBack ["kka3_unc_5","kka3_unc_6","KIA_driver_boat01"]; // 3 on their left shoulder + } else { + // script version or server only mode + diwako_ragdoll_animHolder pushBack ["unconscious"]; // 0 on their back + diwako_ragdoll_animHolder pushBack ["unconscious","KIA_passenger_boat_holdleft"]; // 1 on their belly + diwako_ragdoll_animHolder pushBack ["unconscious"]; // 2 on their right shoulder + diwako_ragdoll_animHolder pushBack ["unconscious","KIA_driver_boat01"]; // 3 on their left shoulder + }; + }; + + if( _heightDif > 0.2 || _heightDif < -0.2) then { + // unit on side + // first one is right shoulder, second one is on left shoulder + _anim = selectRandom ([ diwako_ragdoll_animHolder#2 , diwako_ragdoll_animHolder#3 ] select (_heightDif < -0.2)); + } else { + if(_vRightShoulder#0 > _vLeftShoulder#0) then { + // unit on their belly + _anim = selectRandom (diwako_ragdoll_animHolder#1); + } else { + // unit on their back + _anim = selectRandom (diwako_ragdoll_animHolder#0); + }; + }; + + _unit setUnconscious false; + // play animation + [ + { + params ["_unit","_anim"]; + if(_unit getVariable ["ACE_isUnconscious",false]) then { + // [_unit, _anim, 2, true] call ace_common_fnc_doAnimation; + if(_unit == ace_player) then { + ["ace_common_switchMove", [_unit, _anim]] call CBA_fnc_globalEvent; + } else { + _unit switchMove _anim; + }; + }; + }, // code + [_unit,_anim], // params + 0.2 // delay + ] call CBA_fnc_waitAndExecute; + + // combat network sync issues + if(isMultiplayer) then { + [ + { + params ["_unit","_anim"]; + if((_unit getVariable ["ACE_isUnconscious",false]) && // unit still unconscious + {(isNull objectParent _unit) && // unit not in a car + {!([_unit] call ace_medical_fnc_isBeingCarried) && // not being carried + {!([_unit] call ace_medical_fnc_isBeingDragged)}}} // not being dragged + ) then { + // reapply unconscious animation just in case + // [_unit, _anim, 2, true] call ace_common_fnc_doAnimation; + if(_unit == ace_player) then { + ["ace_common_switchMove", [_unit, _anim]] call CBA_fnc_globalEvent; + } else { + _unit switchMove _anim; + }; + }; + if(!(_unit getVariable ["ACE_isUnconscious",false])) then { + // unit is not unconscious anymore + _unit setUnconscious false; + // free unit of unconscious animation if it is still trapped in it + if(animationState _unit == _anim) then { + _unit switchMove ""; + }; + }; + }, // code + [_unit,_anim], // params + 6.25 // delay + ] call CBA_fnc_waitAndExecute; + }; +}; \ No newline at end of file diff --git a/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_initRagdoll.sqf b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_initRagdoll.sqf index b8ac4ba..0e928b6 100644 --- a/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_initRagdoll.sqf +++ b/ace_ragdoll_unconscious.VR/scripts/diwako/ragdoll/fn_initRagdoll.sqf @@ -22,44 +22,21 @@ diwako_ragdoll_ragdollRunning = true; ["ace_unconscious", { params [["_unit", objNull],["_state", false]]; - if(!diwako_ragdoll_ragdolling) exitWith {}; // ragdolling if it active - if( (_unit != player && {!diwako_ragdoll_ai}) || (!local _unit)) exitWith {}; // only ragdoll players and only ragdolling if it active - if(_state && {vehicle _unit == _unit && {!([_unit] call ace_medical_fnc_isBeingCarried) && {!([_unit] call ace_medical_fnc_isBeingDragged)}}}) then { - // ragdoll player + // if(!local _unit || {!diwako_ragdoll_ragdolling}) exitWith {}; // ragdolling if it's active and unit local + if(!diwako_ragdoll_ragdolling) exitWith {}; // ragdolling if it's active + if((!(isPlayer _unit) && {!diwako_ragdoll_ai})) exitWith {}; // only ragdoll players and only ragdolling AI if that option is set active + if(_state && {(isNull objectParent _unit) && {!([_unit] call ace_medical_fnc_isBeingCarried) && {!([_unit] call ace_medical_fnc_isBeingDragged)}}}) then { + // ragdoll unit _unit setUnconscious true; }; if(!_state) then { - // player woke up before ragdolling was finished + // unit woke up before ragdolling was finished _unit setUnconscious false; }; }] call CBA_fnc_addEventHandler; ["CAManBase", "AnimChanged", { - params ["_unit","_anim"]; - if(!diwako_ragdoll_ragdolling) exitWith {}; // disable ragdolling mid mission - if( (_unit != player && {!diwako_ragdoll_ai}) || !(local _unit)) exitWith {}; // only run on players if ai setting is disabled - if(_anim == "unconsciousrevivedefault" && {alive _unit && {_unit getVariable ["ACE_isUnconscious",false] && {vehicle _unit == _unit}}}) then { - // unit stopped ragdolling, apply ace_death animation to unit - _unit setUnconscious false; - [_unit, [_unit] call ace_common_fnc_getDeathAnim, 2, true] call ace_common_fnc_doAnimation; - if(isMultiplayer) then { - // combat sync issues - [ - { - params ["_unit"]; - if(!(_unit getVariable ["ACE_isUnconscious",false])) then { - // unit is not unconscious anymore - _unit setUnconscious false; - } else { - // unit is still unconscious, reapply death animation just in case and sync it again to all clients - [_unit, [_unit] call ace_common_fnc_getDeathAnim, 2, true] call ace_common_fnc_doAnimation; - }; - }, // code - [_unit], // params - 5 // delay - ] call CBA_fnc_waitAndExecute; - }; - }; + _this call diwako_ragdoll_fnc_animChangedEH; }] call CBA_fnc_addClassEventHandler; player createDiaryRecord ["CBA_docs", ["Ragdolling", "Ragdolling has been activated in this mission! Better check those bodies!"]]; \ No newline at end of file diff --git a/mod/anims/kka3_unc_1.rtm b/mod/anims/kka3_unc_1.rtm new file mode 100644 index 0000000..97b9c9e Binary files /dev/null and b/mod/anims/kka3_unc_1.rtm differ diff --git a/mod/anims/kka3_unc_2.rtm b/mod/anims/kka3_unc_2.rtm new file mode 100644 index 0000000..cba9c8c Binary files /dev/null and b/mod/anims/kka3_unc_2.rtm differ diff --git a/mod/anims/kka3_unc_3.rtm b/mod/anims/kka3_unc_3.rtm new file mode 100644 index 0000000..57e850a Binary files /dev/null and b/mod/anims/kka3_unc_3.rtm differ diff --git a/mod/anims/kka3_unc_4.rtm b/mod/anims/kka3_unc_4.rtm new file mode 100644 index 0000000..93bedd1 Binary files /dev/null and b/mod/anims/kka3_unc_4.rtm differ diff --git a/mod/anims/kka3_unc_5.rtm b/mod/anims/kka3_unc_5.rtm new file mode 100644 index 0000000..0c6d345 Binary files /dev/null and b/mod/anims/kka3_unc_5.rtm differ diff --git a/mod/anims/kka3_unc_6.rtm b/mod/anims/kka3_unc_6.rtm new file mode 100644 index 0000000..8135573 Binary files /dev/null and b/mod/anims/kka3_unc_6.rtm differ diff --git a/mod/anims/kka3_unc_7.rtm b/mod/anims/kka3_unc_7.rtm new file mode 100644 index 0000000..21a1799 Binary files /dev/null and b/mod/anims/kka3_unc_7.rtm differ diff --git a/mod/anims/kka3_unc_8.rtm b/mod/anims/kka3_unc_8.rtm new file mode 100644 index 0000000..d62b140 Binary files /dev/null and b/mod/anims/kka3_unc_8.rtm differ diff --git a/mod/cfgFunctions.hpp b/mod/cfgFunctions.hpp index 5caf0ba..30c92da 100644 --- a/mod/cfgFunctions.hpp +++ b/mod/cfgFunctions.hpp @@ -1,9 +1,13 @@ -class cfgFunctions { - class diwako_ragdoll { - tag="diwako_ragdoll"; - class functions { - file = "diwako_ragdoll\functions\diwako\ragdoll"; - class initRagdoll{}; - }; - }; +class cfgFunctions +{ + class diwako_ragdoll + { + tag="diwako_ragdoll"; + class functions + { + file = "diwako_ragdoll\functions\diwako\ragdoll"; + class initRagdoll{}; + class animChangedEH{}; + }; + }; }; \ No newline at end of file diff --git a/mod/cfgMovesMaleSdr.hpp b/mod/cfgMovesMaleSdr.hpp new file mode 100644 index 0000000..3e09cad --- /dev/null +++ b/mod/cfgMovesMaleSdr.hpp @@ -0,0 +1,55 @@ +class CfgMovesMaleSdr +{ + class States + { + class Unconscious; + class kka3_unc_1: Unconscious + { + file = "diwako_ragdoll\anims\kka3_unc_1.rtm"; + collisionShape = "A3\anims_f\Data\Geom\Sdr\geom_empty.p3d"; + actions = "ReviveWoundedDefaultActions"; + looped = 1; + useIdles = 1; + interpolationRestart = 0; + interpolationSpeed = 60; + leaning = "empty"; + aiming = "empty"; + aimingBody = "empty"; + head = "headNo"; + forceAim = 1; + variantAfter[] = {17,17,17}; + variantsPlayer[] = {}; + variantsAI[] = {}; + InterpolateTo[] = {}; + ConnectTo[] = {}; + }; + class kka3_unc_2: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_2.rtm"; + }; + class kka3_unc_3: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_3.rtm"; + }; + class kka3_unc_4: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_4.rtm"; + }; + class kka3_unc_5: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_5.rtm"; + }; + class kka3_unc_6: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_6.rtm"; + }; + class kka3_unc_7: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_7.rtm"; + }; + class kka3_unc_8: kka3_unc_1 + { + file = "diwako_ragdoll\anims\kka3_unc_8.rtm"; + }; + }; +}; \ No newline at end of file diff --git a/mod/config.cpp b/mod/config.cpp index 6d9e216..93f2943 100644 --- a/mod/config.cpp +++ b/mod/config.cpp @@ -1,5 +1,5 @@ #define REQUIRED_VERSION 1.82 -#define VERSION "1.0" +#define VERSION "1.1" class CfgPatches { class diwako_ragdoll { @@ -15,14 +15,15 @@ class CfgPatches { authorUrl = "https://github.com/diwako/a3AceRagdoll"; version = VERSION; versionStr = VERSION; - license = "https://www.bohemia.net/community/licenses/arma-public-license-share-alike"; + license = "https://www.bohemia.net/community/licenses/arma-public-license-share-alike"; }; }; class Extended_PreInit_EventHandlers { - class diwako_ragdoll { - init = "call compile preprocessFileLineNumbers 'diwako_ragdoll\functions\diwako\ragdoll\cba_settings.sqf'"; - }; + class diwako_ragdoll { + init = "call compile preprocessFileLineNumbers 'diwako_ragdoll\functions\diwako\ragdoll\cba_settings.sqf'"; + }; }; -#include "cfgFunctions.hpp" \ No newline at end of file +#include "cfgFunctions.hpp" +#include "cfgMovesMaleSdr.hpp" \ No newline at end of file diff --git a/mod/functions/diwako/ragdoll/cba_settings.sqf b/mod/functions/diwako/ragdoll/cba_settings.sqf index a0033ea..f321df2 100644 --- a/mod/functions/diwako/ragdoll/cba_settings.sqf +++ b/mod/functions/diwako/ragdoll/cba_settings.sqf @@ -8,10 +8,10 @@ false, // data for this setting true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer { - params ["_value"]; - if (_value isEqualTo true) then { - [] call diwako_ragdoll_fnc_initRagdoll; - }; + params ["_value"]; + if ((_value isEqualTo true) && !diwako_ragdoll_server_only) then { + [] call diwako_ragdoll_fnc_initRagdoll; + }; } // function that will be executed once on mission start and every time the setting is changed. ] call CBA_Settings_fnc_init; @@ -23,4 +23,27 @@ false, // data for this setting true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer {} // function that will be executed once on mission start and every time the setting is changed. +] call CBA_Settings_fnc_init; + +[ + "diwako_ragdoll_server_only", // Internal setting name, should always contain a tag! This will be the global variable which takes the value of the setting. + "CHECKBOX", // setting type + ["Server only mode", "Sets the mod only to be required to run on server. Only vanilla Arma3 animations wil be used! This mode is only useful for the mod version, leave it disabled for script version!"], // Pretty name of the category where the setting can be found. Can be stringtable entry. + SETTINGS, // Pretty name shown inside the ingame settings menu. Can be stringtable entry. + false, // data for this setting + true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer + { + params ["_value"]; + if ((_value isEqualTo true) && diwako_ragdoll_ragdolling && isServer) then { + publicVariable "diwako_ragdoll_fnc_initRagdoll"; + publicVariable "diwako_ragdoll_fnc_animChangedEH"; + publicVariable "diwako_ragdoll_server_only"; + publicVariable "diwako_ragdoll_ragdolling"; + publicVariable "diwako_ragdoll_ai"; + [0,{ + waitUntil { !(isNil "diwako_ragdoll_fnc_initRagdoll") && !(isNil "diwako_ragdoll_fnc_animChangedEH") && !(isNil "diwako_ragdoll_server_only") && !(isNil "diwako_ragdoll_ragdolling") && !(isNil "diwako_ragdoll_ai") }; + [] call diwako_ragdoll_fnc_initRagdoll; + }] remoteExec ["spawn",0,true]; + }; + } // function that will be executed once on mission start and every time the setting is changed. ] call CBA_Settings_fnc_init; \ No newline at end of file diff --git a/mod/functions/diwako/ragdoll/fn_animChangedEH.sqf b/mod/functions/diwako/ragdoll/fn_animChangedEH.sqf new file mode 100644 index 0000000..10aa7cc --- /dev/null +++ b/mod/functions/diwako/ragdoll/fn_animChangedEH.sqf @@ -0,0 +1,119 @@ +/* + Author: diwako + + Description: + Code for AnimChanged eventhandler + + Parameter(s): + _unit - Ragdolled unit + _anim - Currentl changed animation + + Examples: + (begin) + [_unit,_anim] call diwako_ragdoll_fnc_animChangedEH; + (end) + + Returns: + none +*/ +params ["_unit","_anim"]; +if(!(_unit getVariable ["ACE_isUnconscious",false])) exitWith {}; // do not run if unit is conscious +if(!(alive _unit) && // do not run if unit is dead + {!(isNull objectParent _unit)}) exitWith {}; // do not run if unit in any vehicle + +_anim = toLower(_anim); + +if((_anim find "unconsciousrevive") != -1 || // catch ragdoll recovery animations + {_anim == "unconsciousoutprone" || // catch another ragdoll recovery animation + {(_anim find "amov") == 0 }} ) then { // catch any movement or stance type of animation (player specific clause) + _anim = "unconscious"; + + // figure out which position state is need + private _vRightShoulder = _unit selectionPosition "rightshoulder"; + private _vLeftShoulder = _unit selectionPosition "leftshoulder"; + private _heightDif = _vRightShoulder#2 - _vLeftShoulder#2; + + // array of array for each animation + private _animHolder = []; + + if(isNil "diwako_ragdoll_animHolder") then { + diwako_ragdoll_animHolder = []; + if(!diwako_ragdoll_server_only && {isClass(configFile >> "CfgPatches" >> "diwako_ragdoll")}) then { + // mod version found + diwako_ragdoll_animHolder pushBack ["kka3_unc_2"]; // 0 on their back + diwako_ragdoll_animHolder pushBack ["kka3_unc_1", "kka3_unc_3", "kka3_unc_4","unconscious","KIA_passenger_boat_holdleft"]; // 1 on their belly + diwako_ragdoll_animHolder pushBack ["kka3_unc_7","kka3_unc_8"]; // 2 on their right shoulder + diwako_ragdoll_animHolder pushBack ["kka3_unc_5","kka3_unc_6","KIA_driver_boat01"]; // 3 on their left shoulder + } else { + // script version or server only mode + diwako_ragdoll_animHolder pushBack ["unconscious"]; // 0 on their back + diwako_ragdoll_animHolder pushBack ["unconscious","KIA_passenger_boat_holdleft"]; // 1 on their belly + diwako_ragdoll_animHolder pushBack ["unconscious"]; // 2 on their right shoulder + diwako_ragdoll_animHolder pushBack ["unconscious","KIA_driver_boat01"]; // 3 on their left shoulder + }; + }; + + if( _heightDif > 0.2 || _heightDif < -0.2) then { + // unit on side + // first one is right shoulder, second one is on left shoulder + _anim = selectRandom ([ diwako_ragdoll_animHolder#2 , diwako_ragdoll_animHolder#3 ] select (_heightDif < -0.2)); + } else { + if(_vRightShoulder#0 > _vLeftShoulder#0) then { + // unit on their belly + _anim = selectRandom (diwako_ragdoll_animHolder#1); + } else { + // unit on their back + _anim = selectRandom (diwako_ragdoll_animHolder#0); + }; + }; + + _unit setUnconscious false; + // play animation + [ + { + params ["_unit","_anim"]; + if(_unit getVariable ["ACE_isUnconscious",false]) then { + // [_unit, _anim, 2, true] call ace_common_fnc_doAnimation; + if(_unit == ace_player) then { + ["ace_common_switchMove", [_unit, _anim]] call CBA_fnc_globalEvent; + } else { + _unit switchMove _anim; + }; + }; + }, // code + [_unit,_anim], // params + 0.2 // delay + ] call CBA_fnc_waitAndExecute; + + // combat network sync issues + if(isMultiplayer) then { + [ + { + params ["_unit","_anim"]; + if((_unit getVariable ["ACE_isUnconscious",false]) && // unit still unconscious + {(isNull objectParent _unit) && // unit not in a car + {!([_unit] call ace_medical_fnc_isBeingCarried) && // not being carried + {!([_unit] call ace_medical_fnc_isBeingDragged)}}} // not being dragged + ) then { + // reapply unconscious animation just in case + // [_unit, _anim, 2, true] call ace_common_fnc_doAnimation; + if(_unit == ace_player) then { + ["ace_common_switchMove", [_unit, _anim]] call CBA_fnc_globalEvent; + } else { + _unit switchMove _anim; + }; + }; + if(!(_unit getVariable ["ACE_isUnconscious",false])) then { + // unit is not unconscious anymore + _unit setUnconscious false; + // free unit of unconscious animation if it is still trapped in it + if(animationState _unit == _anim) then { + _unit switchMove ""; + }; + }; + }, // code + [_unit,_anim], // params + 6.25 // delay + ] call CBA_fnc_waitAndExecute; + }; +}; \ No newline at end of file diff --git a/mod/functions/diwako/ragdoll/fn_initRagdoll.sqf b/mod/functions/diwako/ragdoll/fn_initRagdoll.sqf index b8ac4ba..0e928b6 100644 --- a/mod/functions/diwako/ragdoll/fn_initRagdoll.sqf +++ b/mod/functions/diwako/ragdoll/fn_initRagdoll.sqf @@ -22,44 +22,21 @@ diwako_ragdoll_ragdollRunning = true; ["ace_unconscious", { params [["_unit", objNull],["_state", false]]; - if(!diwako_ragdoll_ragdolling) exitWith {}; // ragdolling if it active - if( (_unit != player && {!diwako_ragdoll_ai}) || (!local _unit)) exitWith {}; // only ragdoll players and only ragdolling if it active - if(_state && {vehicle _unit == _unit && {!([_unit] call ace_medical_fnc_isBeingCarried) && {!([_unit] call ace_medical_fnc_isBeingDragged)}}}) then { - // ragdoll player + // if(!local _unit || {!diwako_ragdoll_ragdolling}) exitWith {}; // ragdolling if it's active and unit local + if(!diwako_ragdoll_ragdolling) exitWith {}; // ragdolling if it's active + if((!(isPlayer _unit) && {!diwako_ragdoll_ai})) exitWith {}; // only ragdoll players and only ragdolling AI if that option is set active + if(_state && {(isNull objectParent _unit) && {!([_unit] call ace_medical_fnc_isBeingCarried) && {!([_unit] call ace_medical_fnc_isBeingDragged)}}}) then { + // ragdoll unit _unit setUnconscious true; }; if(!_state) then { - // player woke up before ragdolling was finished + // unit woke up before ragdolling was finished _unit setUnconscious false; }; }] call CBA_fnc_addEventHandler; ["CAManBase", "AnimChanged", { - params ["_unit","_anim"]; - if(!diwako_ragdoll_ragdolling) exitWith {}; // disable ragdolling mid mission - if( (_unit != player && {!diwako_ragdoll_ai}) || !(local _unit)) exitWith {}; // only run on players if ai setting is disabled - if(_anim == "unconsciousrevivedefault" && {alive _unit && {_unit getVariable ["ACE_isUnconscious",false] && {vehicle _unit == _unit}}}) then { - // unit stopped ragdolling, apply ace_death animation to unit - _unit setUnconscious false; - [_unit, [_unit] call ace_common_fnc_getDeathAnim, 2, true] call ace_common_fnc_doAnimation; - if(isMultiplayer) then { - // combat sync issues - [ - { - params ["_unit"]; - if(!(_unit getVariable ["ACE_isUnconscious",false])) then { - // unit is not unconscious anymore - _unit setUnconscious false; - } else { - // unit is still unconscious, reapply death animation just in case and sync it again to all clients - [_unit, [_unit] call ace_common_fnc_getDeathAnim, 2, true] call ace_common_fnc_doAnimation; - }; - }, // code - [_unit], // params - 5 // delay - ] call CBA_fnc_waitAndExecute; - }; - }; + _this call diwako_ragdoll_fnc_animChangedEH; }] call CBA_fnc_addClassEventHandler; player createDiaryRecord ["CBA_docs", ["Ragdolling", "Ragdolling has been activated in this mission! Better check those bodies!"]]; \ No newline at end of file