Skip to content

Commit

Permalink
Add revive modules for Farooq's Revive (#386)
Browse files Browse the repository at this point in the history
* Support Farooq's Revive

The ACE Heal module supports reviving the selected player when Farooq's Revive
script is active. It still takes seconds for the player to be up because of
Farooq's Revive script.

* Support Arma 3 revive system in Heal module

* Add Immersive Heal

The new Immersive Heal module gives a more realistic feeling compared to the
ACE Heal module by sending an AI to revive or heal a player. It has two modes
of operation:

* When placed on a player the nearest AI of the same side will be sent to
  revive the player.

* When placed on an AI the nearest player (regardless of side) will be revived.
  Also works on vehicles which will drive up to the player before the driver
  exits and revives the player.

* Fix formatting

* Fix healing multiple units with Arma3 revive system

* Simplify multi-selection checks

* Use lazy evaluation

* Fix formatting

* Fix variable name

* Fix misplaces tab character

* Localize

* Fix spelling

* revie -> revive
* unconsious -> unconscious
* no dot at end of Zeus messages

* Update header and footer includes

* Remove punctuation at end of more Zeus bar messages

* Use remoteExecCall instead of remoteExec

* Rename _revive to _fnc_reviveUnit

This states more clearly that it's a function to call.

* Localize 'Healed' message

* Localize remaining 'Healed' message

* Lower search range for immersive heal to 300
  • Loading branch information
ServiusHack authored and CreepPork committed May 14, 2019
1 parent 676e895 commit 52d9d54
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 14 deletions.
35 changes: 35 additions & 0 deletions @AresModAchillesExpansion/addons/language_f/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,16 @@
<Chinesesimp>治疗</Chinesesimp>
<Chinese>治療</Chinese>
</Key>
<Key ID="STR_AMAE_HEALED">
<Original>Healed</Original>
<English>Healed</English>
<German>Geheilt</German>
</Key>
<Key ID="STR_AMAE_IMMERSIVE_HEAL">
<Original>Immersive Heal</Original>
<English>Immersive Heal</English>
<German>Immersiv heilen</German>
</Key>
<Key ID="STR_AMAE_AMBIENT_ANIMATION">
<Original>Ambient Animation</Original>
<English>Ambient Animation</English>
Expand Down Expand Up @@ -5544,6 +5554,31 @@
<Chinesesimp>碾伤</Chinesesimp>
<Chinese>碾傷</Chinese>
</Key>
<Key ID="STR_AMAE_REVIVE_FEW_SECONDS">
<Original>Player will be revived in a few seconds</Original>
<English>Player will be revived in a few seconds</English>
<German>Der Spieler wird in einigen Sekunden wiederbelebt</German>
</Key>
<Key ID="STR_AMAE_REVIVE_PLAYER">
<Original>Player '%1' will be revived</Original>
<English>Player '%1' will be revived</English>
<German>Der Spieler '%1' wird wiederbelebt</German>
</Key>
<Key ID="STR_AMAE_NO_PLAYER_UNCONSCIOUS">
<Original>No player is unconscious</Original>
<English>No player is unconscious</English>
<German>Kein Spieler ist bewusstlos</German>
</Key>
<Key ID="STR_AMAE_REVIVE_INVALID_SELECTION">
<Original>Neither an unconscious player nor an AI was selected</Original>
<English>Neither an unconscious player nor an AI was selected</English>
<German>Weder ein Spieler noch eine AI wurde ausgewählt</German>
</Key>
<Key ID="STR_AMAE_REVIVE_NO_NEAR_UNITS">
<Original>No units to perform revive nearby</Original>
<English>No units to perform revive nearby</English>
<German>In der Nähe befinden sich keine Einheiten, die wiederbeleben könnten</German>
</Key>
</Container>
<Container name="Building damage dialog strings">
<Key ID="STR_AMAE_LIGHT_DAMAGE">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ class Achilles_ACE_Function_Base

class ModuleACEInjury {};
class ModuleACEHeal {};
class ModuleACEImmersiveHeal {};
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,12 @@ class Achilles_ACE_Heal_Module : Achilles_ACE_Module_Base
_generalMacro = "Achilles_ACE_Heal_Module";
displayName = "$STR_AMAE_HEAL";
function = "Achilles_fnc_ModuleACEHeal";
};

class Achilles_ACE_ImmersiveHeal_Module : Achilles_ACE_Module_Base
{
scopeCurator = 1;
_generalMacro = "Achilles_ACE_ImmersiveHeal_Module";
displayName = "$STR_AMAE_IMMERSIVE_HEAL";
function = "Achilles_fnc_ModuleACEImmersiveHeal";
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,101 @@

#include "\achilles\modules_f_ares\module_header.inc.sqf"

#include "\a3\functions_f_mp_mark\revive\defines.inc"

private ["_injury","_selected_units"];

private _unit = [_logic, false] call Ares_fnc_GetUnitUnderCursor;

private _mode = ["single", "multiple"] select (isNull _unit);

private _options = [localize "STR_AMAE_RANDOM",localize "STR_AMAE_NONE_INJURY",localize "STR_AMAE_LIGHT_INJURY", localize "STR_AMAE_SEVERE_INJURY"];
private _isSingleSelection = !isNull _unit;

if (isClass (configfile >> "CfgPatches" >> "ace_medical")) then
// ACE Medical System
if (isClass (configfile >> "CfgPatches" >> "ace_medical")) exitWith
{
if (_mode == "single") then
if (_isSingleSelection) then
{
["Healed"] call Ares_fnc_ShowZeusMessage;
[localize "STR_AMAE_HEALED"] call Ares_fnc_ShowZeusMessage;
_selected_units = [_unit];
} else
{
_selected_units = ["units"] call Achilles_fnc_SelectUnits;
_selected_units = [localize "STR_AMAE_UNITS"] call Achilles_fnc_SelectUnits;
};

// handle the case the selection was cancled
if (isNil "_selected_units") exitWith {};
if (_selected_units isEqualTo []) exitWith {};

{
if (local _x) then {[_x, _x] call ace_medical_fnc_treatmentAdvanced_fullHealLocal} else {[_x, _x] remoteExec ["ace_medical_fnc_treatmentAdvanced_fullHealLocal", _x]};
if (local _x) then
{
[_x, _x] call ace_medical_fnc_treatmentAdvanced_fullHealLocal
} else
{
[_x, _x] remoteExecCall ["ace_medical_fnc_treatmentAdvanced_fullHealLocal", _x]
};
} forEach _selected_units;
} else
};


// Farooq's Revive System
if (!isNil "FAR_ReviveMode") exitWith
{
if (_mode == "single") then
if (_isSingleSelection) then
{
["Healed"] call Ares_fnc_ShowZeusMessage;
_selected_units = [_unit];
} else
{
_selected_units = ["units"] call Achilles_fnc_SelectUnits;
_selected_units = [localize "STR_AMAE_UNITS"] call Achilles_fnc_SelectUnits;
};

// handle the case the selection was cancled
if (isNil "_selected_units") exitWith {};
if (_selected_units isEqualTo []) exitWith {};

// Vanilla Injury System
// check if any unit is unconscious
if ({ _x getVariable ["FAR_isUnconscious", 0] == 1 } count _selected_units > 0) then
{
_x setDamage 0;
[localize "STR_AMAE_REVIVE_FEW_SECONDS"] call Ares_fnc_ShowZeusMessage;
} else
{
[localize "STR_AMAE_HEALED"] call Ares_fnc_ShowZeusMessage;
};

{
if (_x getVariable ["FAR_isUnconscious", 0] == 1) then
{
_x setVariable ["FAR_isUnconscious", 0, true];
_x setVariable ["FAR_isDragged", 0, true];
} else
{
_x setDamage 0;
};
} forEach _selected_units;
};

// Vanilla Injury System

if (_isSingleSelection) then
{
[localize "STR_AMAE_HEALED"] call Ares_fnc_ShowZeusMessage;
_selected_units = [_unit];
} else
{
_selected_units = [localize "STR_AMAE_UNITS"] call Achilles_fnc_SelectUnits;
};

// handle the case the selection was cancled
if (isNil "_selected_units") exitWith {};
if (_selected_units isEqualTo []) exitWith {};

{
if (REVIVE_ENABLED(_x) && {lifeState _x == "INCAPACITATED"} && {IS_DISABLED(_x)}) then
{
SET_STATE(_x, STATE_REVIVED);
} else
{
_x setDamage 0;
};
} forEach _selected_units;

#include "\achilles\modules_f_ares\module_footer.inc.sqf"
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AUTHOR: ServiusHack
// DESCRIPTION: Command an AI unit to revive a player using farooq's Revive.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#include "\achilles\modules_f_ares\module_header.inc.sqf"

#include "\a3\functions_f_mp_mark\revive\defines.inc"

// Command an AI (second parameter) to revive a player (first parameter).
private _fnc_reviveUnit = {
params ["_player", "_ai"];

// Let Zeus know what will happen
[format [localize "STR_AMAE_REVIVE_PLAYER", name _player]] call Ares_fnc_ShowZeusMessage;

private _vehicle = vehicle _ai;

if (_vehicle isEqualTo _ai) then
{
// move unit to perform the revive
_ai doMove (getPos _player);
} else
{
// make vehicle drive to the player
driver _vehicle doMove (getPos _player);

// wait for vehicle to be close enough
// Make sure we're close to get off when the vehicle stands still.
waitUntil{ (speed _vehicle) < 0.1 && (_ai distance _player) < 20 };

// make sure the vehicle stops
doStop driver _vehicle;

// make the unit leave the vehicle
_ai action ["GetOut", _vehicle];
_ai leaveVehicle _vehicle;

// finally move unit to perform the revive
_ai doMove (getPos _player);
};

waitUntil{ (_ai distance _player) < 2 };

// make it look nice
_ai lookAt _player;
sleep 2;
_ai playMove "AinvPknlMstpSnonWnonDnon_medic1";
_ai playMove "AinvPknlMstpSnonWnonDnon_medicEnd";
_ai playMove "AinvPknlMstpSnonWnonDnon_AmovPercMstpSnonWnonDnon";
_ai playMove "AmovPknlMstpSnonWnonDnon_AmovPercMstpSnonWnonDnon";

// do the actual revive
if (isClass (configfile >> "CfgPatches" >> "ace_medical")) then
{
if (local _player) then
{
[_player, _player] call ace_medical_fnc_treatmentAdvanced_fullHealLocal
} else
{
[_player, _player] remoteExecCall ["ace_medical_fnc_treatmentAdvanced_fullHealLocal", _player]
};
};

if (!isNil "FAR_ReviveMode") then
{
_player setVariable ["FAR_isUnconscious", 0, true];
_player setVariable ["FAR_isDragged", 0, true];
};

if (REVIVE_ENABLED(_player) && lifeState _player == "INCAPACITATED" && IS_DISABLED(_player)) then
{
SET_STATE(_player, STATE_REVIVED);
} else
{
_player setDamage 0;
};

// stop always looking at the revived player
_ai lookAt objNull;
};

// Gets the object that the module was placed upon
private _object = [_logic, false] call Ares_fnc_GetUnitUnderCursor;

// Displays error message if no object or unit has been selected.
if (isNull _object) exitWith
{
[localize "STR_AMAE_NO_UNIT_SELECTED"] call Achilles_fnc_ShowZeusErrorMessage;
};

if (isPlayer _object || isPlayer driver _object) exitWith
{
// find nearest units
private _nearestUnits = nearestObjects [_object, ["man", "landvehicle"], 300];

// find closest AI unit of same side
private _sameSideUnitIndex = _nearestUnits findIf { side group _object isEqualTo side driver _x && !isPlayer driver _x };

if (_sameSideUnitIndex == -1) exitWith
{
[localize "STR_AMAE_REVIVE_NO_NEAR_UNITS"] call Achilles_fnc_ShowZeusErrorMessage;
};

// spawn off movement and revive action
[driver _object, driver (_nearestUnits select _sameSideUnitIndex)] spawn _fnc_reviveUnit;
};

// Make sure we use a unit. Vehicles support kicks in later.
_object = driver _object;

if (!isNull _object) exitWith
{
// find all unconsious players
private _unconsiousPlayers = allPlayers select { _x getVariable ["FAR_isUnconscious", 0] == 1 };

// find nearest player to revive
private _sortedPlayers = [_unconsiousPlayers, [], {_x distance _object}, "ASCEND"] call BIS_fnc_sortBy;
private _nearestPlayer = _sortedPlayers select 0;

if (isNil "_nearestPlayer") exitWith { [localize "STR_AMAE_NO_PLAYER_UNCONSCIOUS"] call Achilles_fnc_ShowZeusErrorMessage; };

// spawn off movement and revive action
[_nearestPlayer, _object] spawn _fnc_reviveUnit;
};

[localize "STR_AMAE_REVIVE_INVALID_SELECTION"] call Achilles_fnc_ShowZeusErrorMessage;

#include "\achilles\modules_f_ares\module_footer.inc.sqf"
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CfgPatches
{
"Achilles_ACE_Injury_Module",
"Achilles_ACE_Heal_Module",
"Achilles_ACE_ImmersiveHeal_Module",
"Achilles_Animation_Module",
"Achilles_Chatter_Module",
"Achilles_Sit_On_Chair_Module",
Expand Down

0 comments on commit 52d9d54

Please sign in to comment.