Skip to content

Commit

Permalink
Hit Reactions - Add weapon dropping on arm hit (acemod#9539)
Browse files Browse the repository at this point in the history
* Create fnc_checkWeaponDrop.sqf

* Update fnc_checkWeaponDrop.sqf

* Create XEH_postInit.sqf

* Update XEH_postInit.sqf

* Update XEH_postInit.sqf

* Update fnc_checkWeaponDrop.sqf

* fix spelling issue

* Update initSettings.sqf

Add weaponDropEnabled setting

* Update stringtable.xml

* Update fnc_checkWeaponDrop.sqf

* Update initSettings.sqf

Forgot a bracket

* Add weapon drop chance setting

* Update XEH_postInit.sqf

* Update CfgEventHandlers.hpp

actually make it run postinit

* Update XEH_PREP.hpp

* Update stringtable.xml

* Update initSettings.sqf

No need, set chance to 0

* Update XEH_postInit.sqf

already comparing against chance, can just set to 0

* Update initSettings.sqf

* Update stringtable.xml

* Update XEH_postInit.sqf

* add arm hit chance

fix weapon thing too

* Update stringtable.xml

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: Grim <[email protected]>

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: Grim <[email protected]>

* appearance stuff

* Update addons/hitreactions/initSettings.sqf

Co-authored-by: Grim <[email protected]>

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: Jouni Järvinen <[email protected]>

* kjw's poor arithmetic

* Update fnc_checkWeaponDrop.sqf

wrong check

* remove systemchat debug

whoops

* Update fnc_checkWeaponDrop.sqf

* Update XEH_postInit.sqf

* Update fnc_checkWeaponDrop.sqf

* Early exit, wait for clear

* Make default setting 0

* Update script_component.hpp

* Update XEH_postInit.sqf

* Update script_component.hpp

* Update XEH_postInit.sqf

* Update XEH_postInit.sqf

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

* Update XEH_postInit.sqf

Unsure if exitWith in postInit is proper? Seems better than nesting all of that in another scope imo

* Update XEH_preInit.sqf

* Update fnc_checkWeaponDrop.sqf

* Update addons/hitreactions/XEH_preInit.sqf

Co-authored-by: Grim <[email protected]>

* Update hitreactions.md

* Update hitreactions.md

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: johnb432 <[email protected]>

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: johnb432 <[email protected]>

* Update addons/hitreactions/initSettings.sqf

* Update XEH_postInit.sqf

* Update addons/hitreactions/XEH_postInit.sqf

Co-authored-by: johnb432 <[email protected]>

* Update addons/hitreactions/XEH_postInit.sqf

Co-authored-by: johnb432 <[email protected]>

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: johnb432 <[email protected]>

* Update addons/hitreactions/functions/fnc_checkWeaponDrop.sqf

Co-authored-by: johnb432 <[email protected]>

* Update XEH_postInit.sqf

* Update XEH_postInit.sqf

* Update fnc_checkWeaponDrop.sqf

* Spacing fixes

* Update addons/hitreactions/XEH_postInit.sqf

Co-authored-by: johnb432 <[email protected]>

* Take _hitEntity into account if exists

* Update fnc_checkWeaponDrop.sqf

_didHitGun will no longer ever be true

* Minor component cleanup

* Removed gun hits, added double hit detection

* Decouple AI and player probabilities

* Tweaks and fixes

* Update XEH_PREP.hpp

* Add missing param

* Fixed bugged state AI are in after using TakeWeapon

* Fixes and cleanup

* Made API clear, moved undroppable to config entry

* Update fnc_checkWeaponDrop.sqf

* Check for Zeus RC and avoid `setUnitLoadout`

* Expand `addWeapon`'s capabilities

* Cleaned up `addWeapon`

* Removed weapon replacement as it's apparently not necessary

* Defined undefined variable

---------

Co-authored-by: Grim <[email protected]>
Co-authored-by: Jouni Järvinen <[email protected]>
Co-authored-by: johnb432 <[email protected]>
  • Loading branch information
4 people authored and blake8090 committed Aug 18, 2024
1 parent aa48274 commit 5593f84
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 4 deletions.
1 change: 0 additions & 1 deletion addons/hitreactions/ACE_Settings.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

class ACE_Settings {
class GVAR(minDamageToTrigger) {
movedToSQF = 1;
Expand Down
7 changes: 6 additions & 1 deletion addons/hitreactions/CfgEventHandlers.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
Expand All @@ -11,6 +10,12 @@ class Extended_PreInit_EventHandlers {
};
};

class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};

class Extended_Hit_EventHandlers {
class CAManBase {
class ADDON {
Expand Down
2 changes: 1 addition & 1 deletion addons/hitreactions/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

PREP(checkWeaponDrop);
PREP(fallDown);
PREP(getRandomAnimation);
86 changes: 86 additions & 0 deletions addons/hitreactions/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include "script_component.hpp"

["ace_firedNonPlayer", {
if (GVAR(weaponDropChanceArmHitPlayer) + GVAR(weaponDropChanceArmHitAI) == 0) exitWith {};

(_this select 6) addEventHandler ["HitPart", {
params ["", "_entity", "", "", "", "", "_selections"];

[_entity, _selections] call FUNC(checkWeaponDrop);
}];
}] call CBA_fnc_addEventHandler;

["ace_firedPlayer", {
if (GVAR(weaponDropChanceArmHitPlayer) + GVAR(weaponDropChanceArmHitAI) == 0) exitWith {};

(_this select 6) addEventHandler ["HitPart", {
params ["", "_entity", "", "", "", "", "_selections"];

[_entity, _selections] call FUNC(checkWeaponDrop);
}];
}] call CBA_fnc_addEventHandler;

[QGVAR(dropWeapon), {
params ["_unit"];

if !(_unit getVariable [QGVAR(canDropWeapon), true]) exitWith {};

// Prevents AI from losing both primary and pistol when being shot with their pistol out
_unit setVariable [QGVAR(canDropWeapon), false];

private _weapon = currentWeapon _unit;
private _thrownWeapon = _unit call EFUNC(common,throwWeapon);

[{
params ["_unit"];

_unit setVariable [QGVAR(canDropWeapon), nil];
}, _unit, 0.5] call CBA_fnc_waitAndExecute;

if (_unit call EFUNC(common,isPlayer)) exitWith {}; // Don't make players pick their own weapons up

// Wait before executing, as otherwise the unit would pick up the weapon immediately
[{
[{
(_this select 0) params ["_unit", "_weapon", "_thrownWeapon", "_timeout"];

// If the unit has been deleted or dead, if the weapon doesn't exist anymore or if it's been too long, stop
if (!alive _unit || {!local _unit} || {isNull _thrownWeapon} || {CBA_missionTime >= _timeout}) exitWith {
(_this select 1) call CBA_fnc_removePerFrameHandler;
};

// Don't pick up weapon when unit is unconscious
if (lifeState _unit == "INCAPACITATED") exitWith {};

// If the unit has no essential weapons, force them to get their weapon, otherwise wait until no enemies are present
if !(
(primaryWeapon _unit == "" && {handgunWeapon _unit == ""}) ||
{(_unit distance (_unit findNearestEnemy _unit)) > missionNamespace getVariable [QGVAR(safePickupDistance), DEFAULT_PICKUP_DISTANCE]}
) exitWith {};

// If the unit is too far away, make them move closer
if (_unit distance _thrownWeapon >= 4) exitWith {
private _pos = getPosATL _thrownWeapon;

_unit setDestination [_pos, "LEADER PLANNED", true];
_unit doMove _pos;
};

(_this select 1) call CBA_fnc_removePerFrameHandler;

_unit action ["TakeWeapon", _thrownWeapon, _weapon];

// Make the unit switch weapons
[{
(_this select 0) hasWeapon (_this select 1)
}, {
params ["_unit", "_weapon"];

if (!alive _unit || {!local _unit} || {primaryWeapon _unit != _weapon}) exitWith {};

// Switch to the primary weapon, if it was picked up
_unit selectWeapon _weapon;
}, [_unit, _weapon], 5] call CBA_fnc_waitUntilAndExecute;
}, 5, _this] call CBA_fnc_addPerFrameHandler;
}, [_unit, _weapon, _thrownWeapon, CBA_missionTime + 300], random [2, 3, 4]] call CBA_fnc_waitAndExecute;
}] call CBA_fnc_addEventHandler;
12 changes: 12 additions & 0 deletions addons/hitreactions/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ PREP_RECOMPILE_END;
#include "initSettings.inc.sqf"

ADDON = true;

GVAR(armSelections) = [
"leftshoulder",
"rightshoulder",
"lefthand",
"leftforearm",
"leftarmroll",
"rightforearm",
"rightarmroll",
"righthand",
"rightarm"
];
33 changes: 33 additions & 0 deletions addons/hitreactions/functions/fnc_checkWeaponDrop.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "..\script_component.hpp"
/*
* Author: KJW
* Checks if an entity should drop their weapon based on projectile hit info.
*
* Arguments:
* 0: Entity that was hit <OBJECT>
* 1: Selection names that were hit <ARRAY>
*
* Return Value:
* None
*
* Example:
* [player, []] call ace_hitreactions_fnc_checkWeaponDrop
*
* Public: No
*/

params ["_entity", "_selections"];

// Make sure entity is a unit
if !(_entity isKindOf "CAManBase") exitWith {};

// Don't throw weapon if unit is unconscious or dead
if !(lifeState _entity in ["HEALTHY", "INJURED"]) exitWith {};

if (random 1 >= ([GVAR(weaponDropChanceArmHitAI), GVAR(weaponDropChanceArmHitPlayer)] select (_entity call EFUNC(common,isPlayer)))) exitWith {};

if (_selections findAny GVAR(armSelections) == -1) exitWith {};

if (getNumber ((currentWeapon _entity) call CBA_fnc_getItemConfig >> QGVAR(undroppable)) == 1) exitWith {};

[QGVAR(dropWeapon), _entity, _entity] call CBA_fnc_targetEvent;
21 changes: 20 additions & 1 deletion addons/hitreactions/initSettings.inc.sqf
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
private _category = [LELSTRING(common,categoryUncategorized), QUOTE(COMPONENT_BEAUTIFIED)];

[
QGVAR(minDamageToTrigger), "SLIDER",
QGVAR(minDamageToTrigger),
"SLIDER",
LSTRING(minDamageToTrigger_displayName),
_category,
[-1, 1, 0.1, 1],
1
] call CBA_fnc_addSetting;

[
QGVAR(weaponDropChanceArmHitPlayer),
"SLIDER",
LSTRING(weaponDropChanceArmHitPlayer_displayName),
_category,
[0, 1, 0, 2, true],
1
] call CBA_fnc_addSetting;

[
QGVAR(weaponDropChanceArmHitAI),
"SLIDER",
LSTRING(weaponDropChanceArmHitAI_displayName),
_category,
[0, 1, 0, 2, true],
1
] call CBA_fnc_addSetting;
2 changes: 2 additions & 0 deletions addons/hitreactions/script_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
#endif

#include "\z\ace\addons\main\script_macros.hpp"

#define DEFAULT_PICKUP_DISTANCE 8
6 changes: 6 additions & 0 deletions addons/hitreactions/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,11 @@
<Turkish>Düşmeyi tetikleyen min hasar</Turkish>
<Spanish>Daño mínimo para provocar la caída</Spanish>
</Key>
<Key ID="STR_ACE_HitReactions_weaponDropChanceArmHitPlayer_displayName">
<English>Player Weapon Drop Chance (Arm Hit)</English>
</Key>
<Key ID="STR_ACE_HitReactions_weaponDropChanceArmHitAI_displayName">
<English>AI Weapon Drop Chance (Arm Hit)</English>
</Key>
</Package>
</Project>
3 changes: 3 additions & 0 deletions docs/wiki/feature/hitreactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ version:
### 1.1 Falling under fire
If a unit is shot while running it falls to the ground in a prone position, the area where the shot lands does not matters.
Note that the shot needs to inflict a certain amount of damage to make the unit fall, a small cut won't make the unit stumble.

### 1.2 Weapon dropping
If a unit's arm is shot it will cause the gun to be dropped based on the chance set. The default is 0.
32 changes: 32 additions & 0 deletions docs/wiki/framework/hitreactions-framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
layout: wiki
title: Hit Reactions Framework
description: Explains how to set-up weapons with ACE3 hit reactions system.
group: framework
order: 5
parent: wiki
mod: ace
version:
major: 3
minor: 18
patch: 0
---

## 1. Config Values

```cpp
class CfgWeapons {
class MyWeapon {
ace_hitreactions_undroppable = 1; // Prevents weapon from being dropped
};
};
```
## 2. Mission Variables
### 2.1 Safe pickup distance for AI
Allows 3rd party mods to set the distance between AI and the nearest hostile that is considered safe to go pickup a dropped weapon.
```sqf
ace_hitreactions_safePickupDistance = 10; // default is 8
```

0 comments on commit 5593f84

Please sign in to comment.