diff --git a/.hemtt/lints.toml b/.hemtt/lints.toml new file mode 100644 index 0000000..969a9a3 --- /dev/null +++ b/.hemtt/lints.toml @@ -0,0 +1,4 @@ +[sqf.var_all_caps] +options.ignore = [ + "MTS_RECOMPILES", "MTS_PREP_RECOMPILE" +] diff --git a/README.md b/README.md index 4c625a0..3d567d0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
-
+
diff --git a/addons/engineer/CfgVehicles.hpp b/addons/engineer/CfgVehicles.hpp
index 59e155b..9e25ba8 100644
--- a/addons/engineer/CfgVehicles.hpp
+++ b/addons/engineer/CfgVehicles.hpp
@@ -56,4 +56,22 @@ class CfgVehicles {
ace_dragging_canDrag = 1;
ace_dragging_dragPosition[] = {0, 1.2, 0};
};
+
+ // Assault Breacher Vehicle / MiRPz
+ class APC_Tracked_01_base_F;
+ class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F {
+ class Attributes;
+ };
+ class B_APC_Tracked_01_CRV_F: B_APC_Tracked_01_base_F {
+ class Attributes: Attributes {
+ class GVAR(mineClearing) {
+ displayName = CSTRING(mineClearingDisplayName);
+ property = QGVAR(enableMineClearing);
+ control = "Checkbox";
+ defaultValue = "true";
+ typeName = "BOOL";
+ expression = QUOTE(_this setVariable [ARR_3(QQGVAR(enableMineClearing),_value,true)];); // Only run on server
+ };
+ };
+ };
};
diff --git a/addons/engineer/XEH_PREP.hpp b/addons/engineer/XEH_PREP.hpp
index 7cc71d8..115dc4f 100644
--- a/addons/engineer/XEH_PREP.hpp
+++ b/addons/engineer/XEH_PREP.hpp
@@ -1,2 +1,8 @@
PREP(addIgniteMiclicAction);
+PREP(canStartMineClearing);
+PREP(canStopMineClearing);
+PREP(handleMineClearingEffects);
PREP(igniteMiclic);
+PREP(initMineClearingActions);
+PREP(startMineClearing);
+PREP(stopMineClearing);
diff --git a/addons/engineer/XEH_preInit.sqf b/addons/engineer/XEH_preInit.sqf
index b47cf66..4528ed2 100644
--- a/addons/engineer/XEH_preInit.sqf
+++ b/addons/engineer/XEH_preInit.sqf
@@ -7,3 +7,11 @@ PREP_RECOMPILE_START;
PREP_RECOMPILE_END;
ADDON = true;
+
+["B_APC_Tracked_01_CRV_F", "InitPost", {
+ _this call FUNC(initMineClearingActions);
+}, nil, nil, true] call CBA_fnc_addClassEventHandler;
+
+["gm_BPz2a0_base", "InitPost", {
+ _this call FUNC(initMineClearingActions);
+}, nil, nil, true] call CBA_fnc_addClassEventHandler;
diff --git a/addons/engineer/config.cpp b/addons/engineer/config.cpp
index ee624be..3ab7a4b 100644
--- a/addons/engineer/config.cpp
+++ b/addons/engineer/config.cpp
@@ -10,7 +10,7 @@ class CfgPatches {
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"mts_main", "ace_cargo", "ace_dragging"};
author = ECSTRING(main,authors);
- authors[] = {"Timi007", "Mishkar"};
+ authors[] = {"Timi007", "Mishkar", "Lemonberries"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
diff --git a/addons/engineer/engineer_compat_gm/CfgVehicles.hpp b/addons/engineer/engineer_compat_gm/CfgVehicles.hpp
new file mode 100644
index 0000000..241a51b
--- /dev/null
+++ b/addons/engineer/engineer_compat_gm/CfgVehicles.hpp
@@ -0,0 +1,18 @@
+class CfgVehicles {
+ class gm_Leopard1_base;
+ class gm_BPz2_base: gm_Leopard1_base {
+ class Attributes;
+ };
+ class gm_BPz2a0_base: gm_BPz2_base {
+ class Attributes: Attributes {
+ class GVAR(mineClearing) {
+ displayName = CSTRING(mineClearingDisplayName);
+ property = QGVAR(enableMineClearing);
+ control = "Checkbox";
+ defaultValue = "true";
+ typeName = "BOOL";
+ expression = QUOTE(_this setVariable [ARR_3(QQGVAR(enableMineClearing),_value,true)];); // Only run on server
+ };
+ };
+ };
+};
diff --git a/addons/engineer/engineer_compat_gm/config.cpp b/addons/engineer/engineer_compat_gm/config.cpp
new file mode 100644
index 0000000..3616a21
--- /dev/null
+++ b/addons/engineer/engineer_compat_gm/config.cpp
@@ -0,0 +1,23 @@
+#include "script_component.hpp"
+
+class CfgPatches {
+ class SUBADDON {
+ name = COMPONENT_NAME;
+ units[] = {};
+ weapons[] = {};
+ requiredVersion = REQUIRED_VERSION;
+ requiredAddons[] = {
+ QUOTE(ADDON),
+ "gm_vehicles_land_tracked_bpz2"
+ };
+ skipWhenMissingDependencies = 1;
+ author = ECSTRING(main,authors);
+ authors[] = {"Timi007"};
+ url = ECSTRING(main,URL);
+ VERSION_CONFIG;
+
+ addonRootClass = QUOTE(ADDON);
+ };
+};
+
+#include "CfgVehicles.hpp"
diff --git a/addons/engineer/engineer_compat_gm/script_component.hpp b/addons/engineer/engineer_compat_gm/script_component.hpp
new file mode 100644
index 0000000..e5e3fed
--- /dev/null
+++ b/addons/engineer/engineer_compat_gm/script_component.hpp
@@ -0,0 +1,3 @@
+#define SUBCOMPONENT compat_gm
+#define SUBCOMPONENT_BEAUTIFIED Compat GM
+#include "..\script_component.hpp"
diff --git a/addons/engineer/functions/fnc_canStartMineClearing.sqf b/addons/engineer/functions/fnc_canStartMineClearing.sqf
new file mode 100644
index 0000000..f239658
--- /dev/null
+++ b/addons/engineer/functions/fnc_canStartMineClearing.sqf
@@ -0,0 +1,26 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Checks if the vehicle can start clearing mines.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ * 1: OBJECT - Caller
+ *
+ * Returns:
+ * BOOLEAN - Can start clearing mines.
+ *
+ * Example:
+ * _this call mts_engineer_fnc_canStartMineClearing
+ *
+ */
+
+params ["_vehicle", "_caller"];
+
+(_caller isEqualTo (driver _vehicle)) && // is driver of the vehicle
+{_vehicle getVariable [QGVAR(enableMineClearing), true]} && // mine clearing enabled
+{!(_vehicle getVariable [QGVAR(mineClearingActive), false])} && // not already mine clearing
+{speed _vehicle <= MAX_MINE_CLEARING_SPEED} &&
+{isEngineOn _vehicle}
diff --git a/addons/engineer/functions/fnc_canStopMineClearing.sqf b/addons/engineer/functions/fnc_canStopMineClearing.sqf
new file mode 100644
index 0000000..cd29334
--- /dev/null
+++ b/addons/engineer/functions/fnc_canStopMineClearing.sqf
@@ -0,0 +1,23 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Checks if the vehicle can stop clearing mines.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ * 1: OBJECT - Caller
+ *
+ * Returns:
+ * BOOLEAN - Can stop clearing mines.
+ *
+ * Example:
+ * _this call mts_engineer_fnc_canStopMineClearing
+ *
+ */
+
+params ["_vehicle", "_caller"];
+
+(_caller isEqualTo (driver _vehicle)) && // is driver of the vehicle
+{_vehicle getVariable [QGVAR(mineClearingActive), false]} // mine clearing is active
diff --git a/addons/engineer/functions/fnc_handleMineClearingEffects.sqf b/addons/engineer/functions/fnc_handleMineClearingEffects.sqf
new file mode 100644
index 0000000..0a8c0ad
--- /dev/null
+++ b/addons/engineer/functions/fnc_handleMineClearingEffects.sqf
@@ -0,0 +1,118 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Spawn and move the particles during mine clearing.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Example:
+ * _this call mts_engineer_fnc_handleMineClearingEffects
+ *
+ */
+
+params [["_vehicle", objNull, [objNull]]];
+
+private _pos = getPos _vehicle;
+
+private _dustParticle = "#particlesource" createVehicleLocal _pos;
+_dustParticle setParticleCircle [0, [0, 0, 0]];
+_dustParticle setParticleRandom
+[
+ 2, // lifeTimeVar
+ [0.5, 3, 0], // positionVar
+ [5, 5, 10], // moveVelocityVar
+ 1, // rotationVelocityVar
+ 0, // sizeVar
+ [0, 0, 0, 0.01], // colorVar
+ 0, // randomDirectionPeriodVar
+ 0, // randomDirectionIntensityVar
+ 0 // angleVar
+];
+_dustParticle setDropInterval 0.01;
+
+private _dirtParticle = "#particlesource" createVehicleLocal _pos;
+_dirtParticle setParticleCircle [0, [0, 0, 0]];
+_dirtParticle setParticleRandom
+[
+ 2,
+ [0.5, 3, 0],
+ [15, 15, 5],
+ 0.1,
+ 0,
+ [0, 0, 0, 0],
+ 0,
+ 0
+];
+_dirtParticle setDropInterval 0.5;
+
+[{
+ params ["_PFHArgs", "_PFHID"];
+ _PFHArgs params ["_vehicle", "_dustParticle", "_dirtParticle"];
+
+ if (!(_vehicle getVariable [QGVAR(mineClearingActive), false])) exitWith {
+ [_PFHID] call CBA_fnc_removePerFrameHandler;
+
+ deleteVehicle _dustParticle;
+ deleteVehicle _dirtParticle;
+ };
+
+ private _vectorDir = vectorDirVisual _vehicle;
+
+ _dustParticle setParticleParams
+ [
+ ["\A3\data_f\cl_basic", 1, 0, 1],
+ "",
+ "Billboard",
+ 1,
+ 4, // lifeTime
+ [0, 4, -2.5], // pos3D
+ [(_vectorDir select 0) * 50, (_vectorDir select 1) * 50, 22], // moveVelocity
+ 0, // rotationVelocity
+ 1.6, // weight
+ 1, // volume
+ 0.3, // rubbing
+ [2.2, 4, 6], // size
+ [[0.060, 0.04, 0.02, 0.6], [0.050, 0.035, 0.02, 0.4], [0.030, 0.025, 0.015, 0.2]], // color
+ [1], // animationSpeed
+ 3, // randomDirectionPeriod
+ 3, // randomDirectionIntensity
+ "", // onTimerScript
+ "", // beforeDestroyScript
+ _vehicle,
+ 0, // angle
+ true, // onSurface
+ 0.1 // bounceOnSurface
+ ];
+
+ _dirtParticle setParticleParams
+ [
+ ["\A3\data_f\ParticleEffects\Universal\Mud", 1, 0, 1],
+ "",
+ "SpaceObject",
+ 1,
+ 10,
+ [0, 4, -2.5],
+ [(_vectorDir select 0) * 20, (_vectorDir select 1) * 20, 10],
+ 0,
+ 2,
+ 0.1,
+ 0.1,
+ [0.2],
+ [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
+ [0.08],
+ 0,
+ 0,
+ "",
+ "",
+ _vehicle,
+ 0,
+ true,
+ 0.2
+ ];
+}, DIRT_SFX_UPDATE_INTERVAL, [_vehicle, _dustParticle, _dirtParticle]] call CBA_fnc_addPerFrameHandler;
diff --git a/addons/engineer/functions/fnc_igniteMiclic.sqf b/addons/engineer/functions/fnc_igniteMiclic.sqf
index fe9eddf..556f239 100644
--- a/addons/engineer/functions/fnc_igniteMiclic.sqf
+++ b/addons/engineer/functions/fnc_igniteMiclic.sqf
@@ -16,7 +16,7 @@
* Nothing.
*
* Example:
- * [this] call mts_items_fnc_igniteMiclic
+ * [this] call mts_engineer_fnc_igniteMiclic
*
*/
diff --git a/addons/engineer/functions/fnc_initMineClearingActions.sqf b/addons/engineer/functions/fnc_initMineClearingActions.sqf
new file mode 100644
index 0000000..11313f7
--- /dev/null
+++ b/addons/engineer/functions/fnc_initMineClearingActions.sqf
@@ -0,0 +1,68 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Adds actions for mine clearing to the vehicle.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Example:
+ * _this call mts_engineer_fnc_initMineClearingActions
+ *
+ */
+
+params [["_vehicle", objNull, [objNull]]];
+
+_vehicle addAction [
+ LLSTRING(startMineClearing),
+ {
+ params ["_vehicle"];
+
+ [_vehicle] call FUNC(startMineClearing);
+ },
+ [], // _arguments
+ 2, // priority
+ true, // showWindow
+ true, // hideOnUse
+ "", // shortcut
+ QUOTE([ARR_2(_target,_this)] call FUNC(canStartMineClearing))
+];
+
+_vehicle addAction [
+ LLSTRING(stopMineClearing),
+ {
+ params ["_vehicle"];
+
+ [_vehicle] call FUNC(stopMineClearing);
+ },
+ [], // _arguments
+ 2, // priority
+ true, // showWindow
+ true, // hideOnUse
+ "", // shortcut
+ QUOTE([ARR_2(_target,_this)] call FUNC(canStopMineClearing))
+];
+
+// If driver leaves vehicle during mine clearing, speed limiter and allowDamage need to be set again
+_vehicle addEventHandler ["Local", {
+ params ["_vehicle", "_isLocal"];
+
+ TRACE_1("Locality changed during mine clearing",_this);
+
+ if (_vehicle getVariable [QGVAR(mineClearingActive), false]) then {
+ // Set speed limiter and damage again
+ _vehicle setCruiseControl [MAX_MINE_CLEARING_SPEED, false];
+ _vehicle allowDamage false;
+ } else {
+ // Set speed limiter and damage again
+ _vehicle setCruiseControl [0, false];
+ if (_vehicle getVariable [QGVAR(originalIsDamageAllowed), true]) then {
+ _vehicle allowDamage true;
+ };
+ };
+}];
diff --git a/addons/engineer/functions/fnc_startMineClearing.sqf b/addons/engineer/functions/fnc_startMineClearing.sqf
new file mode 100644
index 0000000..0af2d1c
--- /dev/null
+++ b/addons/engineer/functions/fnc_startMineClearing.sqf
@@ -0,0 +1,73 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Start the mine clearing process. Must be called where vehicle is local.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Example:
+ * [_veh] call mts_engineer_fnc_startMineClearing
+ *
+ */
+
+params [["_vehicle", objNull, [objNull]]];
+
+CHECK(isNull _vehicle);
+CHECKRET(!local _vehicle,ERROR_1("Called on non-local vehicle '%1'",_vehicle));
+
+_vehicle setVariable [QGVAR(mineClearingActive), true, true];
+_vehicle setVariable [QGVAR(originalIsDamageAllowed), isDamageAllowed _vehicle, true];
+
+_vehicle allowDamage false;
+
+_vehicle setCruiseControl [MAX_MINE_CLEARING_SPEED, false];
+
+// Animate plow
+private _animationSource = ["", 0];
+if (_vehicle isKindOf "B_APC_Tracked_01_CRV_F") then {
+ _animationSource = ["moveplow", 1]; // for vanilla
+};
+if (_vehicle isKindOf "gm_BPz2a0_base") then {
+ _animationSource = ["dozer_blade_elev_source", 0.65]; // for gm
+};
+
+_vehicle animateSource _animationSource;
+
+[{
+ params ["_vehicle", "_animationSource"];
+ _animationSource params ["_animationName", "_animationPhase"];
+
+ (_vehicle animationSourcePhase _animationName) >= (_animationPhase - 0.02)
+}, {
+ params ["_vehicle"];
+
+ [_vehicle] remoteExecCall [QFUNC(handleMineClearingEffects), 0];
+
+ GVAR(lastDirtPatch) = objNull;
+
+ [{
+ params ["_PFHArgs", "_PFHID"];
+ _PFHArgs params ["_vehicle", "_animationSource"];
+
+ if (!(_vehicle getVariable [QGVAR(mineClearingActive), false])) exitWith {
+ [_PFHID] call CBA_fnc_removePerFrameHandler;
+ };
+
+ if ((isNull GVAR(lastDirtPatch)) || (_vehicle distance GVAR(lastDirtPatch) > DIRT_PATCH_DISTANCE)) then {
+ private _dirtPatch = createVehicle ["Land_DirtPatch_01_6x8_F", [0, 0, 0], [], 0, "CAN_COLLIDE"];
+ private _dirtPatchPosASL = AGLToASL (_vehicle modelToWorldVisual [0, 2, 0]);
+ _dirtPatch setPosASL _dirtPatchPosASL;
+ _dirtPatch setDir (getDir _vehicle) + 90;
+
+ createVehicle ["Land_ClutterCutter_medium_F", getPosATL _dirtPatch, [], 0, "CAN_COLLIDE"];
+
+ GVAR(lastDirtPatch) = _dirtPatch;
+ };
+ }, DIRT_PATCH_UPDATE_INTERVAL, _this] call CBA_fnc_addPerFrameHandler;
+}, [_vehicle, _animationSource]] call CBA_fnc_waitUntilAndExecute;
diff --git a/addons/engineer/functions/fnc_stopMineClearing.sqf b/addons/engineer/functions/fnc_stopMineClearing.sqf
new file mode 100644
index 0000000..b92232e
--- /dev/null
+++ b/addons/engineer/functions/fnc_stopMineClearing.sqf
@@ -0,0 +1,38 @@
+#include "script_component.hpp"
+/**
+ * Author: Timi007
+ *
+ * Description:
+ * Stops the mine clearing process. Must be called where vehicle is local.
+ *
+ * Parameter(s):
+ * 0: OBJECT - Mine clearing vehicle (ABV/MiRPz)
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Example:
+ * [_veh] call mts_engineer_fnc_stopMineClearing
+ *
+ */
+
+params [["_vehicle", objNull, [objNull]]];
+
+CHECK(isNull _vehicle);
+CHECKRET(!local _vehicle,ERROR_1("Called on non-local vehicle '%1'",_vehicle));
+
+if (_vehicle isKindOf "B_APC_Tracked_01_CRV_F") then {
+ _vehicle animateSource ["moveplow", 0]; // for vanilla
+};
+if (_vehicle isKindOf "gm_BPz2a0_base") then {
+ _vehicle animateSource ["dozer_blade_elev_source", 0]; // for gm
+};
+
+_vehicle setCruiseControl [0, false];
+
+if (_vehicle getVariable [QGVAR(originalIsDamageAllowed), true]) then {
+ _vehicle allowDamage true;
+};
+
+
+_vehicle setVariable [QGVAR(mineClearingActive), false, true];
diff --git a/addons/engineer/script_component.hpp b/addons/engineer/script_component.hpp
index 9628901..024fb3c 100644
--- a/addons/engineer/script_component.hpp
+++ b/addons/engineer/script_component.hpp
@@ -23,3 +23,8 @@
#define G 9.81 // Gravitational acceleration
#define SPAWN_HEIGHT_OFFSET 0.5 // Spawn height of rocket relative to the miclic ATL position
+
+#define MAX_MINE_CLEARING_SPEED 5 // km/h
+#define DIRT_PATCH_UPDATE_INTERVAL 0.5 // Sec
+#define DIRT_SFX_UPDATE_INTERVAL 2 // Sec
+#define DIRT_PATCH_DISTANCE 2.5 // m
diff --git a/addons/engineer/stringtable.xml b/addons/engineer/stringtable.xml
index 82f8811..1688cfc 100644
--- a/addons/engineer/stringtable.xml
+++ b/addons/engineer/stringtable.xml
@@ -17,5 +17,23 @@