mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Changed: Entire frag system re-optimized to a single tracking/GC index-based PFH.
Changed: Spalling calculations now throttled across frames and limited; accurate but performant Changed: All lookups are now index-based on a global projectiles array. This reduced runtime dramatically for all fragmentation.
This commit is contained in:
parent
aef896cc21
commit
58a55313cd
@ -1,15 +1,33 @@
|
||||
class ACE_Settings {
|
||||
class GVAR(enabled) {
|
||||
class GVAR(Enabled) {
|
||||
displayName = "$STR_ACE_frag_EnableFrag";
|
||||
description = "$STR_ACE_frag_EnableFrag_Desc";
|
||||
typeName = "BOOL";
|
||||
value = 1;
|
||||
};
|
||||
|
||||
class GVAR(spallEnabled) {
|
||||
class GVAR(SpallEnabled) {
|
||||
displayName = "$STR_ACE_frag_EnableSpall";
|
||||
description = "$STR_ACE_frag_EnableSpall_Desc";
|
||||
typeName = "BOOL";
|
||||
value = 1;
|
||||
};
|
||||
class GVAR(maxTrack) {
|
||||
displayName = "$STR_ACE_frag_MaxTrack";
|
||||
description = "$STR_ACE_frag_MaxTrack_Desc";
|
||||
typeName = "SCALAR";
|
||||
value = 500;
|
||||
};
|
||||
class GVAR(MaxTrackPerFrame) {
|
||||
displayName = "$STR_ACE_frag_MaxTrackPerFrame";
|
||||
description = "$STR_ACE_frag_MaxTrackPerFrame_Desc";
|
||||
typeName = "SCALAR";
|
||||
value = 50;
|
||||
};
|
||||
|
||||
class GVAR(EnableDebugTrace) {
|
||||
displayName = "$STR_ACE_frag_EnableDebugTrace";
|
||||
description = "$STR_ACE_frag_EnableDebugTrace_Desc";
|
||||
typeName = "BOOL";
|
||||
value = 0;
|
||||
};
|
||||
};
|
||||
|
@ -9,8 +9,6 @@ class CfgAmmo {
|
||||
// GVAR(skip) = 1;
|
||||
//};
|
||||
|
||||
#include "CfgAmmoReflections.hpp"
|
||||
|
||||
class Bo_GBU12_LGB;
|
||||
class ACE_GBU12 : Bo_GBU12_LGB {
|
||||
GVAR(enabled) = 1;
|
||||
@ -473,4 +471,6 @@ class CfgAmmo {
|
||||
class ACE_frag_spall_huge: ACE_frag_huge {
|
||||
timeToLive = 0.3;
|
||||
};
|
||||
|
||||
#include "CfgAmmoReflections.hpp"
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
//CfgAmmoReflections.hpp
|
||||
|
||||
#define ACE_EXPLOSION_REFLECTION(range, hit) class ace_explosion_reflection_##range##_##hit : ace_explosion_reflection_base { indirectHitRange = range; indirectHit = hit; dangerRadiusHit = range*3; suppressionRadiusHit = range*2; };
|
||||
class Sh_120mm_HE;
|
||||
class ace_explosion_reflection_base : Sh_120mm_HE {
|
||||
CraterWaterEffects = "";
|
||||
CraterEffects = "";
|
||||
|
@ -1,5 +1,10 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
if(GVAR(EnableDebugTrace) && !isMultiplayer) then {
|
||||
GVAR(traceFrags) = true;
|
||||
GVAR(autoTrace) = true;
|
||||
};
|
||||
|
||||
if(isServer) then {
|
||||
[QGVAR(frag_eh), { _this call FUNC(frago); }] call ace_common_fnc_addEventHandler;
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ GVAR(TOTALFRAGS) = 0;
|
||||
GVAR(spallHPData) = [];
|
||||
GVAR(spallIsTrackingCount) = 0;
|
||||
|
||||
GVAR(autoTrace) = true;
|
||||
GVAR(autoTrace) = false;
|
||||
GVAR(traceID) = -1;
|
||||
GVAR(traces) = [];
|
||||
GVAR(tracesStarted) = false;
|
||||
@ -43,6 +43,7 @@ PREP(doExplosions);
|
||||
PREP(doReflections);
|
||||
|
||||
|
||||
GVAR(lastIterationIndex) = 0;
|
||||
GVAR(objects) = [];
|
||||
GVAR(objectTypes) = [];
|
||||
GVAR(arguments) = [];
|
||||
|
@ -1,20 +1,21 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_enabled", "_gun", "_type", "_round", "_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"];
|
||||
private ["_enabled","_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"];
|
||||
PARAMS_3(_gun,_type,_round);
|
||||
|
||||
if (!GVAR(enabled)) exitWith {};
|
||||
|
||||
_gun = _this select 0;
|
||||
_type = _this select 1;
|
||||
_round = _this select 2;
|
||||
|
||||
_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled));
|
||||
if(_enabled < 1) exitWith {};
|
||||
//_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled));
|
||||
//if(_enabled < 1) exitWith {};
|
||||
|
||||
if(_round in GVAR(blackList)) exitWith {
|
||||
GVAR(blackList) = GVAR(blackList) - [_round];
|
||||
};
|
||||
|
||||
// Exit on max track
|
||||
if( (count GVAR(objects)) > GVAR(MaxTrack)) exitWith { };
|
||||
|
||||
_doFragTrack = false;
|
||||
if(_gun == ACE_player) then {
|
||||
_doFragTrack = true;
|
||||
@ -27,7 +28,7 @@ if(_gun == ACE_player) then {
|
||||
};
|
||||
};
|
||||
};
|
||||
if(GVAR(spallEnabled)) then {
|
||||
if(GVAR(SpallEnabled)) then {
|
||||
if(GVAR(spallIsTrackingCount) <= 0) then {
|
||||
GVAR(spallHPData) = [];
|
||||
};
|
||||
@ -40,12 +41,15 @@ if(GVAR(spallEnabled)) then {
|
||||
};
|
||||
// ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)];
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack);
|
||||
#endif
|
||||
if(GVAR(autoTrace)) then {
|
||||
[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack);
|
||||
};
|
||||
|
||||
// We only do the single track object check here.
|
||||
if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then {
|
||||
// We should do an {!(_round in GVAR(objects))}
|
||||
// But we leave that out here for optimization. So this cannot be a framework function
|
||||
// Otherwise, it should only be added once and from the FiredEH
|
||||
if(_doFragTrack && alive _round) then {
|
||||
_spallTrack = [];
|
||||
_spallTrackID = [];
|
||||
|
||||
@ -57,12 +61,12 @@ if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then {
|
||||
(getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force))),
|
||||
(getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")))))
|
||||
];
|
||||
|
||||
TRACE_1("Initializing track", _round);
|
||||
GVAR(objects) pushBack _round;
|
||||
GVAR(arguments) pushBack _args;
|
||||
|
||||
if(_doSpall) then {
|
||||
[_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack);
|
||||
[_round, 1, _spallTrack, _spallTrackID] call FUNC(spallTrack);
|
||||
};
|
||||
// ACE_player sideChat "WTF2";
|
||||
};
|
||||
|
@ -1,14 +1,10 @@
|
||||
//fnc_doSpall.sqf
|
||||
#include "script_component.hpp"
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
GVAR(traceFrags) = true;
|
||||
#endif
|
||||
// ACE_player sideChat "WAAAAAAAAAAAAAAAAAAAAA";
|
||||
|
||||
private ["_params", "_hitData", "_initialData", "_hpData", "_object", "_foundObjects", "_index", "_foundObjecsts", "_roundType", "_round", "_caliber", "_explosive", "_idh", "_alive", "_exit", "_vm", "_velocity", "_oldVelocity", "_curVelocity", "_diff", "_polar", "_unitDir", "_spallPos", "_pos1", "_i", "_pos2", "_blah", "_data", "_spallPolar", "_warn", "_c", "_m", "_k", "_gC", "_fragPower", "_fragTypes", "_spread", "_spallCount", "_elev", "_dir", "_vel", "_spallFragVect", "_fragType", "_fragment", "_pos"];
|
||||
|
||||
_params = _this select 0;
|
||||
[(_this select 1)] call cba_fnc_removePerFrameHandler;
|
||||
_hitData = _params select 0;
|
||||
_initialData = GVAR(spallHPData) select (_hitData select 0);
|
||||
_hpData = (_hitData select 1) select (_params select 1);
|
||||
|
@ -163,11 +163,8 @@ if(_isArmed && (count _objects) > 0) then {
|
||||
_fragObj setPosASL _lastPos;
|
||||
_fragObj setVectorDir _vec;
|
||||
_fragObj setVelocity _vel;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
|
||||
GVAR(traceFrags) = true;
|
||||
#endif
|
||||
if(GVAR(traceFrags)) then {
|
||||
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
|
||||
[ACE_player, _fragObj, [1,0,0,1]] call FUNC(addTrack);
|
||||
};
|
||||
_fragCount = _fragCount + 1;
|
||||
@ -200,11 +197,9 @@ if(_isArmed && (count _objects) > 0) then {
|
||||
_fragObj setPosASL _lastPos;
|
||||
_fragObj setVectorDir _vec;
|
||||
_fragObj setVelocity _vel;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
|
||||
GVAR(traceFrags) = true;
|
||||
#endif
|
||||
|
||||
if(GVAR(traceFrags)) then {
|
||||
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
|
||||
[ACE_player, _fragObj, [1,0.5,0,1]] call FUNC(addTrack);
|
||||
};
|
||||
_fragCount = _fragCount + 1;
|
||||
|
@ -9,36 +9,48 @@
|
||||
* Return Value:
|
||||
* None
|
||||
*/
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
PARAMS_2(_pfhArgs,_handle);
|
||||
//PARAMS_2(_pfhArgs,_handle);
|
||||
|
||||
if (!GVAR(enabled)) exitWith {};
|
||||
|
||||
private["_gcIndex"];
|
||||
_gcIndex = [];
|
||||
{
|
||||
|
||||
_iter = 0;
|
||||
while { (count GVAR(objects)) > 0 && { _iter < GVAR(MaxTrackPerFrame) } } do {
|
||||
private["_object", "_args"];
|
||||
_object = _x;
|
||||
if(GVAR(lastIterationIndex) >= (count GVAR(objects))) then {
|
||||
GVAR(lastIterationIndex) = 0;
|
||||
};
|
||||
_object = GVAR(objects) select GVAR(lastIterationIndex);
|
||||
|
||||
if(!isNil "_object") then {
|
||||
if(isNull _object) then {
|
||||
_gcIndex pushBack _forEachIndex;
|
||||
_gcIndex pushBack GVAR(lastIterationIndex);
|
||||
} else {
|
||||
_args = GVAR(arguments) select _forEachIndex;
|
||||
_args = GVAR(arguments) select GVAR(lastIterationIndex);
|
||||
|
||||
_args call FUNC(pfhRound);
|
||||
};
|
||||
|
||||
if(!alive _object) then {
|
||||
_gcIndex pushBack _forEachIndex;
|
||||
if(!(_args call FUNC(pfhRound))) then {
|
||||
_gcIndex pushBack GVAR(lastIterationIndex); // Add it to the GC if it returns false
|
||||
};
|
||||
// If its not alive anymore, remove it from the queue, it already ran once on dead
|
||||
if(!alive _object) then {
|
||||
_gcIndex pushBack GVAR(lastIterationIndex);
|
||||
};
|
||||
};
|
||||
};
|
||||
} forEach GVAR(objects);
|
||||
_iter = _iter + 1;
|
||||
GVAR(lastIterationIndex) = GVAR(lastIterationIndex) + 1;
|
||||
};
|
||||
|
||||
// clean up dead object references
|
||||
private["_deletionCount", "_deleteIndex"];
|
||||
_deletionCount = 0;
|
||||
{
|
||||
_deleteIndex = _gcIndex - _deletionCount;
|
||||
TRACE_1("GC Projectile", _x);
|
||||
_deleteIndex = _x - _deletionCount;
|
||||
GVAR(objects) deleteAt _deleteIndex;
|
||||
GVAR(arguments) deleteAt _deleteIndex;
|
||||
|
||||
|
@ -1,25 +1,28 @@
|
||||
#include "script_component.hpp"
|
||||
private ["_params", "_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
|
||||
_params = _this select 0;
|
||||
_round = _params select 0;
|
||||
_lastPos = _params select 1;
|
||||
_lastVel = _params select 2;
|
||||
_type = _params select 3;
|
||||
_time = _params select 4;
|
||||
_doSpall = _params select 6;
|
||||
_spallTrack = _params select 7;
|
||||
_foundObjectHPIds = _params select 8;
|
||||
_skip = _params select 9;
|
||||
_explosive = _params select 10;
|
||||
_indirectRange = _params select 11;
|
||||
_force = _params select 12;
|
||||
_fragPower = _params select 13;
|
||||
private ["_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
|
||||
_round = _this select 0;
|
||||
_lastPos = _this select 1;
|
||||
_lastVel = _this select 2;
|
||||
_type = _this select 3;
|
||||
_time = _this select 4;
|
||||
_doSpall = _this select 6;
|
||||
_spallTrack = _this select 7;
|
||||
_foundObjectHPIds = _this select 8;
|
||||
_skip = _this select 9;
|
||||
_explosive = _this select 10;
|
||||
_indirectRange = _this select 11;
|
||||
_force = _this select 12;
|
||||
_fragPower = _this select 13;
|
||||
|
||||
if(_round in GVAR(blackList)) exitWith {
|
||||
false
|
||||
};
|
||||
|
||||
if (!alive _round) then {
|
||||
if(_time != time && {!(_round in GVAR(blackList))}) then {
|
||||
if(_time != time) then {
|
||||
if(_skip == 0) then {
|
||||
if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then {
|
||||
[QGVAR(frag_eh), _params] call ace_common_fnc_serverEvent;
|
||||
[QGVAR(frag_eh), _this] call ace_common_fnc_serverEvent;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -33,13 +36,14 @@ if (!alive _round) then {
|
||||
} forEach _spallTrack;
|
||||
};
|
||||
} else {
|
||||
if(_round in GVAR(blackList)) exitWith {
|
||||
[_round] call FUNC(removePfhRound);
|
||||
};
|
||||
|
||||
|
||||
_params set[1, (getPosASL _round)];
|
||||
_params set[2, (velocity _round)];
|
||||
if(_doSpall) then {
|
||||
[_round, 1, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack);
|
||||
private["_scale"];
|
||||
_scale = ( (count GVAR(objects)) / GVAR(MaxTrackPerFrame) ) max 0.1;
|
||||
[_round, _scale, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack);
|
||||
};
|
||||
};
|
||||
|
||||
true
|
@ -22,7 +22,7 @@ if (count _intersectsWith > 0) then {
|
||||
if(!(_x in _foundObjects)) then {
|
||||
// diag_log text format["Adding HP: %1", _x];
|
||||
_index = (count GVAR(spallHPData));
|
||||
_hpId = _x addEventHandler ["hitPart", format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]];
|
||||
_hpId = _x addEventHandler ["hitPart", compile format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]];
|
||||
_foundObjects set[(count _foundObjects), _x];
|
||||
_foundObjectHPIds set[(count _foundObjectHPIds), _hpId];
|
||||
_data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds];
|
||||
|
@ -3,19 +3,33 @@
|
||||
<Package name="Frag">
|
||||
<Key ID="STR_ACE_frag_EnableFrag">
|
||||
<English>Fragmentation Simulation</English>
|
||||
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_EnableFrag_Desc">
|
||||
<English>Enable the ACE Fragmentation Simulation</English>
|
||||
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_EnableSpall">
|
||||
<English>Spalling Simulation</English>
|
||||
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_EnableSpall_Desc">
|
||||
<English>Enable the ACE Spalling Simulation</English>
|
||||
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_MaxTrack">
|
||||
<English>Maximum Projectiles Tracked</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_MaxTrack_Desc">
|
||||
<English>This setting controls the maximum amount of projectiles the fragmentation & spalling system will track at any given time. If more projectiles are fired, they will not be tracked. Lower this setting if you do not want FPS drops at high-count projectile scenarios ( >200 rounds in the air at once)</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_MaxTrackPerFrame">
|
||||
<English>Maximum Projectiles Per Frame</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_MaxTrackPerFrame_Desc">
|
||||
<English>The number of spall track calculations to perform in any given frame. This helps spread the FPS impact of tracking spall rounds across multiple frames, limiting its impact even further.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_EnableDebugTrace">
|
||||
<English>(SP Only) Frag/Spall Debug Tracing</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_frag_EnableDebugTrace_Desc">
|
||||
<English>(SP Only) Requires a mission/editor restart. Enables visual tracing of fragmentation and spalling rounds in SP game mode only.</English>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user