diff --git a/addons/repair/functions/fnc_getSelectionsToIgnore.sqf b/addons/repair/functions/fnc_getSelectionsToIgnore.sqf index f66d0f212c..821e23a1f8 100644 --- a/addons/repair/functions/fnc_getSelectionsToIgnore.sqf +++ b/addons/repair/functions/fnc_getSelectionsToIgnore.sqf @@ -1,13 +1,21 @@ #include "..\script_component.hpp" /* * Author: commy2, kymckay, LinkIsGrim - * Get list of vehicle hitpoints to ignore + * Get list of vehicle hitpoints to ignore and depends hitpoints * * Arguments: * 0: Vehicle * * Return Value: - * HitPoints to ignore + * 0: HitPoint indexes to ignore + * 1: Depends hitpoints with parents + * : Depends Index + * : Parent Index + * 2: Depends hitpoints with complex/multiple parents + * : Depends Index + * : Parent + * 0: Parent Hitpoint + * 1: Individual, valid parent hitpoints * * Example: * [vehicle] call ace_repair_fnc_getSelectionsToIgnore @@ -26,7 +34,7 @@ if (_type in _initializedClasses) exitWith { }; //you return different amount of values each time private _vehCfg = configOf _vehicle; -private _hitpointGroups = getArray (_vehCfg >> QGVAR(hitpointGroups)); +private _hitPointGroups = getArray (_vehCfg >> QGVAR(hitpointGroups)); private _turretPaths = ((fullCrew [_vehicle, "gunner", true]) + (fullCrew [_vehicle, "commander", true])) apply {_x # 3}; (getAllHitPointsDamage _vehicle) params [["_hitPoints", []], ["_hitSelections", []]]; @@ -34,47 +42,39 @@ private _turretPaths = ((fullCrew [_vehicle, "gunner", true]) + (fullCrew [_vehi ([_vehicle] call FUNC(getWheelHitPointsWithSelections)) params ["_wheelHitPoints", "_wheelHitSelections"]; private _indexesToIgnore = []; -private _dependsIndexMap = createHashMap; private _processedSelections = []; +private _dependsIndexMap = createHashMap; +private _complexDependsMap = createHashMap; { private _selection = _x; - private _hitpoint = toLower (_hitPoints select _forEachIndex); - private _isWheelOrTrack = _selection in _wheelHitSelections || {_hitpoint in _wheelHitPoints} || {_hitpoint in TRACK_HITPOINTS}; + private _hitPoint = toLower (_hitPoints select _forEachIndex); + private _isWheelOrTrack = _selection in _wheelHitSelections || {_hitPoint in _wheelHitPoints} || {_hitPoint in TRACK_HITPOINTS}; - if (_hitpoint isEqualTo "") then { // skip empty hitpoint + if (_hitPoint isEqualTo "") then { // skip empty hitpoint _indexesToIgnore pushBack _forEachIndex; continue }; - if (_isWheelOrTrack && {_selection in _processedSelections || {_selection isEqualTo ""}}) then { // skip duplicate or empty selection wheel/track - TRACE_3("Skipping duplicate Wheel/Track or empty selection",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping duplicate wheel, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ + if (_isWheelOrTrack && {_selection in _processedSelections || {_selection isEqualTo ""}}) then { + TRACE_3("Skipping duplicate Wheel/Track or empty selection",_hitPoint,_forEachIndex,_selection); _indexesToIgnore pushBack _forEachIndex; _processedSelections pushBack _selection; continue }; - if ("glass" in _hitpoint) then { // skip glass - TRACE_3("Skipping glass",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping glass, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ + if ("glass" in _hitPoint) then { + TRACE_3("Skipping glass",_hitPoint,_forEachIndex,_selection); _indexesToIgnore pushBack _forEachIndex; _processedSelections pushBack _selection; continue }; - if (_hitpoint select [0,7] isEqualTo "hitera_" || {_hitpoint select [0,4] isEqualTo "era_"} - || {_hitpoint select [0,8] isEqualTo "hitslat_"} || {_hitpoint select [0,5] isEqualTo "slat_"} - || {_hitpoint select [0,9] isEqualTo "sideskirt"} || {_hitpoint select [0,6] isEqualTo "armor_"} - || {_hitpoint select [0,3] isEqualTo "mud"}) then { // skip era/slat/sideskirt/armor/mudguards - TRACE_3("Skipping ERA/Slat/Sideskirt/Armor/Mudguard HitPoint",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping ERA/SLAT, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ + if (_hitPoint select [0,7] isEqualTo "hitera_" || {_hitPoint select [0,4] isEqualTo "era_"} + || {_hitPoint select [0,8] isEqualTo "hitslat_"} || {_hitPoint select [0,5] isEqualTo "slat_"} + || {_hitPoint select [0,9] isEqualTo "sideskirt"} || {_hitPoint select [0,6] isEqualTo "armor_"} + || {_hitPoint select [0,3] isEqualTo "mud"} || {_hitPoint select [0,9] isEqualTo "smoketube"}) then { + TRACE_3("Skipping ERA/Slat/Sideskirt/Armor/Mudguard/Smoketube HitPoint",_hitPoint,_forEachIndex,_selection); _indexesToIgnore pushBack _forEachIndex; _processedSelections pushBack _selection; continue @@ -83,75 +83,88 @@ private _processedSelections = []; private _armorComponent = ""; if (_selection == "") then { // some hitpoints have empty selection but defined armor component (mostly RHS) { - private _turretHitpointCfg = ([_vehCfg, _x] call CBA_fnc_getTurret) >> "HitPoints"; - private _hitpointsCfg = "configName _x == _hitpoint" configClasses _turretHitpointCfg; - if (_hitpointsCfg isNotEqualTo []) exitWith { - TRACE_2("turret hitpoint configFound",_hitpoint,_x); - _hitpointsCfg = _hitpointsCfg # 0; - // only do turret hitpoints and stuff linked to visuals + private _turretHitPointCfg = ([_vehCfg, _x] call CBA_fnc_getTurret) >> "HitPoints"; + private _hitPointsCfg = "configName _x == _hitPoint" configClasses _turretHitPointCfg; + if (_hitPointsCfg isNotEqualTo []) exitWith { + TRACE_2("turret hitpoint config found",_hitPoint,_x); + _hitPointsCfg = _hitPointsCfg # 0; + // only do turret hitpoints and stuff linked to visuals if ( - (_hitpoint in ["hitturret", "hitgun"]) || - {(getNumber (_hitpointsCfg >> "isGun")) == 1} || - {(getNumber (_hitpointsCfg >> "isTurret")) == 1} || - {(getText (_hitpointsCfg >> "visual")) != ""} + (_hitPoint in ["hitturret", "hitgun"]) || + {(getNumber (_hitPointsCfg >> "isGun")) == 1} || + {(getNumber (_hitPointsCfg >> "isTurret")) == 1} || + {(getText (_hitPointsCfg >> "visual")) != ""} ) then { - _armorComponent = getText (_hitpointsCfg >> "armorComponent"); + _armorComponent = getText (_hitPointsCfg >> "armorComponent"); }; }; } forEach _turretPaths; if (_armorComponent == "") then { - private _hitpointsCfg = "configName _x == _hitpoint" configClasses (_vehCfg >> "HitPoints"); - if (_hitpointsCfg isNotEqualTo []) then { - _hitpointsCfg = _hitpointsCfg # 0; + private _hitPointsCfg = "configName _x == _hitPoint" configClasses (_vehCfg >> "HitPoints"); + if (_hitPointsCfg isNotEqualTo []) then { + _hitPointsCfg = _hitPointsCfg # 0; if ( - (getNumber (_hitpointsCfg >> "isGun")) == 1 || - {(getNumber (_hitpointsCfg >> "isTurret")) == 1} || - {(getText (_hitpointsCfg >> "visual")) != ""} + (getNumber (_hitPointsCfg >> "isGun")) == 1 || + {(getNumber (_hitPointsCfg >> "isTurret")) == 1} || + {(getText (_hitPointsCfg >> "visual")) != ""} ) then { - _armorComponent = getText (_hitpointsCfg >> "armorComponent"); + _armorComponent = getText (_hitPointsCfg >> "armorComponent"); }; }; }; }; if ((_selection == "") && {_armorComponent == ""}) then { - TRACE_3("Skipping no selection OR armor component",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping no selection OR armor component, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ + TRACE_3("Skipping no selection OR armor component",_hitPoint,_forEachIndex,_selection); _indexesToIgnore pushBack _forEachIndex; _processedSelections pushBack _selection; continue }; - if (!(getText (_vehCfg >> "HitPoints" >> _hitpoint >> "depends") in ["", "0"])) then { // skip depends hitpoints, should be normalized by engine - TRACE_3("Skipping depends hitpoint",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping depends hitpoint, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ - private _parentHitpoint = getText (_vehCfg >> "HitPoints" >> _hitpoint >> "depends"); - _parentHitpoint = toLower _parentHitpoint; - private _parentHitpointIndex = _hitPoints findIf {_x == _parentHitpoint}; + if (!(getText (_vehCfg >> "HitPoints" >> _hitPoint >> "depends") in ["", "0"])) then { + // Caches depends hitpoints and their parents + private _parentHitPoint = getText (_vehCfg >> "HitPoints" >> _hitPoint >> "depends"); + _parentHitPoint = toLower _parentHitPoint; + private _parentHitPointIndex = _hitPoints findIf {_x == _parentHitPoint}; - if (_parentHitpointIndex != -1) then { - _dependsIndexMap set [_forEachIndex, _parentHitpointIndex]; - } else { // multiple parents or incorrect parent - _indexesToIgnore pushBack _forEachIndex; - private _groupIndex = _hitpointGroups findIf {_x # 0 == _hitpoint}; - if (_groupIndex != -1) then { - ERROR_2("[%1] hitpoint [%2] is both a group-parent and an ignored depends and will be unrepairable",_type,_hitpoint); - ERROR_1("group: %1",_hitpointGroups # _groupIndex); + if (_parentHitPointIndex != -1) then { + _dependsIndexMap set [_forEachIndex, _parentHitPointIndex]; + TRACE_3("Depends hitpoint and parent index",_hitPoint,_forEachIndex,_parentHitPoint); + } else { + // Multiple parents or broken parents + _indexesToIgnore pushBack _forEachIndex; + private _parentHitPoints = _parentHitPoint splitString "+*() "; + _parentHitPoints deleteAt (_parentHitPoints findIf {!(_x regexMatch "[a-z]")}); + + private _validComplexHitPoint = true; + { + private _currentHitPoint = _x; + private _hitPointsCfg = "configName _x == _currentHitPoint" configClasses (_vehCfg >> "HitPoints"); + if (_hitPointsCfg isEqualTo []) then { + _validComplexHitPoint = false; + break; + }; + } forEach _parentHitPoints; + + if (_validComplexHitPoint) then { + TRACE_3("Skipping depends and setting complex parent",_hitPoint,_forEachIndex,_parentHitPoint); + _complexDependsMap set [_forEachIndex, [_parentHitPoint, _parentHitPoints]]; + _dependsIndexMap set [_forEachIndex, _parentHitPointIndex]; + } else { + TRACE_4("Skipping depends with broken complex parent",_hitPoint,_forEachIndex,_parentHitPoint,_parentHitPoints); + private _groupIndex = _hitPointGroups findIf {_x # 0 == _hitPoint}; + if (_groupIndex != -1) then { + ERROR_2("[%1] hitpoint [%2] is both a group-parent and an ignored depends and will be unrepairable",_type,_hitPoint); + ERROR_1("group: %1",_hitPointGroups # _groupIndex); + }; }; }; _processedSelections pushBack _selection; continue }; - if (ANY_OF(_hitpointGroups, ANY_OF(_x select 1, _x == _hitpoint))) then { // skip child hitpoints - TRACE_3("Skipping child hitpoint",_hitpoint,_forEachIndex,_selection); - /*#ifdef DEBUG_MODE_FULL - systemChat format ["Skipping child hitpoint, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection]; - #endif*/ + if (ANY_OF(_hitPointGroups, ANY_OF(_x select 1, _x == _hitPoint))) then { + TRACE_3("Skipping child hitpoint",_hitPoint,_forEachIndex,_selection); _indexesToIgnore pushBack _forEachIndex; _processedSelections pushBack _selection; continue @@ -160,7 +173,7 @@ private _processedSelections = []; _processedSelections pushBack _selection; } forEach _hitSelections; -_initializedClasses set [_type, [_indexesToIgnore, _dependsIndexMap]]; +_initializedClasses set [_type, [_indexesToIgnore, _dependsIndexMap, _complexDependsMap]]; SETMVAR(GVAR(ignoredAndDependsInitializedClasses),_initializedClasses); -[_indexesToIgnore, _dependsIndexMap] +[_indexesToIgnore, _dependsIndexMap, _complexDependsMap] diff --git a/addons/repair/functions/fnc_normalizeHitPoints.sqf b/addons/repair/functions/fnc_normalizeHitPoints.sqf index 16546ac475..a6ef6bf495 100644 --- a/addons/repair/functions/fnc_normalizeHitPoints.sqf +++ b/addons/repair/functions/fnc_normalizeHitPoints.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: commy2 - * Used to normalize dependant hitpoints. May overwrite some global variables that are named like hitpoints or "Total" though... + * Used to normalize depends hitpoints - sets their damage to damage of parent or parents. * * Arguments: * 0: Local Vehicle @@ -16,16 +16,25 @@ */ params ["_vehicle"]; -TRACE_2("params",_vehicle, typeOf _vehicle); +TRACE_2("params",_vehicle,typeOf _vehicle); // Can't execute all commands if the vehicle isn't local, exit if that's so if !(local _vehicle) exitWith {ERROR_1("Vehicle Not Local %1", _vehicle);}; -([_vehicle] call FUNC(getSelectionsToIgnore)) params ["", "_dependsIndexMap"]; +([_vehicle] call FUNC(getSelectionsToIgnore)) params ["", "_dependsIndexMap", "_complexDependsMap"]; -// apply normalized damage to all depends hitpoints -{ +{ // apply normalized damage to all depends hitpoints private _damage = _vehicle getHitIndex _y; + if (_y == -1) then { // handle complex depends parents + (_complexDependsMap get _x) params ["_parentHitPointScript", "_parentHitPointArray"]; + { + private _hitPoint = _parentHitPointArray select _forEachIndex; + private _hitPointDamage = str (_vehicle getHitPointDamage _hitPoint); + _parentHitPointScript = [_parentHitPointScript, _hitPoint, _hitPointDamage] call CBA_fnc_replace; + } forEach _parentHitPointArray; + TRACE_1("complex script",_parentHitPointScript); + _damage = call compile _parentHitPointScript; + }; TRACE_2("setting depends hitpoint",_x,_damage); _vehicle setHitIndex [_x, _damage]; } forEach _dependsIndexMap;