Wire cutter - Various improvements and cleanup (#6389)

* Optimize and cleanup interactEH function

* Add missing fences and improve formatting

* Improve cutDownFence function

* Remove unused sound files and cleanup

* Multi-line condition and fix examples

* Increase PFH delay and use distanceSqr
This commit is contained in:
mharis001 2018-07-13 12:30:13 -04:00 committed by PabstMirror
parent 3673a6f56a
commit def05b9cf1
14 changed files with 246 additions and 189 deletions

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));
@ -13,6 +12,6 @@ class Extended_PreInit_EventHandlers {
class Extended_PostInit_EventHandlers {
class ADDON {
clientInit = QUOTE( call COMPILE_FILE(XEH_clientInit) );
clientInit = QUOTE(call COMPILE_FILE(XEH_clientInit));
};
};

View File

@ -1,12 +0,0 @@
class CfgSounds {
class ACE_Wirecutter_sound {
name = "ACE_wirecutter_sound";
sound[] = {QPATHTOF(sound\wire_cut.ogg), "db-0", 1};
titles[] = {};
};
class ACE_Wirecutter_sound_long {
name = "ACE_wirecutter_sound_long";
sound[] = {QPATHTOF(sound\wire_cut_long.ogg), "db-0", 1};
titles[] = {};
};
};

View File

@ -8,19 +8,76 @@ class CfgVehicles {
class Wall_F;
class NonStrategic;
class Land_Net_Fence_4m_F: Wall_F { GVAR(isFence) = 1; };
class Land_Net_Fence_8m_F: Wall_F { GVAR(isFence) = 1; };
class Land_New_WiredFence_5m_F: Wall_F { GVAR(isFence) = 1; };
class Land_New_WiredFence_10m_F: Wall_F { GVAR(isFence) = 1; };
class Land_SportGround_fence_F: Wall_F { GVAR(isFence) = 1; };
class Land_Wired_Fence_4m_F: Wall_F { GVAR(isFence) = 1; };
class Land_Wired_Fence_8m_F: Wall_F { GVAR(isFence) = 1; };
class Land_SportGround_fence_noLC_F: Wall_F { GVAR(isFence) = 1; };
class Land_Mil_WiredFence_F: Wall_F { GVAR(isFence) = 1; };
class Land_IndFnc_Corner_F: Wall_F { GVAR(isFence) = 1; };
class Land_IndFnc_9_F: Wall_F { GVAR(isFence) = 1; };
class Land_IndFnc_3_Hole_F: Wall_F { GVAR(isFence) = 1; };
class Land_IndFnc_3_F: Wall_F { GVAR(isFence) = 1; };
class Land_Razorwire_F: NonStrategic { GVAR(isFence) = 1; };
class Land_Net_Fence_4m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Net_Fence_8m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_New_WiredFence_5m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_New_WiredFence_10m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_SportGround_fence_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Wired_Fence_4m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Wired_Fence_8m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_SportGround_fence_noLC_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Mil_WiredFence_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_IndFnc_Corner_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_IndFnc_9_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_IndFnc_3_Hole_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_IndFnc_3_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Razorwire_F: NonStrategic {
GVAR(isFence) = 1;
};
class Land_PlasticNetFence_01_short_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_PlasticNetFence_01_long_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_NetFence_01_m_4m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_NetFence_01_m_8m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_WiredFence_01_4m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_WiredFence_01_8m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_WiredFence_01_16m_F: Wall_F {
GVAR(isFence) = 1;
};
class Land_Slums01_8m: Wall_F {
GVAR(isFence) = 1;
};
class Land_Slums02_4m: Wall_F {
GVAR(isFence) = 1;
};
class Land_BackAlley_01_l_1m_F: Wall_F {
GVAR(isFence) = 1;
};
};

View File

@ -1,6 +1,6 @@
class CfgWeapons {
class CBA_MiscItem_ItemInfo;
class ACE_ItemCore;
class CBA_MiscItem_ItemInfo;
class ACE_wirecutter: ACE_ItemCore {
author = ECSTRING(common,ACETeam);

View File

@ -1,7 +1,7 @@
ace_logistics_wirecutter
===========
Adds an item that allows cutting of fences in Aarma 3 and AiA/CUP maps.
Adds an item that allows cutting of fences in Arma 3 and AiA/CUP maps.
#### Items Added:
`ACE_wirecutter`

View File

@ -1,4 +1,3 @@
PREP(cutDownFence);
PREP(interactEH);
PREP(isFence);

View File

@ -8,7 +8,7 @@ class CfgPatches {
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_interaction"};
author = ECSTRING(common,ACETeam);
authors[] = {"gpgpgpgp", "PabstMirror"};
authors[] = {"gpgpgpgp", "PabstMirror", "mharis001"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};

View File

@ -1,5 +1,4 @@
class StageTI
{
class StageTI {
texture = "a3\data_f\default_glass_ti_ca.paa";
};
ambient[] = {1,1,1,1};
@ -10,24 +9,20 @@ specular[] = {0,0,0,1};
specularPower = 0;
PixelShaderID = "Super";
VertexShaderID = "Super";
class Stage1
{
class Stage1 {
texture = "z\ace\addons\logistics_wirecutter\data\ace_wirecutter_nohq.paa";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1,0,0};
up[] = {0,1,0};
dir[] = {0,0,0};
pos[] = {0,0,0};
};
};
class Stage2
{
class Stage2 {
texture = "#(argb,8,8,3)color(0.5,0.5,0.5,0.5,DT)";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1,0,0};
up[] = {0,1,0};
dir[] = {0,0,0};
@ -38,8 +33,7 @@ class Stage3
{
texture = "#(argb,8,8,3)color(0,0,0,0,MC)";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1,0,0};
up[] = {0,1,0};
dir[] = {0,0,0};
@ -50,8 +44,7 @@ class Stage4
{
texture = "#(argb,8,8,3)color(1,1,1,1,AS)";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1,0,0};
up[] = {0,1,0};
dir[] = {0,0,0};
@ -62,26 +55,22 @@ class Stage5
{
texture = "#(argb,8,8,3)color(0,0.6,1,1,SMDI)";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1,0,0};
up[] = {0,1,0};
dir[] = {0,0,0};
pos[] = {0,0,0};
};
};
class Stage6
{
class Stage6 {
texture = "#(ai,32,128,1)fresnel(0.71,0.74)";
uvSource = "none";
};
class Stage7
{
class Stage7 {
texture = "a3\data_f\env_land_co.paa";
useWorldEnvMap = "true";
uvSource = "tex";
class uvTransform
{
class uvTransform {
aside[] = {1.0,0.0,0.0};
up[] = {0.0,1.0,0.0};
dir[] = {0.0,0.0,0.0};

View File

@ -1,6 +1,6 @@
/*
* Author: gpgpgpgp, edited by commy2, PabstMirror
* Starts cutting down a fence
* Author: gpgpgpgp, commy2, PabstMirror, mharis001
* Starts cutting down a fence. Triggers global "ace_wireCuttingStarted" event.
*
* Arguments:
* 0: Unit <OBJECT>
@ -10,52 +10,59 @@
* None
*
* Example:
* [player, berlinWall] call ace_logistics_wirecutter_fnc_cutDownFence
* [player, cursorObject] call ace_logistics_wirecutter_fnc_cutDownFence
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_fenceObject"];
TRACE_2("params",_unit,_fenceObject);
params ["_unit", "_fence"];
TRACE_2("Fence cutting started",_unit,_fence);
if (_unit != ACE_player) exitWith {};
private _timeToCut = if ([_unit] call EFUNC(common,isEngineer)) then {7.5} else {11};
// Get cut time based on if unit is a engineer
private _cutTime = if (_unit call EFUNC(common,isEngineer)) then {CUT_TIME_ENGINEER} else {CUT_TIME_DEFAULT};
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AinvPknlMstpSnonWnonDr_medic5", 0] call EFUNC(common,doAnimation);
};
private _onCompletion = {
TRACE_1("_onCompletion",_this);
(_this select 0) params ["_fenceObject", "", "_unit"];
_fenceObject setdamage 1;
[
_cutTime,
[_unit, _fence, 0],
{
TRACE_1("Fence cutting successful",_this);
(_this select 0) params ["_unit", "_fence"];
_fence setDamage 1;
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AmovPknlMstpSrasWrflDnon", 1] call EFUNC(common,doAnimation);
};
};
},
{
TRACE_1("Fence cutting failed",_this);
(_this select 0) params ["_unit"];
private _onFail = {
TRACE_1("_onFail", _this);
(_this select 0) params ["", "", "_unit"];
if !(_unit call EFUNC(common,isSwimming)) then {
[_unit, "AmovPknlMstpSrasWrflDnon", 1] call EFUNC(common,doAnimation);
};
};
},
localize LSTRING(CuttingFence),
{
params ["_args", "_elapsedTime"];
_args params ["_unit", "_fence", "_lastSoundTime"];
private _progressCheck = {
params ["_args", "_passedTime"];
_args params ["_fenceObject", "_lastSoundEffectTime", "_unit"];
if (_passedTime > (_lastSoundEffectTime + SOUND_CLIP_TIME_SPACEING)) then {
playSound3D [QUOTE(PATHTO_R(sound\wirecut.ogg)), objNull, false, (getPosASL _unit), 3, 1, 10];
_args set [1, _passedTime];
if (_elapsedTime > _lastSoundTime + SOUND_CLIP_TIME_SPACING) then {
playSound3D [QPATHTO_R(sound\wirecut.ogg), objNull, false, getPosASL _unit, 3, 1, 10];
_args set [2, _elapsedTime];
};
((!isNull _fenceObject) && {(damage _fenceObject) < 1} && {("ACE_wirecutter" in (items _unit))})
};
!isNull _fence
&& {damage _fence < 1}
&& {"ACE_wirecutter" in ([_player, false, true, true, true, false] call CBA_fnc_uniqueUnitItems)}
},
["isNotSwimming"]
] call EFUNC(common,progressBar);
[_timeToCut, [_fenceObject,0,_unit], _onCompletion, _onFail, localize LSTRING(CuttingFence), _progressCheck, ["isNotSwimming"]] call EFUNC(common,progressBar);
["ace_wireCuttingStarted", [_unit, _fenceObject]] call CBA_fnc_globalEvent;
["ace_wireCuttingStarted", [_unit, _fence]] call CBA_fnc_globalEvent;

View File

@ -1,9 +1,10 @@
/*
* Author: PabstMirror
* When interact_menu starts rendering (from "interact_keyDown" event)
* Author: PabstMirror, mharis001
* Dynamically adds "Cut Fence" actions to nearby fences when interact_menu is opened.
* Called by the "ace_interactMenuOpened" event.
*
* Arguments:
* Interact Menu Type (0 - world, 1 - self) <NUMBER>
* Interact Menu Type (0 - World, 1 - Self) <NUMBER>
*
* Return Value:
* None
@ -11,65 +12,69 @@
* Example:
* [0] call ace_logistics_wirecutter_fnc_interactEH
*
* Public: Yes
* Public: No
*/
#include "script_component.hpp"
params ["_interactionType"];
//Ignore self-interaction menu or mounted vehicle interaction
if ((_interactionType != 0) || {(vehicle ACE_player) != ACE_player}) exitWith {};
// Ignore self-interaction menu or mounted vehicle interaction
// For performance reasons only add PFH if player has wirecutter item
// If player somehow gets a wirecutter during keyDown, they will just have to reopen menu
if (
_interactionType != 0
|| {vehicle ACE_player != ACE_player}
|| {!("ACE_wirecutter" in ([ACE_player, false, true, true, true, false] call CBA_fnc_uniqueUnitItems))}
) exitWith {};
//for performance only do stuff it they have a wirecutter item
//(if they somehow get one durring keydown they'll just have to reopen)
if (!("ACE_wirecutter" in (items ace_player))) exitWith {};
TRACE_1("Starting wire-cut action PFEH",_interactionType);
TRACE_1("Starting wirecuter interact PFH",_interactionType);
[{
params ["_args", "_pfID"];
BEGIN_COUNTER(interactEH);
params ["_args", "_pfhID"];
_args params ["_setPosition", "_addedHelpers", "_fencesHelped"];
if (!EGVAR(interact_menu,keyDown)) then {
{deleteVehicle _x; nil} count _addedHelpers;
[_pfID] call CBA_fnc_removePerFrameHandler;
{deleteVehicle _x} forEach _addedHelpers;
[_pfhID] call CBA_fnc_removePerFrameHandler;
} else {
// Prevent Rare Error when ending mission with interact key down:
if (isNull ace_player) exitWith {};
//If player moved >5 meters from last pos, then rescan
if (((getPosASL ace_player) distance _setPosition) > 5) then {
// Prevent rare error when ending mission with interact key down
if (isNull ACE_player) exitWith {};
// Rescan if player has moved more than 5 meters from last position
if (getPosASL ACE_player distanceSqr _setPosition > 25) then {
private _fncStatement = {
params ["", "_player", "_attachedFence"];
[_player, _attachedFence] call FUNC(cutDownFence);
};
private _fncCondition = {
params ["_helper", "_player", "_attachedFence"];
if (!([_player, _attachedFence, ["isNotSwimming"]] call EFUNC(common,canInteractWith))) exitWith {false};
((!isNull _attachedFence) && {(damage _attachedFence) < 1} && {("ACE_wirecutter" in (items _player))} && {
//Custom LOS check for fence
private _headPos = ACE_player modelToWorldVisual (ACE_player selectionPosition "pilot");
((!(lineIntersects [AGLtoASL _headPos, AGLtoASL (_helper modelToWorldVisual [0,0,1.25]), _attachedFence, ACE_player])) ||
{!(lineIntersects [AGLtoASL _headPos, getPosASL _attachedFence, _attachedFence, ACE_player])})
})
};
!isNull _attachedFence
&& {damage _attachedFence < 1}
&& {"ACE_wirecutter" in ([_player, false, true, true, true, false] call CBA_fnc_uniqueUnitItems)}
&& {[_player, _attachedFence, ["isNotSwimming"]] call EFUNC(common,canInteractWith)}
&& {
// Custom LOS check for fence
private _headPos = AGLtoASL (_player modelToWorldVisual (_player selectionPosition "pilot"));
!lineIntersects [_headPos, AGLtoASL (_helper modelToWorldVisual [0, 0, 1.25]), _attachedFence, _player]
|| {!lineIntersects [_headPos, getPosASL _attachedFence, _attachedFence, _player]}
}
};
{
if (!(_x in _fencesHelped)) then {
if ([_x] call FUNC(isFence)) then {
if (!(_x in _fencesHelped) && {_x call FUNC(isFence)}) then {
_fencesHelped pushBack _x;
private _helper = "ACE_LogicDummy" createVehicleLocal (getpos _x);
private _action = [QGVAR(helperCutFence), (localize LSTRING(CutFence)), QPATHTOF(ui\wirecutter_ca.paa), _fncStatement, _fncCondition, {}, _x, {[0,0,0]}, 5.5, [false, false, false, false, true]] call EFUNC(interact_menu,createAction);
[_helper, 0, [],_action] call EFUNC(interact_menu,addActionToObject);
_helper setPosASL ((getPosASL _x) vectorAdd [0,0,1.25]);
private _helper = "ACE_LogicDummy" createVehicleLocal [0, 0, 0];
private _action = [QGVAR(helperCutFence), localize LSTRING(CutFence), QPATHTOF(ui\wirecutter_ca.paa), _fncStatement, _fncCondition, {}, _x, {[0, 0, 0]}, 5.5, [false, false, false, false, true]] call EFUNC(interact_menu,createAction);
[_helper, 0, [], _action] call EFUNC(interact_menu,addActionToObject);
_helper setPosASL (getPosASL _x vectorAdd [0, 0, 1.25]);
_addedHelpers pushBack _helper;
};
};
nil
} count nearestObjects [ace_player, [], 15];
} forEach nearestObjects [ACE_player, [], 15];
_args set [0, (getPosASL ace_player)];
_args set [0, getPosASL ACE_player];
};
};
}, 0.1, [((getPosASL ace_player) vectorAdd [-100,0,0]), [], []]] call CBA_fnc_addPerFrameHandler;
END_COUNTER(interactEH);
}, 0.5, [getPosASL ACE_player vectorAdd [-100, 0, 0], [], []]] call CBA_fnc_addPerFrameHandler;

View File

@ -1,32 +1,32 @@
/*
* Author: PabstMirror
* Checks if object is a fence. Should work on any fence type, even (typeOf == "").
* Call is fairly expensive because of all of the string checking.
* Checks if object is a fence. Should work on any fence type, even when (typeOf == "").
* Call is fairly expensive because of string checking.
*
* Arguments:
* 0: An Object To Test <OBJECT>
* 0: Object to test <OBJECT>
*
* Return Value:
* Is it a fence <BOOL>
* Is fence <BOOL>
*
* Example:
* [aFence] call ace_logistics_wirecutter_fnc_isFence
* [cursorObject] call ace_logistics_wirecutter_fnc_isFence
*
* Public: No
*/
#include "script_component.hpp"
params ["_object"];
TRACE_1("params",_object);
TRACE_1("Checking if fence",_object);
private _typeOf = typeOf _object;
private _returnValue = if (_typeOf != "") then {
//If the fence has configEntry we can check it directly
(1 == (getNumber (configFile >> "CfgVehicles" >> _typeOf >> QGVAR(isFence))));
// Check for isFence entry since we have valid typeOf
1 == getNumber (configFile >> "CfgVehicles" >> _typeOf >> QGVAR(isFence));
} else {
//Check the p3d name against list (in script_component.hpp)
((getModelInfo _object) select 0) in FENCE_P3DS;
// Check the p3d name against list (in script_component.hpp)
(getModelInfo _object select 0) in FENCE_P3DS;
};
_returnValue

View File

@ -16,8 +16,7 @@
#include "\z\ace\addons\main\script_macros.hpp"
//find is case sensitive, so keep everything lowercase
// find is case sensitive, so keep everything lowercase
#define FENCE_P3DS [\
"mil_wiredfence_f.p3d",\
"wall_indfnc_3.p3d",\
@ -26,7 +25,21 @@
"pletivo_wired.p3d",\
"wall_fen1_5.p3d",\
"net_fence_8m_f.p3d",\
"razorwire_f.p3d"\
"razorwire_f.p3d",\
"wired_fence_4m_f.p3d",\
"wired_fence_8m_f.p3d",\
"plasticnetfence_01_short_f.p3d",\
"plasticnetfence_01_long_f.p3d",\
"netfence_01_m_4m_f.p3d",\
"netfence_01_m_8m_f.p3d",\
"wiredfence_01_4m_f.p3d",\
"wiredfence_01_8m_f.p3d",\
"wiredfence_01_16m_f.p3d",\
"slums01_8m.p3d",\
"slums02_4m.p3d",\
"backalley_01_l_1m_f.p3d"\
]
#define SOUND_CLIP_TIME_SPACEING 1.5
#define SOUND_CLIP_TIME_SPACING 1.5
#define CUT_TIME_DEFAULT 11
#define CUT_TIME_ENGINEER 7.5