Interaction - Add actions based on animations (#6144)

* Add actions based on animations

* Add setting

* Add ability to set items for users

* Add actions for 1.82 changes

Add actions for backpacks, canisters, entrench tool.
Move items and backpack to WeaponHolder.

* Add RHS 0.4.6 ZIL spare

* Update to new standards

* Handle RHS BTR retread system

* Make init faster: move condition to configClasses

* Fix CUP fake anims

* Refactor

* Rework

* Rename init function

* Decrease number of classes to init

* Fix merge mistake

* Apply suggestions from code review

* Updated code for current mod structure

* Multiple fixes & tweaks

- Made anim setting require a mission restart
- Handle more types of items that can be spawned
- Prioritise adding items to inventory and only drop on ground if no inventory space
- Add more position checks to make certain no valid position are present before stopping
- If 1 item was spawned in, it's considered as success
- Disable RHS' wheel replacement only if ace_repair is loaded

* Update CfgVehicles.hpp

* cache config lookup at preStart

* Fix error

* Add text config entry for progress bar title

* Restructure interactions, improved some locations & added interaction to some missing vehicles

* Reverted preInit change

---------

Co-authored-by: jonpas <jonpas33@gmail.com>
Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
This commit is contained in:
Dystopian 2024-08-11 07:29:50 +03:00 committed by GitHub
parent e36363e8cc
commit 96f81f1c9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 939 additions and 5 deletions

View File

@ -6,4 +6,12 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
// Disable RHS' wheel replacement mechanic
if (["ace_repair"] call EFUNC(common,isModLoaded)) then {
RHS_Retread_Enabled = false;
rhs_btr70_EnableRetread = false;
rhs_TypeTirePressure = 1;
RHS_BTR_Effects_Init = true;
};
ADDON = true;

View File

@ -0,0 +1,123 @@
class CfgVehicles {
class Wheeled_APC_F;
class rhs_btr_base: Wheeled_APC_F {
class EGVAR(interaction,anims) {
class wheel_1_unhide {
positions[] = {{-0.8, -1.7, 0}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
class wheel_2_unhide {
positions[] = {{0.35, -2.9, -0.1}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_btr70_vmf: rhs_btr_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class wheel_1_unhide: wheel_1_unhide {
positions[] = {{-1.2, -2.6, 0.2}};
};
class wheel_2_unhide: wheel_2_unhide {
positions[] = {{-0.3, -3.8, 0}};
};
};
};
class rhs_btr70_msv: rhs_btr70_vmf {};
class rhs_btr80_msv: rhs_btr70_msv {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class wheel_1_unhide: wheel_1_unhide {
positions[] = {{-1, -2.5, 0.6}};
};
class wheel_2_unhide: wheel_2_unhide {
enabled = 0;
};
};
};
class Truck_F;
class rhs_truck: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class RHS_Ural_BaseTurret: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_zil131_base: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_kraz255_base;
class rhs_kraz255b1_base: rhs_kraz255_base {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class O_Truck_02_covered_F;
class rhs_kamaz5350: O_Truck_02_covered_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class MRAP_02_base_F;
class rhs_tigr_base: MRAP_02_base_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class Offroad_01_base_f;
class RHS_UAZ_Base: Offroad_01_base_f {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
};

View File

@ -0,0 +1,21 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhs_main_loadorder",
"ace_repair"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"Dystopian", "johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,3 @@
#define SUBCOMPONENT repair
#define SUBCOMPONENT_BEAUTIFIED Repair
#include "..\script_component.hpp"

View File

@ -43,8 +43,7 @@ class CfgVehicles {
EGVAR(refuel,fuelCapacity) = 302;
};
class Truck_F;
class Truck_01_base_F: Truck_F {};
class Truck_01_base_F;
class rhsusf_fmtv_base: Truck_01_base_F {
EGVAR(refuel,fuelCapacity) = 219;
};
@ -55,8 +54,7 @@ class CfgVehicles {
EGVAR(refuel,fuelCargo) = 900; // 45 jerrycans
};
class rhsusf_HEMTT_A4_base: Truck_01_base_F {};
class rhsusf_M977A4_usarmy_wd: rhsusf_HEMTT_A4_base {};
class rhsusf_M977A4_usarmy_wd;
class rhsusf_M977A4_AMMO_usarmy_wd: rhsusf_M977A4_usarmy_wd {
EGVAR(rearm,defaultSupply) = 1200;
};

View File

@ -0,0 +1,52 @@
class CfgVehicles {
class rhsusf_stryker_base;
class rhsusf_stryker_m1126_base: rhsusf_stryker_base {
class EGVAR(interaction,anims) {
class Hide_FCans {
positions[] = {{-0.7, -3, -0.4}};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = ECSTRING(refuel,TakeFuelCanister);
text = ECSTRING(refuel,TakeFuelCanisterAction);
};
};
};
class rhsusf_stryker_m1127_base: rhsusf_stryker_m1126_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-0.5, -3, -0.4}};
};
};
};
class rhsusf_stryker_m1126_m2_base: rhsusf_stryker_m1126_base {};
class rhsusf_stryker_m1132_m2_base: rhsusf_stryker_m1126_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-1, -4, -0.4}};
};
};
};
class rhsusf_stryker_m1134_base: rhsusf_stryker_m1132_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-0.7, -3, -0.7}};
};
};
};
class rhsusf_m1a2tank_base;
class rhsusf_m1a2sep2_base: rhsusf_m1a2tank_base {
class EGVAR(interaction,anims) {
class fuelcans_hide {
// Rotate interactions with turret rotation
positions[] = {
"[0.23, -0.6, 0] vectorAdd ([[1.1, -3.6, 0.6], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0.23, -0.6, 0] vectorAdd ([[-1.1, -3.6, 0.6], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"
};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = ECSTRING(refuel,TakeFuelCanister);
text = ECSTRING(refuel,TakeFuelCanisterAction);
};
};
};
};

View File

@ -21,3 +21,4 @@ class CfgPatches {
};
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,126 @@
class CfgVehicles {
class Truck_01_base_F;
class rhsusf_fmtv_base: Truck_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {{1, 1.4, 0}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_M1078A1P2_fmtv_usarmy: rhsusf_fmtv_base {};
class rhsusf_M1078A1P2_B_fmtv_usarmy: rhsusf_M1078A1P2_fmtv_usarmy {};
class rhsusf_M1078A1P2_B_M2_fmtv_usarmy: rhsusf_M1078A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.4, -0.5}};
};
};
};
class rhsusf_M1078A1R_SOV_M2_D_fmtv_socom: rhsusf_M1078A1P2_B_M2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1, -0.5}};
};
};
};
class rhsusf_M1083A1P2_fmtv_usarmy: rhsusf_M1078A1P2_fmtv_usarmy {};
class rhsusf_M1083A1P2_B_fmtv_usarmy: rhsusf_M1083A1P2_fmtv_usarmy {};
class rhsusf_M1083A1P2_B_M2_fmtv_usarmy: rhsusf_M1083A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.4, -0.5}};
};
};
};
class rhsusf_M1084A1P2_fmtv_usarmy: rhsusf_M1083A1P2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.8, 0}};
};
};
};
class rhsusf_M1084A1P2_B_M2_fmtv_usarmy: rhsusf_M1083A1P2_B_M2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.8, -0.5}};
};
};
};
class rhsusf_M1085A1P2_B_Medical_fmtv_usarmy: rhsusf_M1083A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 6.1, 0}};
};
};
};
class rhsusf_HEMTT_A4_base: Truck_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel' vectorAdd [0.6, 0.6, -0.4]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class MRAP_01_base_F;
class rhsusf_m1151_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel' vectorAdd [-0.465, 0, 0]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
// Don't inherit, as it's easier for the trenches compat
class rhsusf_M1165A1_GMV_SAG2_base: rhsusf_m1151_base {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel_gmv' vectorAdd [0, -0.44, 0]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_rg33_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_M1239_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_MATV_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
};

View File

@ -0,0 +1,23 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhsusf_main_loadorder",
"ace_repair"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
addonRootClass = QUOTE(ADDON);
};
};
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,3 @@
#define SUBCOMPONENT repair
#define SUBCOMPONENT_BEAUTIFIED Repair
#include "..\script_component.hpp"

View File

@ -0,0 +1,48 @@
class CfgVehicles {
class rhsusf_stryker_base;
class rhsusf_stryker_m1126_base: rhsusf_stryker_base {
class EGVAR(interaction,anims) {
class Hide_PioKit {
positions[] = {{-1, -2.2, -0.5}};
items[] = {"ACE_EntrenchingTool"};
name = ECSTRING(trenches,EntrenchingToolName);
text = ECSTRING(trenches,EntrenchingToolName);
};
};
};
class rhsusf_stryker_m1127_base: rhsusf_stryker_m1126_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-0.8, -2.2, -0.5}};
};
};
};
class rhsusf_stryker_m1126_m2_base: rhsusf_stryker_m1126_base {};
class rhsusf_stryker_m1132_m2_base: rhsusf_stryker_m1126_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-1.3, -3.3, -0.5}};
};
};
};
class rhsusf_stryker_m1134_base: rhsusf_stryker_m1132_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-1, -2.2, -0.8}};
};
};
};
class rhsusf_m1151_base;
class rhsusf_M1165A1_GMV_SAG2_base: rhsusf_m1151_base {
class EGVAR(interaction,anims) {
class tools_hide {
positions[] = {{0.365, 1.5, -0.4}};
items[] = {"ACE_EntrenchingTool"};
name = ECSTRING(trenches,EntrenchingToolName);
text = ECSTRING(trenches,EntrenchingToolName);
};
};
};
};

View File

@ -0,0 +1,23 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhsusf_main_loadorder",
"ace_trenches"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
addonRootClass = QUOTE(ADDON);
};
};
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,3 @@
#define SUBCOMPONENT trenches
#define SUBCOMPONENT_BEAUTIFIED Trenches
#include "..\script_component.hpp"

View File

@ -372,6 +372,16 @@ class CfgVehicles {
};
class Car_F: Car {};
class Offroad_01_base_F: Car_F {
class GVAR(anims) {
class HideBackpacks {
positions[] = {{-1.15, -1.15, -0.2}, {1.1, -1.15, -0.2}, {1.1, -2.5, -0.2}};
items[] = {"B_TacticalPack_blk", "B_TacticalPack_blk", "B_Carryall_khk", "B_Carryall_khk"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Quadbike_01_base_F: Car_F {
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -405,6 +415,49 @@ class CfgVehicles {
};
};
class Wheeled_APC_F;
class APC_Wheeled_01_base_F: Wheeled_APC_F {
class GVAR(anims) {
class showBags {
phase = 0;
// Rotate interactions with turret rotation
positions[] = {
"[0, -1.6, 0] vectorAdd ([[1, -1, 0.1], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0, -1.6, 0] vectorAdd ([[-1, -1, 0.1], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"
};
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class APC_Wheeled_02_base_F: Wheeled_APC_F {
class GVAR(anims);
};
class APC_Wheeled_02_base_v2_F: APC_Wheeled_02_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr"};
name = "$STR_BACKPACK_CONTAINER_NAME";
text = "$STR_BACKPACK_CONTAINER_NAME";
};
};
};
class APC_Wheeled_03_base_F: Wheeled_APC_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Tank: LandVehicle {
class ACE_Actions {
class ACE_MainActions {
@ -432,6 +485,88 @@ class CfgVehicles {
};
};
};
class Tank_F;
class LT_01_base_F: Tank_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr"};
name = "$STR_BACKPACK_CONTAINER_NAME";
text = "$STR_BACKPACK_CONTAINER_NAME";
};
class showBags2: showBags {
selections[] = {"vhc_bags2"};
};
};
};
class APC_Tracked_01_base_F: Tank_F {
class GVAR(anims);
};
class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
positions[] = {"private _pos = _target selectionPosition 'vhc_bags'; _pos set [0, -(_pos select 0)]; _pos"}; // Mirror position to other side of vehicle
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class B_APC_Tracked_01_CRV_F: B_APC_Tracked_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags: showBags {
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
};
};
};
class APC_Tracked_02_base_F: Tank_F {
class GVAR(anims);
};
class O_APC_Tracked_02_base_F: APC_Tracked_02_base_F {};
class O_APC_Tracked_02_cannon_F: O_APC_Tracked_02_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class APC_Tracked_03_base_F: Tank_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class MBT_01_base_F: Tank_F {
class GVAR(anims);
};
class B_MBT_01_base_F: MBT_01_base_F {};
class B_MBT_01_cannon_F: B_MBT_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Motorcycle: LandVehicle {
class ACE_Actions {

View File

@ -54,4 +54,5 @@ PREP(push);
// misc
PREP(canFlip);
PREP(initAnimActions);
PREP(replaceTerrainObject);

View File

@ -149,11 +149,20 @@ GVAR(isOpeningDoor) = false;
["isNotOnLadder", {getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> animationState (_this select 0) >> "ACE_isLadder") != 1}] call EFUNC(common,addCanInteractWithCondition);
["CBA_settingsInitialized", {
TRACE_2("settingsInitialized",GVAR(disableNegativeRating),GVAR(enableAnimActions));
if (GVAR(disableNegativeRating)) then {
player addEventHandler ["HandleRating", {
(_this select 1) max 0
}];
};
if (!GVAR(enableAnimActions)) exitWith {};
// Don't add inherited anim actions (but actions are added to child classes)
{
[_x, "InitPost", LINKFUNC(initAnimActions), true, [], true] call CBA_fnc_addClassEventHandler;
} forEach (keys (uiNamespace getVariable QGVAR(animActionsClasses)));
}] call CBA_fnc_addEventHandler;
{
@ -162,7 +171,6 @@ GVAR(isOpeningDoor) = false;
}] call CBA_fnc_addPlayerEventHandler;
} forEach ["loadout", "weapon"];
// add "Take _weapon_" action to dropped weapons
private _action = [
// action display name will be overwritten in modifier function

View File

@ -16,6 +16,7 @@ DFUNC(repair_Statement) = { // moved from config because of build problems
};
if (hasInterface) then {
GVAR(initializedAnimClasses) = [];
GVAR(replaceTerrainModels) = createHashMapFromArray call (uiNamespace getVariable QGVAR(cacheReplaceTerrainModels));
};

View File

@ -23,3 +23,13 @@ private _cacheReplaceTerrainModels = createHashMap;
} forEach _replaceTerrainClasses;
uiNamespace setVariable [QGVAR(cacheReplaceTerrainModels), compileFinal str _cacheReplaceTerrainModels];
// Cache classes with anim actions
private _animActionsClasses = (QUOTE(isClass (_x >> QQGVAR(anims)) && {!isClass (inheritsFrom _x >> QQGVAR(anims))}) configClasses (configFile >> "CfgVehicles"));
_animActionsClasses = _animActionsClasses apply { configName _x };
_animActionsClasses = _animActionsClasses select {
private _class = _x;
(_animActionsClasses findIf {(_class != _x) && {_class isKindOf _x}}) == -1 // filter classes that already have a parent in the list
};
uiNamespace setVariable [QGVAR(animActionsClasses), compileFinal (_animActionsClasses createHashMapFromArray [])];

View File

@ -0,0 +1,194 @@
#include "..\script_component.hpp"
/*
* Author: Dystopian
* Initializes object interactions based on animations.
*
* Arguments:
* 0: Target <OBJECT>
*
* Return Value:
* None
*
* Example:
* cursorObject call ace_interaction_fnc_initAnimActions
*
* Public: No
*/
params ["_object"];
private _class = typeOf _object;
if (_class in GVAR(initializedAnimClasses)) exitWith {};
GVAR(initializedAnimClasses) pushBack _class;
private _statement = {
params ["_target", "_player", "_params"];
_params params ["_anim", "_phase", "_duration", "_text"];
TRACE_5("statement",_target,_player,_anim,_phase,_duration);
[
_duration,
[_target, _player, _anim, _phase],
{
(_this select 0) params ["_target", "_player", "_anim", "_phase"];
private _items = _target getVariable [
format [QGVAR(animsItems_%1), _anim],
getArray (configOf _target >> QGVAR(anims) >> _anim >> "items")
];
// If 1 object was spawned in, consider it a success
private _success = false;
if (_items isNotEqualTo []) then {
if (_items isEqualType "") then {
_items = [_items];
};
private _weaponHolder = objNull;
{
private _type = (_x call EFUNC(common,getItemType)) select 0;
if (_type == "") then {
private _emptyPosAGL = [];
// This covers testing vehicle stability and finding a safe position
for "_i" from 1 to 3 do {
_emptyPosAGL = [_target, _x, _player] call EFUNC(common,findUnloadPosition);
if (_emptyPosAGL isNotEqualTo []) exitWith {};
};
// If still no valid position, try the next item
if (_emptyPosAGL isEqualTo []) then {
[LELSTRING(common,NoRoomToUnload)] call EFUNC(common,displayTextStructured);
continue;
};
private _object = createVehicle [_x, _emptyPosAGL, [], 0, "CAN_COLLIDE"];
if (!isNull _object) then {
// Prevent items from taking damage when unloaded
[_object, "blockDamage", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
[EFUNC(common,statusEffect_set), [_object, "blockDamage", QUOTE(ADDON), false], 2] call CBA_fnc_waitAndExecute;
_success = true;
} else {
WARNING_1("Failed to create object of type '%1'",_x);
};
continue;
};
// Functions/code below are guaranteed to spawn in objects
_success = true;
// getItemType considers backpacks as weapons, so handle them first
if (getNumber (configFile >> "CfgVehicles" >> _x >> "isBackpack") == 1) then {
if (backpack _player == "") then {
_player addBackpackGlobal _x;
} else {
if (isNull _weaponHolder) then {
_weaponHolder = nearestObject [_player, "WeaponHolder"];
if (isNull _weaponHolder || {_player distance _weaponHolder > 2}) then {
_weaponHolder = createVehicle ["GroundWeaponHolder", [0, 0, 0], [], 0, "NONE"];
_weaponHolder setPosASL getPosASL _player;
};
};
_weaponHolder addBackpackCargoGlobal [_x, 1];
};
continue;
};
switch (_type) do {
case "weapon": {
[_player, _x, true] call CBA_fnc_addWeapon;
};
case "item": {
[_player, _x, true] call CBA_fnc_addItem;
};
case "magazine": {
[_player, _x, -1, true] call CBA_fnc_addMagazine;
};
};
} forEach _items;
};
if (!_success) exitWith {};
_target animate [_anim, _phase, true];
},
{},
_text,
{
(_this select 0) params ["_target", "", "_anim", "_phase"];
_target animationPhase _anim != _phase
},
["isNotSwimming"]
] call EFUNC(common,progressBar);
};
private _condition = {
params ["_target", "_player", "_params"];
_params params ["_anim", "_phase"];
_target animationPhase _anim != _phase
&& {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)}
};
private _config = configOf _object;
{
private _animConfig = _x;
private _anim = configName _animConfig;
private _animationSourcesConfig = _config >> "AnimationSources" >> _anim;
if !(
isClass _animationSourcesConfig // anim exist
&& {0 != [_animationSourcesConfig >> "scope", "NUMBER", 1] call CBA_fnc_getConfigEntry} // anim not hidden
&& {isNumber (_animationSourcesConfig >> "initPhase")} // anim correct (some CUP anims are inherited and cleared)
&& {0 != [_animConfig >> "enabled", "NUMBER", 1] call CBA_fnc_getConfigEntry} // anim enabled
) then {continue};
private _positions = [];
{
if (_x isEqualType "") then {
_positions pushBack compile _x;
} else {
_positions pushBack _x;
};
} forEach getArray (_animConfig >> "positions");
_positions append getArray (_animConfig >> "selections");
if (_positions isEqualTo []) then {
ERROR_2("No action position for _class %1 anim %2",_class,_anim);
continue;
};
private _phase = [_animConfig >> "phase", "NUMBER", 1] call CBA_fnc_getConfigEntry;
private _name = [_animConfig >> "name", "TEXT", localize "str_a3_cfgactions_unmountitem0"] call CBA_fnc_getConfigEntry;
private _icon = [_animConfig >> "icon", "TEXT", "\A3\ui_f\data\igui\cfg\actions\take_ca.paa"] call CBA_fnc_getConfigEntry;
private _duration = [_animConfig >> "duration", "NUMBER", 10] call CBA_fnc_getConfigEntry;
private _text = getText (_animConfig >> "text");
{
private _action = [
format [QGVAR(anim_%1_%2), _anim, _forEachIndex],
_name, _icon, _statement, _condition, {},
[_anim, _phase, _duration, _text],
_x
] call EFUNC(interact_menu,createAction);
[_class, 0, [], _action] call EFUNC(interact_menu,addActionToClass);
TRACE_3("add anim",_class,_anim,_x);
} forEach _positions;
} forEach configProperties [_config >> QGVAR(anims), "isClass _x"];

View File

@ -38,6 +38,16 @@
true
] call CBA_fnc_addSetting;
[
QGVAR(enableAnimActions), "CHECKBOX",
LSTRING(SettingAnimActionsName),
format ["ACE %1", LLSTRING(DisplayName)],
true,
true,
{[QGVAR(enableAnimActions), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;
[
QGVAR(interactWithTerrainObjects), "CHECKBOX",
["str_a3_modules_moduleomquest_defend_f_attributes_useterrainobject0", LSTRING(interactWithTerrainObjects_Description)],

View File

@ -1324,5 +1324,9 @@
<Spanish>Advertencia: puede provocar que algunos objetos choquen con otros.</Spanish>
<Portuguese>Aviso: pode causar que alguns objetos colidam com outros.</Portuguese>
</Key>
<Key ID="STR_ACE_Interaction_SettingAnimActionsName">
<English>Interaction with animations</English>
<Russian>Взаимодействие с анимациями</Russian>
</Key>
</Package>
</Project>

View File

@ -238,6 +238,20 @@ class CfgVehicles {
// Patria = LAV
GVAR(fuelCapacity) = 269;
};
class APC_Wheeled_02_base_F: Wheeled_APC_F {
class EGVAR(interaction,anims);
};
class APC_Wheeled_02_base_v2_F: APC_Wheeled_02_base_F {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class showCanisters {
phase = 0;
positions[] = {{-1.188, -3.87, -0.769}, {1.638, -3.87, -0.769}};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = CSTRING(TakeFuelCanister);
text = CSTRING(TakeFuelCanisterAction);
};
};
};
class Truck_F: Car_F {
GVAR(fuelCapacity) = 400;
@ -308,12 +322,14 @@ class CfgVehicles {
class MBT_01_base_F: Tank_F {
// Merkava IV
GVAR(fuelCapacity) = 1400;
class EGVAR(interaction,anims);
};
class MBT_02_base_F: Tank_F {
// T100 Black Eagle
// Assuming T80
GVAR(fuelCapacity) = 1100;
class EGVAR(interaction,anims);
};
class MBT_03_base_F: Tank_F {
@ -324,11 +340,37 @@ class CfgVehicles {
class MBT_01_arty_base_F: MBT_01_base_F {
// Assuming similar 2S3
GVAR(fuelCapacity) = 830;
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class showCanisters {
phase = 0;
// Rotate interactions with turret rotation
positions[] = {
"[0, -2.5, 0] vectorAdd ([[1.6, -2.4, -0.3], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0, -2.5, 0] vectorAdd ([[1.8, 0.55, -0.7], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0, -2.5, 0] vectorAdd ([[-1.8, 0.55, -0.7], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"
};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = CSTRING(TakeFuelCanister);
text = CSTRING(TakeFuelCanisterAction);
};
};
};
class MBT_02_arty_base_F: MBT_02_base_F {
// Assuming similar 2S3
GVAR(fuelCapacity) = 830;
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class showCanisters {
phase = 0;
// Rotate interactions with turret rotation
positions[] = {"[0, -2.1, 0] vectorAdd ([[1.6, -2.65, -0.3], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"};
items[] = {"Land_CanisterFuel_F"};
name = CSTRING(TakeFuelCanister);
text = CSTRING(TakeFuelCanisterAction);
};
};
};
class Heli_Light_02_base_F: Helicopter_Base_H {

View File

@ -429,9 +429,33 @@ class CfgVehicles {
GVAR(hitpointPositions)[] = {{"HitTurret", {0,-2,0}}};
};
class Tank_F;
class APC_Tracked_02_base_F: Tank_F {
class EGVAR(interaction,anims) {
class showTracks {
phase = 0;
positions[] = {{-1.7, -3.875, -0.7}, {1.7, -3.875, -0.7}};
items[] = {"ACE_Track", "ACE_Track", "ACE_Track"};
name = CSTRING(RemoveTrack);
text = CSTRING(RemovingTrack);
};
};
};
class Car_F: Car {
class HitPoints;
};
class Offroad_02_base_F: Car_F {
class EGVAR(interaction,anims) {
class hideSpareWheel {
selections[] = {"spare_wheel"};
items[] = {"ACE_Wheel"};
name = CSTRING(RemoveWheel);
text = CSTRING(RemovingWheel);
};
};
};
class Truck_F: Car_F {
class HitPoints: HitPoints {
class HitLBWheel;
@ -449,10 +473,43 @@ class CfgVehicles {
};
};
class Truck_01_viv_base_F;
class Truck_01_cargo_base_F: Truck_01_viv_base_F {
class EGVAR(interaction,anims) {
class Tyre1_hide {
selections[] = {"tyre1_hide"};
items[] = {"ACE_Wheel"};
name = CSTRING(RemoveWheel);
text = CSTRING(RemovingWheel);
};
};
};
class Truck_01_flatbed_base_F: Truck_01_viv_base_F {
class EGVAR(interaction,anims) {
class Tyre1_hide {
selections[] = {"tyre1_hide"};
items[] = {"ACE_Wheel"};
name = CSTRING(RemoveWheel);
text = CSTRING(RemovingWheel);
};
};
};
class Quadbike_01_base_F: Car_F {
GVAR(hitpointPositions)[] = { {"HitEngine", {0, 0.5, -0.7}}, {"HitFuel", {0, 0, -0.5}} };
};
class Hatchback_01_base_F: Car_F {
GVAR(hitpointPositions)[] = {{"HitBody", {0, 0.7, -0.5}}, {"HitFuel", {0, -1.75, -0.75}}};
};
class Van_02_base_F: Truck_F {
class EGVAR(interaction,anims) {
class spare_tyre_hide {
positions[] = {"[[-1.2, -3.7, -0.4], [-0.45, -3.5, -0.4]] select (_target animationPhase 'Door_4_source' == 0)"};
items[] = {"ACE_Wheel"};
name = CSTRING(RemoveWheel);
text = CSTRING(RemovingWheel);
};
};
};
};

View File

@ -106,4 +106,44 @@ class CfgVehicles {
MACRO_ADDITEM(ACE_EntrenchingTool,50);
};
};
class Wheeled_APC_F;
class APC_Wheeled_02_base_F: Wheeled_APC_F {
class EGVAR(interaction,anims);
};
class APC_Wheeled_02_base_v2_F: APC_Wheeled_02_base_F {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class showTools {
phase = 0;
positions[] = {{-1.108, -1.47, -0.769}};
items[] = {"ACE_EntrenchingTool"};
name = CSTRING(EntrenchingToolName);
text = CSTRING(EntrenchingToolName);
};
};
};
class APC_Wheeled_03_base_F: Wheeled_APC_F {
class EGVAR(interaction,anims) {
class showTools {
phase = 0;
positions[] = {{-0.9, -3, -0.5}};
items[] = {"ACE_EntrenchingTool"};
name = CSTRING(EntrenchingToolName);
text = CSTRING(EntrenchingToolName);
};
};
};
class Tank_F;
class LT_01_base_F: Tank_F {
class EGVAR(interaction,anims) {
class showTools {
phase = 0;
positions[] = {{0.6, 0, -0.3}};
items[] = {"ACE_EntrenchingTool"};
name = CSTRING(EntrenchingToolName);
text = CSTRING(EntrenchingToolName);
};
};
};
};