diff --git a/.travis.yml b/.travis.yml index 388b1f114f..0aadd9cd0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ before_script: - pip install pygithub3 script: - python3 tools/deploy.py + - python3 tools/sqf_validator.py env: global: - secure: "KcJQbknBOdC5lA4nFGKPXVRVIGLDXDRzC8XkHuXJCE9pIR/wbxbkvx8fHKcC6SC9eHgzneC3+o4m4+CjIbVvIwDgslRbJ8Y59i90ncONmdoRx1HUYHwuYWVZm9HJFjCsIbrEqhSyyKS+PB3WZVOLbErtNHsgS8f43PTh5Ujg7Vg=" diff --git a/addons/captives/XEH_postInit.sqf b/addons/captives/XEH_postInit.sqf index fec6e84fbe..26f84e6bd9 100644 --- a/addons/captives/XEH_postInit.sqf +++ b/addons/captives/XEH_postInit.sqf @@ -26,7 +26,7 @@ if (isServer) then { ["SetHandcuffed", {_this call FUNC(setHandcuffed)}] call EFUNC(common,addEventHandler); ["SetSurrendered", {_this call FUNC(setSurrendered)}] call EFUNC(common,addEventHandler); -//Medical Integration Events??? +//Medical Integration Events ["medical_onUnconscious", {_this call ACE_Captives_fnc_handleOnUnconscious}] call EFUNC(common,addEventHandler); if (!hasInterface) exitWith {}; diff --git a/addons/captives/functions/fnc_setHandcuffed.sqf b/addons/captives/functions/fnc_setHandcuffed.sqf index a8c8e02fd4..00122862eb 100644 --- a/addons/captives/functions/fnc_setHandcuffed.sqf +++ b/addons/captives/functions/fnc_setHandcuffed.sqf @@ -109,3 +109,6 @@ if (_state) then { showHUD true; }; }; + +//Global Event after changes: +["CaptiveStatusChanged", [_unit, _state, "SetHandcuffed"]] call EFUNC(common,globalEvent); diff --git a/addons/captives/functions/fnc_setSurrendered.sqf b/addons/captives/functions/fnc_setSurrendered.sqf index dd9ac417c5..cdba47a406 100644 --- a/addons/captives/functions/fnc_setSurrendered.sqf +++ b/addons/captives/functions/fnc_setSurrendered.sqf @@ -101,3 +101,6 @@ if (_state) then { }, 0, [_unit, (ACE_time + 20)]] call CBA_fnc_addPerFrameHandler; }; }; + +//Global Event after changes: +["CaptiveStatusChanged", [_unit, _state, "SetSurrendered"]] call EFUNC(common,globalEvent); diff --git a/addons/cargo/functions/fnc_canLoad.sqf b/addons/cargo/functions/fnc_canLoad.sqf index f5d1304a95..f18ceb5835 100644 --- a/addons/cargo/functions/fnc_canLoad.sqf +++ b/addons/cargo/functions/fnc_canLoad.sqf @@ -31,4 +31,6 @@ if (_nearestVehicle isKindOf "Cargo_Base_F" || isNull _nearestVehicle) then { if (isNull _nearestVehicle) exitWith {false}; +if ((locked _nearestVehicle) >= 2) exitWith {false}; + [_object, _nearestVehicle] call FUNC(canLoadItemIn) diff --git a/addons/common/CfgVehicles.hpp b/addons/common/CfgVehicles.hpp index 69d6f99924..7c5c9295f9 100644 --- a/addons/common/CfgVehicles.hpp +++ b/addons/common/CfgVehicles.hpp @@ -140,4 +140,10 @@ class CfgVehicles { isBicycle = 1; XEH_DISABLED; }; + + class Bag_Base; + class ACE_FakeBackpack: Bag_Base { + scope = 1; + maximumLoad = 1E6; + }; }; diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf index 4bd58ade33..912acce7c4 100644 --- a/addons/common/XEH_postInit.sqf +++ b/addons/common/XEH_postInit.sqf @@ -7,9 +7,9 @@ // PFHs ////////////////////////////////////////////////// -//Singe PFEH to handle execNextFrame and waitAndExec: +//Singe PFEH to handle execNextFrame, waitAndExec and waitUntilAndExec: [{ - private "_entry"; + private ["_entry", "_deleted"]; //Handle the waitAndExec array: while {!(GVAR(waitAndExecArray) isEqualTo []) && {GVAR(waitAndExecArray) select 0 select 0 <= ACE_Time}} do { @@ -27,6 +27,18 @@ GVAR(nextFrameBufferA) = GVAR(nextFrameBufferB); GVAR(nextFrameBufferB) = []; GVAR(nextFrameNo) = diag_frameno + 1; + + //Handle the waitUntilAndExec array: + _deleted = 0; + { + // if condition is satisifed call statement + if ((_x select 2) call (_x select 0)) then { + // make sure to delete the correct handle when multiple conditions are met in one frame + GVAR(waitUntilAndExecArray) deleteAt (_forEachIndex - _deleted); + _deleted = _deleted + 1; + (_x select 2) call (_x select 1); + }; + } forEach GVAR(waitUntilAndExecArray); }, 0, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf index e422206134..ff06c1c3e3 100644 --- a/addons/common/XEH_preInit.sqf +++ b/addons/common/XEH_preInit.sqf @@ -146,8 +146,10 @@ PREP(resetAllDefaults); PREP(restoreVariablesJIP); PREP(runAfterSettingsInit); PREP(sanitizeString); +PREP(selectWeaponMode); PREP(sendRequest); PREP(serverLog); +PREP(setAllGear); PREP(setCaptivityStatus); PREP(setDefinedVariable); PREP(setDisableUserInputStatus); @@ -181,6 +183,7 @@ PREP(unmuteUnit); PREP(useItem); PREP(useMagazine); PREP(waitAndExecute); +PREP(waitUntilAndExecute); PREP(waveHeightAt); PREP(translateToWeaponSpace); @@ -220,6 +223,10 @@ PREP(getDoorTurrets); PREP(getTurretsFFV); PREP(getTurretsOther); +// missing inventory commands +PREP(binocularMagazine); +PREP(removeBinocularMagazine); + // ACE_Debug PREP(exportConfig); PREP(getChildren); @@ -282,11 +289,12 @@ PREP(hashListPush); GVAR(syncedEvents) = HASH_CREATE; -//GVARS for execNextFrame and waitAndExec +//GVARS for execNextFrame and waitAndExec and waitUntilAndExecute GVAR(waitAndExecArray) = []; GVAR(nextFrameNo) = diag_frameno; GVAR(nextFrameBufferA) = []; GVAR(nextFrameBufferB) = []; +GVAR(waitUntilAndExecArray) = []; GVAR(settingsInitFinished) = false; GVAR(runAtSettingsInitialized) = []; diff --git a/addons/common/functions/fnc_binocularMagazine.sqf b/addons/common/functions/fnc_binocularMagazine.sqf new file mode 100644 index 0000000000..f097b90841 --- /dev/null +++ b/addons/common/functions/fnc_binocularMagazine.sqf @@ -0,0 +1,40 @@ +/* + * Author: commy2 + * Returns the magazine of the units rangefinder. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Magazine of the units binocular + * + * Example: + * [player] call ace_common_fnc_binocularMagazine + * + * Public: Yes + * + * Note: Doesn't work on dead units + */ +#include "script_component.hpp" + +params ["_unit"]; + +private ["_binocular", "_muzzle", "_mode", "_magazine"]; + +_binocular = binocular _unit; + +if (_binocular == "") exitWith {""}; + +_muzzle = currentMuzzle _unit; +_mode = currentWeaponMode _unit; + +_unit selectWeapon _binocular; + +// didn't select the binocular (unit probably dead or not local). function won't work. quit with empty string +if (currentWeapon _unit != _binocular) exitWith {""}; + +_magazine = currentMagazine _unit; + +[_unit, _muzzle, _mode] call FUNC(selectWeaponMode); + +_magazine diff --git a/addons/common/functions/fnc_dropBackpack.sqf b/addons/common/functions/fnc_dropBackpack.sqf index fc2b0bba64..26c902a057 100644 --- a/addons/common/functions/fnc_dropBackpack.sqf +++ b/addons/common/functions/fnc_dropBackpack.sqf @@ -18,7 +18,7 @@ private ["_backpackObject", "_holder"]; _backpackObject = backpackContainer _unit; -_unit addBackpack "Bag_Base"; +_unit addBackpack "ACE_FakeBackpack"; removeBackpack _unit; objectParent _backpackObject // return diff --git a/addons/common/functions/fnc_getAllGear.sqf b/addons/common/functions/fnc_getAllGear.sqf index 97b28fddd6..715966b176 100644 --- a/addons/common/functions/fnc_getAllGear.sqf +++ b/addons/common/functions/fnc_getAllGear.sqf @@ -25,6 +25,7 @@ * 16: Handgun Magazines * 17: Assigned Items (map, compass, watch, etc.) * 18: Binoculars + * 19: Binocular Magazine (E.g. Laserbatteries) * * Public: Yes * @@ -44,6 +45,7 @@ if (isNull _unit) exitWith {[ "", ["","","",""], [], "", ["","","",""], [], [], + "", "" ]}; @@ -57,5 +59,6 @@ if (isNull _unit) exitWith {[ secondaryWeapon _unit, secondaryWeaponItems _unit, secondaryWeaponMagazine _unit, handgunWeapon _unit, handgunItems _unit, handgunMagazine _unit, assignedItems _unit, - binocular _unit + binocular _unit, + [_unit] call FUNC(binocularMagazine) ] diff --git a/addons/common/functions/fnc_removeBinocularMagazine.sqf b/addons/common/functions/fnc_removeBinocularMagazine.sqf new file mode 100644 index 0000000000..3d2252390a --- /dev/null +++ b/addons/common/functions/fnc_removeBinocularMagazine.sqf @@ -0,0 +1,30 @@ +/* + * Author: commy2 + * Removes the magazine of the units rangefinder. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call ace_common_fnc_removeBinocularMagazine + * + * Public: Yes + */ +#include "script_component.hpp" + +params ["_unit"]; + +private ["_binocular", "_selectBinocular"]; + +_binocular = binocular _unit; + +_selectBinocular = currentWeapon _unit == _binocular; + +_unit addWeapon _binocular; + +if (_selectBinocular) then { + _unit selectWeapon _binocular; +}; diff --git a/addons/common/functions/fnc_selectWeaponMode.sqf b/addons/common/functions/fnc_selectWeaponMode.sqf new file mode 100644 index 0000000000..f255c63e98 --- /dev/null +++ b/addons/common/functions/fnc_selectWeaponMode.sqf @@ -0,0 +1,31 @@ +/* + * Author: commy2 + * Unit selects given muzzle and weapon mode. + * + * Arguments: + * 0: unit + * 1: weapon or Muzzle + * 2: weapon Mode + * + * Return Value: + * Successful? + * + * Example: + * [player, primaryWeapon player, "FullAuto"] call ace_common_fnc_selectWeaponMode + * + * Public: Yes + */ +#include "script_component.hpp" + +params ["_unit", "_muzzle", "_mode"]; + +local _index = 0; + +while { + _index < 100 && {currentMuzzle _unit != _muzzle || {currentWeaponMode _unit != _mode}} +} do { + _unit action ["SwitchWeapon", _unit, _unit, _index]; + _index = _index + 1; +}; + +_index < 100 // return diff --git a/addons/common/functions/fnc_setAllGear.sqf b/addons/common/functions/fnc_setAllGear.sqf new file mode 100644 index 0000000000..e25045a685 --- /dev/null +++ b/addons/common/functions/fnc_setAllGear.sqf @@ -0,0 +1,172 @@ +/* + * Author: bux578, commy2 + * Applies gear to unit. + * + * Arguments: + * 0: Unit + * 1: All Gear based on return value of ACE_common_fnc_getAllGear + * 2: Remove all attachments from weapons? (default: false) + * 3: Remove all items from prefilled backpacks? (default: false) + * + * Return Value: + * None + * + * Example: + * [player, gear_array, true, true] call ace_common_fnc_setAllGear + * + * Public: Yes + */ +#include "script_component.hpp" + +params ["_unit", "_allGear", ["_clearAttachments", false], ["_clearBackpack", false]]; + +// remove all starting gear of a player +removeAllWeapons _unit; +removeGoggles _unit; +removeHeadgear _unit; +removeVest _unit; +removeUniform _unit; +removeAllAssignedItems _unit; +removeBackpack _unit; + +_allGear params [ + "_headgear", "_goggles", + "_uniform", "_uniformitems", + "_vest", "_vestitems", + "_backpack", "_backpackitems", + "_primaryweapon", "_primaryweaponitems", "_primaryweaponmagazine", + "_secondaryweapon", "_secondaryweaponitems", "_secondaryweaponmagazine", + "_handgunweapon", "_handgunweaponitems", "_handgunweaponmagazine", + "_assigneditems", + "_binocular", + "_binocularmagazine" +]; + +// start restoring the items +if (_headgear != "") then {_unit addHeadgear _headgear}; +if (_goggles != "") then {_unit addGoggles _goggles}; + +// ensure all weapons being loaded +_unit addBackpack "ACE_FakeBackpack"; + +// primaryWeapon +if (_primaryweapon != "") then { + { + _unit addMagazine _x; + false + } count _primaryweaponmagazine; + + _unit addWeapon _primaryweapon; + + if (_clearAttachments) then { + removeAllPrimaryWeaponItems _unit; + }; + + { + if (_x != "") then { + _unit addPrimaryWeaponItem _x; + }; + false + } count _primaryweaponitems; +}; + +// secondaryWeapon +if (_secondaryweapon != "") then { + { + _unit addMagazine _x; + false + } count _secondaryweaponmagazine; + + _unit addWeapon _secondaryweapon; + + if (_clearAttachments) then { + //removeAllSecondaryWeaponItems _unit; + { + _unit removeSecondaryWeaponItem _x; + false + } count secondaryWeaponItems _unit; + }; + + { + if (_x != "") then { + _unit addSecondaryWeaponItem _x; + }; + false + } count _secondaryweaponitems; +}; + +// handgun +if (_handgunweapon != "") then { + { + _unit addMagazine _x; + false + } count _handgunweaponmagazine; + + _unit addWeapon _handgunweapon; + + if (_clearAttachments) then { + removeAllHandgunItems _unit; + }; + + { + if (_x != "") then { + _unit addHandgunItem _x; + }; + false + } count _handgunweaponitems; +}; + +// binocular +_unit addWeapon _binocular; +_unit addMagazine _binocularmagazine; + +// done with dummy backpack. now remove +removeBackpack _unit; + +// uniform +if (_uniform != "") then { + _unit forceAddUniform _uniform; +}; + +{ + _unit addItemToUniform _x; + false +} count _uniformitems; + +// vest +if (_vest != "") then { + _unit addVest _vest; +}; + +{ + _unit addItemToVest _x; + false +} count _vestitems; + +// backpack +if (_backpack != "") then { + _unit addBackpack _backpack; + + if (_clearBackpack) then { + local _backpackObject = unitBackpack _unit; + + clearMagazineCargoGlobal _backpackObject; + clearWeaponCargoGlobal _backpackObject; + clearItemCargoGlobal _backpackObject; + }; + + { + _unit addItemToBackpack _x; + false + } count _backpackitems; +}; + +// assigned items +_assignedItems deleteAt (_assignedItems find _binocular); + +{ + _unit linkItem _x; + false +} count _assignedItems; + +nil diff --git a/addons/common/functions/fnc_waitUntilAndExecute.sqf b/addons/common/functions/fnc_waitUntilAndExecute.sqf new file mode 100644 index 0000000000..6a7867d707 --- /dev/null +++ b/addons/common/functions/fnc_waitUntilAndExecute.sqf @@ -0,0 +1,23 @@ +/* + * Author: joko // Jonas + * Executes a code once with after the Condition is True, using a PFH + * + * Argument: + * 0: Condition + * 1: Code to execute + * 2: Parameters to run the code with + * + * Return value: + * None + * + * Example: + * [{(_this select 0) == vehicle (_this select 0)}, {(_this select 0) setDamage 1;}, [ACE_player]] call ace_common_fnc_waitAndExecute + * + * Public: No + */ +#include "script_component.hpp" + +TRACE_1("Adding",_this); + +GVAR(waitUntilAndExecArray) pushBack _this; +nil diff --git a/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf b/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf index de7cdefd70..c371c8d5a5 100644 --- a/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf +++ b/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf @@ -35,7 +35,7 @@ if (isClass _config && {getText (_config >> "ACE_UsedTube") != ""} && {getNumber _unit removeMagazines _magazine; if (backpack _unit == "") then { - _unit addBackpack "Bag_Base"; + _unit addBackpack "ACE_FakeBackpack"; _unit removeWeapon _launcher; _unit addMagazine _magazine; _didAdd = _magazine in (magazines _unit); diff --git a/addons/interact_menu/XEH_clientInit.sqf b/addons/interact_menu/XEH_clientInit.sqf index 44dfddcadd..59fb01a353 100644 --- a/addons/interact_menu/XEH_clientInit.sqf +++ b/addons/interact_menu/XEH_clientInit.sqf @@ -8,17 +8,19 @@ GVAR(cachedBuildingActionPairs) = []; GVAR(ParsedTextCached) = []; -//Setup text/shadow/size/color settings matrix -[] call FUNC(setupTextColors); ["SettingChanged", { - PARAMS_1(_name); - if (_name in [QGVAR(colorTextMax), QGVAR(colorTextMin), QGVAR(colorShadowMax), QGVAR(colorShadowMin), QGVAR(textSize), QGVAR(shadowSetting)]) then { + params ["_name"]; + if (({_x == _name} count [QGVAR(colorTextMax), QGVAR(colorTextMin), QGVAR(colorShadowMax), QGVAR(colorShadowMin), QGVAR(textSize), QGVAR(shadowSetting)]) == 1) then { [] call FUNC(setupTextColors); }; }] call EFUNC(common,addEventhandler); -// Install the render EH on the main display -addMissionEventHandler ["Draw3D", DFUNC(render)]; +["SettingsInitialized", { + //Setup text/shadow/size/color settings matrix + [] call FUNC(setupTextColors); + // Install the render EH on the main display + addMissionEventHandler ["Draw3D", DFUNC(render)]; +}] call EFUNC(common,addEventHandler); //Add Actions to Houses: ["interactMenuOpened", {_this call FUNC(userActions_addHouseActions)}] call EFUNC(common,addEventHandler); @@ -54,7 +56,7 @@ addMissionEventHandler ["Draw3D", DFUNC(render)]; // If no menu is open just quit if (GVAR(openedMenuType) < 0) exitWith {}; - EXPLODE_2_PVT(_this,_unit,_isUnconscious); + params ["_unit", "_isUnconscious"]; if (_unit != ACE_player || !_isUnconscious) exitWith {}; diff --git a/addons/interact_menu/functions/fnc_render.sqf b/addons/interact_menu/functions/fnc_render.sqf index 55ca280c43..54f197a2a3 100644 --- a/addons/interact_menu/functions/fnc_render.sqf +++ b/addons/interact_menu/functions/fnc_render.sqf @@ -14,13 +14,14 @@ BEGIN_COUNTER(fnc_render); -private ["_cursorPos1", "_cursorPos2", "_p1", "_p2", "_forEachIndex", "_x", "_cursorScreenPos", "_closestDistance", "_closestSelection", "_sPos", "_disSq", "_closest", "_cTime", "_delta", "_foundTarget", "_misMatch", "_hoverPath", "_i", "_actionData", "_player", "_target"]; -_foundTarget = false; -_cursorPos1 = positionCameraToWorld [0, 0, 0]; -_cursorPos2 = positionCameraToWorld [0, 0, 2]; +private ["_cursorPos2", "_p1", "_p2", "_forEachIndex", "_x", "_cursorScreenPos", "_closestDistance", "_closestSelection", "_sPos", "_disSq", "_closest", "_cTime", "_delta", "_foundTarget", "_misMatch", "_hoverPath", "_i", "_actionData", "_player", "_target"]; +_foundTarget = false; if (GVAR(openedMenuType) >= 0) then { + // _cursorPos1 = positionCameraToWorld [0, 0, 2]; + _cursorPos2 = positionCameraToWorld [0, 0, 2]; + // Render all available nearby interactions call FUNC(renderActionPoints); diff --git a/addons/medical/data/littergeneric.p3d b/addons/medical/data/littergeneric.p3d index 4170dd5a41..801a6f5a4f 100644 Binary files a/addons/medical/data/littergeneric.p3d and b/addons/medical/data/littergeneric.p3d differ diff --git a/addons/medical/data/littergeneric_clean.p3d b/addons/medical/data/littergeneric_clean.p3d index 7fa6fb3e91..0ebddf30ca 100644 Binary files a/addons/medical/data/littergeneric_clean.p3d and b/addons/medical/data/littergeneric_clean.p3d differ diff --git a/addons/medical/functions/fnc_actionDiagnose.sqf b/addons/medical/functions/fnc_actionDiagnose.sqf index 5cc0d307da..072b9b1a7e 100644 --- a/addons/medical/functions/fnc_actionDiagnose.sqf +++ b/addons/medical/functions/fnc_actionDiagnose.sqf @@ -35,10 +35,12 @@ if (_target getvariable[QGVAR(hasLostBlood), 0] > 0) then { _genericMessages pushback LSTRING(noBloodloss); }; -if (_target getvariable[QGVAR(hasPain), false]) then { - _genericMessages pushback LSTRING(inPain); -} else { - _genericMessages pushback LSTRING(noPain); +if (alive _target) then { + if (_target getvariable[QGVAR(hasPain), false]) then { + _genericMessages pushback LSTRING(inPain); + } else { + _genericMessages pushback LSTRING(noPain); + }; }; ["displayTextStructured", [_caller], [_genericMessages, 3.0, _caller]] call EFUNC(common,targetEvent); diff --git a/addons/medical/functions/fnc_addToTriageCard.sqf b/addons/medical/functions/fnc_addToTriageCard.sqf index 76d74f85a7..b1df46f751 100644 --- a/addons/medical/functions/fnc_addToTriageCard.sqf +++ b/addons/medical/functions/fnc_addToTriageCard.sqf @@ -29,7 +29,7 @@ _amount = 1; private "_info"; _info = _log select _foreachIndex; _info set [1,(_info select 1) + 1]; - _info set [2, ACE_time]; + _info set [2, ACE_gameTime]; _log set [_foreachIndex, _info]; _amount = (_info select 1); @@ -38,7 +38,7 @@ _amount = 1; } foreach _log; if (!_inList) then { - _log pushback [_newItem, 1, ACE_time]; + _log pushback [_newItem, 1, ACE_gameTime]; }; _unit setvariable [QGVAR(triageCard), _log, true]; ["Medical_onItemAddedToTriageCard", [_unit, _newItem, _amount]] call EFUNC(common,localEvent); diff --git a/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf b/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf index abf09385b2..2ef1174e63 100644 --- a/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf +++ b/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf @@ -94,12 +94,79 @@ if (_impact > 0 && {GVAR(enableAdvancedWounds)}) then { [_target, _impact, _part, _mostEffectiveSpot, _mostEffectiveInjury, _bandage] call FUNC(handleBandageOpening); }; -// If all wounds have been bandaged, we will reset all damage to 0, so the unit is not showing any blood on the model anymore. -if (GVAR(healHitPointAfterAdvBandage) && {{(_x select 2) == _part && {((_x select 4) * (_x select 3)) > 0}}count _openWounds == 0}) then { - _hitSelections = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"]; - _hitPoints = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"]; - _point = _hitPoints select (_hitSelections find _selectionName); - _target setHitPointDamage [_point, 0]; +// If all wounds to a body part have been bandaged, reset damage to that body part to zero +// so that the body part functions normally and blood is removed from the uniform. +// Arma combines left and right arms into a single body part (HitHands), same with left and right legs (HitLegs). +// Arms are actually hands. +if (GVAR(healHitPointAfterAdvBandage)) then { + private["_currentWounds", "_headWounds", "_bodyWounds", "_legsWounds", "_armWounds"]; + + // Get the list of the wounds the target is currently suffering from. + _currentWounds = _target getVariable [QGVAR(openWounds), []]; + + // Tally of unbandaged wounds to each body part. + _headWounds = 0; + _bodyWounds = 0; + _legsWounds = 0; + _armWounds = 0; + + // Loop through all current wounds and add up the number of unbandaged wounds on each body part. + { + _x params ["", "", "_bodyPart", "_numOpenWounds", "_bloodLoss"]; + + // Use switch/case for early termination if wounded limb is found before all six are checked. + // Number of wounds multiplied by blood loss will return zero for a fully + // bandaged body part, not incrementing the wound counter; or it will return + // some other number which will increment the wound counter. + switch (_bodyPart) do { + // Head + case 0: { + _headWounds = _headWounds + (_numOpenWounds * _bloodLoss); + }; + + // Body + case 1: { + _bodyWounds = _bodyWounds + (_numOpenWounds * _bloodLoss); + }; + + // Left Arm + case 2: { + _armWounds = _armWounds + (_numOpenWounds * _bloodLoss); + }; + + // Right Arm + case 3: { + _armWounds = _armWounds + (_numOpenWounds * _bloodLoss); + }; + + // Left Leg + case 4: { + _legsWounds = _legsWounds + (_numOpenWounds * _bloodLoss); + }; + + // Right Leg + case 5: { + _legsWounds = _legsWounds + (_numOpenWounds * _bloodLoss); + }; + }; + } forEach _currentWounds; + + // Any body part that has no wounds is healed to full health + if (_headWounds == 0) then { + _target setHitPointDamage ["hitHead", 0.0]; + }; + + if (_bodyWounds == 0) then { + _target setHitPointDamage ["hitBody", 0.0]; + }; + + if (_armWounds == 0) then { + _target setHitPointDamage ["hitHands", 0.0]; + }; + + if (_legsWounds == 0) then { + _target setHitPointDamage ["hitLegs", 0.0]; + }; }; true; diff --git a/addons/medical_menu/functions/fnc_handleUI_DisplayOptions.sqf b/addons/medical_menu/functions/fnc_handleUI_DisplayOptions.sqf index c65aba5074..dafd72d54d 100644 --- a/addons/medical_menu/functions/fnc_handleUI_DisplayOptions.sqf +++ b/addons/medical_menu/functions/fnc_handleUI_DisplayOptions.sqf @@ -75,7 +75,7 @@ if (_name isEqualTo "triage") exitwith { _message = localize _message; }; }; - _triageCardTexts pushback format["%1x - %2 (%3m)", _amount, _message, round((ACE_time - _time) / 60)]; + _triageCardTexts pushback format["%1x - %2 (%3m)", _amount, _message, round((ACE_gameTime - _time) / 60)]; nil; } count _log; diff --git a/addons/respawn/functions/fnc_handleKilled.sqf b/addons/respawn/functions/fnc_handleKilled.sqf index 200e3c98c8..cd1ad33491 100644 --- a/addons/respawn/functions/fnc_handleKilled.sqf +++ b/addons/respawn/functions/fnc_handleKilled.sqf @@ -24,7 +24,7 @@ if (ACE_player == _unit) then { if (GVAR(SavePreDeathGear)) then { GVAR(unitGear) = [_unit] call EFUNC(common,getAllGear); - GVAR(unitGear) pushBack [currentWeapon _unit, currentMuzzle _unit, currentWeaponMode _unit]; + GVAR(unitGear) append [currentWeapon _unit, currentMuzzle _unit, currentWeaponMode _unit]; }; }; diff --git a/addons/respawn/functions/fnc_moveRallypoint.sqf b/addons/respawn/functions/fnc_moveRallypoint.sqf index bf96905343..fa8aae40a5 100644 --- a/addons/respawn/functions/fnc_moveRallypoint.sqf +++ b/addons/respawn/functions/fnc_moveRallypoint.sqf @@ -46,7 +46,7 @@ _position set [2, 0]; _rallypoint setPosATL _position; _unit reveal _rallypoint; - _rallypoint setVariable [QGVAR(markerDate), format ["%1:%2", date select 3, date select 4], true]; + _rallypoint setVariable [QGVAR(markerDate), [dayTime, "HH:MM"] call BIS_fnc_timeToString, true]; ["rallypointMoved", [_rallypoint, _side, _position]] call EFUNC(common,globalEvent); diff --git a/addons/respawn/functions/fnc_restoreGear.sqf b/addons/respawn/functions/fnc_restoreGear.sqf index e8a512e127..d01e45dd50 100644 --- a/addons/respawn/functions/fnc_restoreGear.sqf +++ b/addons/respawn/functions/fnc_restoreGear.sqf @@ -1,5 +1,5 @@ /* - * Author: bux578 + * Author: bux578, commy2 * Restores previously saved gear. * * Arguments: @@ -10,150 +10,16 @@ * None * * Example: - * [ACE_Player, stored_allGear] call ace_respawn_fnc_restoreGear + * [ACE_Player, stored_allGear, active_weapon_muzzle_and_mode] call ace_respawn_fnc_restoreGear * * Public: No */ #include "script_component.hpp" -params ["_unit", "_allGear"]; +params ["_unit", "_allGear", "_activeWeaponAndMuzzle"]; -// remove all starting gear of a player -removeAllWeapons _unit; -removeGoggles _unit; -removeHeadgear _unit; -removeVest _unit; -removeUniform _unit; -removeAllAssignedItems _unit; -clearAllItemsFromBackpack _unit; -removeBackpack _unit; - -_allGear params [ - "_headgear", "_goggles", - "_uniform", "_uniformitems", - "_vest", "_vestitems", - "_backpack", "_backpackitems", - "_primaryweapon", "_primaryweaponitems", "_primaryweaponmagazine", - "_secondaryweapon", "_secondaryweaponitems", "_secondaryweaponmagazine", - "_handgunweapon", "_handgunweaponitems", "_handgunweaponmagazine", - "_assigneditems", "_binocular", - "_activeWeaponAndMuzzle" -]; - -// start restoring the items -if (_headgear != "") then {_unit addHeadgear _headgear}; -if (_goggles != "") then {_unit addGoggles _goggles}; -if (_uniform != "") then {_unit forceAddUniform _uniform}; -if (_vest != "") then {_unit addVest _vest}; - -{ - _unit addItemToUniform _x; - false -} count _uniformitems; - -{ - _unit addItemToVest _x; - false -} count _vestitems; - -private "_flagRemoveDummyBag"; - -if (format ["%1", _backpack] != "") then { - _unit addBackpack _backpack; - - // make sure the backpack is empty. Some bags are prefilled by config - private "_backpackObject"; - _backpackObject = unitBackpack _unit; - - clearMagazineCargoGlobal _backpackObject; - clearWeaponCargoGlobal _backpackObject; - clearItemCargoGlobal _backpackObject; - - { - _unit addItemToBackpack _x; - false - } count _backpackitems; - - _flagRemoveDummyBag = false; -} else { - // dummy backpack to ensure mags being loaded - _unit addBackpack "Bag_Base"; - - _flagRemoveDummyBag = true; -}; - -// primaryWeapon -if ((_primaryweapon != "") && {_primaryweapon != "ACE_FakePrimaryWeapon"}) then { - { - _unit addMagazine _x; - false - } count _primaryweaponmagazine; - - _unit addWeapon _primaryweapon; - - { - if (_x != "") then { - _unit addPrimaryWeaponItem _x; - }; - false - } count _primaryweaponitems; -}; - -// secondaryWeapon -if (_secondaryweapon != "") then { - { - _unit addMagazine _x; - false - } count _secondaryweaponmagazine; - - _unit addWeapon _secondaryweapon; - - { - if (_x != "") then { - _unit addSecondaryWeaponItem _x; - }; - false - } count _secondaryweaponitems; -}; - -// handgun -if (_handgunweapon != "") then { - { - _unit addMagazine _x; - false - } count _handgunweaponmagazine; - - _unit addWeapon _handgunweapon; - - { - if (_x != "") then { - _unit addHandgunItem _x; - }; - false - } count _handgunweaponitems; -}; - -// remove dummy bagpack -if (_flagRemoveDummyBag) then { - removeBackpack _unit; -}; - -_assignedItems deleteAt (_assignedItems find _binocular); - -// items -{_unit linkItem _x; false} count _assignedItems; - -_unit addWeapon _binocular; - -// reload Laserdesignator -// we assume that if the unit had a Laserdesignator it probably had batteries for it -if ("Laserdesignator" in assignedItems _unit) then { - _unit selectWeapon "Laserdesignator"; - - if (currentMagazine _unit == "") then { - _unit addMagazine "Laserbatteries"; - }; -}; +// restore all gear +[_unit, _allGear, true, true] call EFUNC(common,setAllGear); // restore the last active weapon, muzzle and weaponMode _activeWeaponAndMuzzle params ["_activeWeapon", "_activeMuzzle", "_activeWeaponMode"]; @@ -171,8 +37,7 @@ if ( }; if (currentWeapon _unit != "") then { - private "_index"; - _index = 0; + local _index = 0; while { _index < 100 && {currentWeaponMode _unit != _activeWeaponMode} diff --git a/addons/tacticalladder/data/ace_tacticalladder.p3d b/addons/tacticalladder/data/ace_tacticalladder.p3d index 7bb924ff46..ad1c21c144 100644 Binary files a/addons/tacticalladder/data/ace_tacticalladder.p3d and b/addons/tacticalladder/data/ace_tacticalladder.p3d differ diff --git a/addons/weather/functions/fnc_calculateAirDensity.sqf b/addons/weather/functions/fnc_calculateAirDensity.sqf index 921bff3bf3..f3de65f99d 100644 --- a/addons/weather/functions/fnc_calculateAirDensity.sqf +++ b/addons/weather/functions/fnc_calculateAirDensity.sqf @@ -9,14 +9,14 @@ * 2: relativeHumidity - value between 0.0 and 1.0 * * Return Value: - * 0: density of air - kg * m^(-3) + * density of air - kg * m^(-3) * * Return value: * None */ #include "script_component.hpp" -PARAMS_3(_temperature,_pressure,_relativeHumidity); +params ["_temperature", "_pressure", "_relativeHumidity"]; _pressure = _pressure * 100; // hPa to Pa diff --git a/addons/weather/functions/fnc_calculateBarometricPressure.sqf b/addons/weather/functions/fnc_calculateBarometricPressure.sqf index 869deb93cb..134a741127 100644 --- a/addons/weather/functions/fnc_calculateBarometricPressure.sqf +++ b/addons/weather/functions/fnc_calculateBarometricPressure.sqf @@ -4,10 +4,10 @@ * Calculates the barometric pressure based on altitude and weather * * Arguments: - * 0: altitude - meters + * altitude - meters * * Return Value: - * 0: barometric pressure - hPA + * barometric pressure - hPA * * Return value: * None diff --git a/addons/weather/functions/fnc_calculateDewPoint.sqf b/addons/weather/functions/fnc_calculateDewPoint.sqf index 76656b1f55..cbfc606054 100644 --- a/addons/weather/functions/fnc_calculateDewPoint.sqf +++ b/addons/weather/functions/fnc_calculateDewPoint.sqf @@ -8,7 +8,7 @@ * 2: relativeHumidity - value between 0.0 and 1.0 * * Return Value: - * 0: dew point + * dew point * * Return value: * None @@ -18,7 +18,7 @@ #define __b 17.67 #define __c 243.5 -PARAMS_2(_t,_rh); +params ["_t", "_rh"]; if (_rh == 0) exitWith { CELSIUS(0) }; diff --git a/addons/weather/functions/fnc_calculateHeatIndex.sqf b/addons/weather/functions/fnc_calculateHeatIndex.sqf index 473360c867..057c13d7ad 100644 --- a/addons/weather/functions/fnc_calculateHeatIndex.sqf +++ b/addons/weather/functions/fnc_calculateHeatIndex.sqf @@ -5,10 +5,10 @@ * * Arguments: * 0: temperature - degrees celcius - * 2: relativeHumidity - value between 0.0 and 1.0 + * 1: relativeHumidity - value between 0.0 and 1.0 * * Return Value: - * 0: heat index + * heat index * * Return value: * None @@ -24,7 +24,7 @@ #define __C7 0.000687678 #define __C8 0.000274954 -PARAMS_2(_t,_rh); +params ["_t", "_rh"]; // Source: https://en.wikipedia.org/wiki/Heat_index diff --git a/addons/weather/functions/fnc_calculateRoughnessLength.sqf b/addons/weather/functions/fnc_calculateRoughnessLength.sqf index 08ae44cc74..4fd0d18fb3 100644 --- a/addons/weather/functions/fnc_calculateRoughnessLength.sqf +++ b/addons/weather/functions/fnc_calculateRoughnessLength.sqf @@ -4,10 +4,10 @@ * Calculates the terrain roughness length at a given world position * * Arguments: - * 0: _this - world position + * world position * * Return Value: - * 0: roughness length + * roughness length * * Public: No */ diff --git a/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf b/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf index dd31dfe05e..5e02795d59 100644 --- a/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf +++ b/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf @@ -4,10 +4,10 @@ * Calculates the temperature based on altitude and weather * * Arguments: - * 0: height - meters + * height - meters * * Return Value: - * 0: temperature - degrees celsius + * temperature - degrees celsius * * Return value: * None diff --git a/addons/weather/functions/fnc_calculateWetBulb.sqf b/addons/weather/functions/fnc_calculateWetBulb.sqf index c180cf8384..94e96cd11b 100644 --- a/addons/weather/functions/fnc_calculateWetBulb.sqf +++ b/addons/weather/functions/fnc_calculateWetBulb.sqf @@ -9,7 +9,7 @@ * 2: relativeHumidity - value between 0.0 and 1.0 * * Return Value: - * 0: wet bulb + * wet bulb * * Return value: * None @@ -18,7 +18,7 @@ private ["_es", "_e", "_eDiff", "_eGuessPrev", "_cTempDelta", "_twGuess", "_eguess"]; -PARAMS_3(_temperature,_pressure,_relativeHumidity); +params ["_temperature", "_pressure", "_relativeHumidity"]; // Source: http://cosmoquest.org/forum/showthread.php?155366-Calculating-Wet-Bulb-Temperature-from-RH-amp-Dry-Bulb _es = 6.112 * exp((17.67 * _temperature) / (_temperature + 243.5)); diff --git a/addons/weather/functions/fnc_calculateWindChill.sqf b/addons/weather/functions/fnc_calculateWindChill.sqf index 021d2f8b99..ee3a20283b 100644 --- a/addons/weather/functions/fnc_calculateWindChill.sqf +++ b/addons/weather/functions/fnc_calculateWindChill.sqf @@ -5,16 +5,16 @@ * * Arguments: * 0: temperature - degrees celcius - * 2: wind speed - m/s + * 1: wind speed - m/s * * Return Value: - * 0: wind chill + * wind chill * * Public: No */ #include "script_component.hpp" -PARAMS_2(_t,_v); +params ["_t", "_v"]; // Source: https://en.wikipedia.org/wiki/Wind_chill diff --git a/addons/weather/functions/fnc_calculateWindSpeed.sqf b/addons/weather/functions/fnc_calculateWindSpeed.sqf index d991897b97..87c6c49d42 100644 --- a/addons/weather/functions/fnc_calculateWindSpeed.sqf +++ b/addons/weather/functions/fnc_calculateWindSpeed.sqf @@ -10,24 +10,26 @@ * 3: Account for obstacles * * Return Value: - * 0: wind speed - m/s + * wind speed - m/s * * Public: No */ #include "script_component.hpp" -private ["_windSpeed", "_windDir", "_height", "_newWindSpeed", "_windSource", "_roughnessLength"]; +private ["_fnc_polar2vect", "_windSpeed", "_windDir", "_windDirAdjusted", "_height", "_newWindSpeed", "_windSource", "_roughnessLength"]; -PARAMS_4(_position,_windGradientEnabled,_terrainEffectEnabled,_obstacleEffectEnabled); +params ["_position", "_windGradientEnabled", "_terrainEffectEnabled", "_obstacleEffectEnabled"]; -fnc_polar2vect = { +_fnc_polar2vect = { private ["_mag2D"]; - _mag2D = (_this select 0) * cos((_this select 2)); - [_mag2D * sin((_this select 1)), _mag2D * cos((_this select 1)), (_this select 0) * sin((_this select 2))]; + params ["_x", "_y", "_z"]; + _mag2D = _x * cos(_z); + [_mag2D * sin(_y), _mag2D * cos(_y), _x * sin(_z)]; }; _windSpeed = vectorMagnitude ACE_wind; _windDir = (ACE_wind select 0) atan2 (ACE_wind select 1); +_windDirAdjusted = _windDir + 180; // Wind gradient if (_windGradientEnabled) then { @@ -46,19 +48,19 @@ if (_terrainEffectEnabled) then { if (_windSpeed > 0.05) then { _newWindSpeed = 0; { - _windSource = [100, _windDir + 180, _x] call fnc_polar2vect; + _windSource = [100, _windDirAdjusted, _x] call _fnc_polar2vect; if (!(terrainIntersectASL [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 9) * _windSpeed; }; - _windSource = [100, _windDir + 180 + _x, 0] call fnc_polar2vect; + _windSource = [100, _windDirAdjusted + _x, 0] call _fnc_polar2vect; if (!(terrainIntersectASL [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 9) * _windSpeed; }; - _windSource = [100, _windDir + 180 - _x, 0] call fnc_polar2vect; + _windSource = [100, _windDirAdjusted - _x, 0] call _fnc_polar2vect; if (!(terrainIntersectASL [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 9) * _windSpeed; }; - } forEach [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + } count [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; _windSpeed = _newWindSpeed; }; }; @@ -68,19 +70,19 @@ if (_obstacleEffectEnabled) then { if (_windSpeed > 0.05) then { _newWindSpeed = 0; { - _windSource = [20, _windDir + 180, _x] call fnc_polar2vect; + _windSource = [20, _windDirAdjusted, _x] call _fnc_polar2vect; if (!(lineIntersects [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 2) * _windSpeed; }; - _windSource = [20, _windDir + 180 + _x, 0] call fnc_polar2vect; + _windSource = [20, _windDirAdjusted + _x, 0] call _fnc_polar2vect; if (!(lineIntersects [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 2) * _windSpeed; }; - _windSource = [20, _windDir + 180 - _x, 0] call fnc_polar2vect; + _windSource = [20, _windDirAdjusted - _x, 0] call _fnc_polar2vect; if (!(lineIntersects [_position, _position vectorAdd _windSource])) exitWith { _newWindSpeed = cos(_x * 2) * _windSpeed; }; - } forEach [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]; + } count [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]; _windSpeed = _newWindSpeed; }; }; diff --git a/addons/weather/functions/fnc_getWind.sqf b/addons/weather/functions/fnc_getWind.sqf index 5b123afaa0..7e133896a6 100644 --- a/addons/weather/functions/fnc_getWind.sqf +++ b/addons/weather/functions/fnc_getWind.sqf @@ -11,11 +11,12 @@ */ #include "script_component.hpp" +private ["_periodPercent", "_periodPosition"]; + if (isNil "ACE_WIND_PARAMS") exitWith { [0, 0, 0] }; -EXPLODE_5_PVT(ACE_WIND_PARAMS,_dir,_dirChange,_spd,_spdChange,_period); +ACE_WIND_PARAMS params ["_dir", "_dirChange", "_spd", "_spdChange", "_period"]; -private ["_periodPercent", "_periodPosition"]; _periodPosition = (ACE_time - GVAR(wind_period_start_time)) min _period; _periodPercent = _periodPosition / _period; diff --git a/addons/weather/functions/fnc_initModuleSettings.sqf b/addons/weather/functions/fnc_initModuleSettings.sqf index eb0eaafc31..034612ab58 100644 --- a/addons/weather/functions/fnc_initModuleSettings.sqf +++ b/addons/weather/functions/fnc_initModuleSettings.sqf @@ -15,10 +15,7 @@ #include "script_component.hpp" -private ["_logic", "_units", "_activated"]; -_logic = _this select 0; -_units = _this select 1; -_activated = _this select 2; +params ["_logic", "_units", "_activated"]; if !(_activated) exitWith {}; @@ -36,4 +33,4 @@ if !(_activated) exitWith {}; // Server weather update interval [_logic, QGVAR(serverUpdateInterval), "serverUpdateInterval"] call EFUNC(common,readSettingFromModule); -GVAR(serverUpdateInterval) = 1 max GVAR(serverUpdateInterval) min 600; \ No newline at end of file +GVAR(serverUpdateInterval) = 1 max GVAR(serverUpdateInterval) min 600; diff --git a/addons/weather/functions/fnc_updateRain.sqf b/addons/weather/functions/fnc_updateRain.sqf index ced8641f61..6c4c829747 100644 --- a/addons/weather/functions/fnc_updateRain.sqf +++ b/addons/weather/functions/fnc_updateRain.sqf @@ -14,8 +14,8 @@ if (!GVAR(syncRain)) exitWith {}; if (!isNil "ACE_RAIN_PARAMS") then { - EXPLODE_3_PVT(ACE_RAIN_PARAMS,_oldRain,_newRain,_period); - + ACE_RAIN_PARAMS params ["_oldRain", "_newRain", "_period"]; + private ["_periodPosition", "_periodPercent"]; _periodPosition = (ACE_time - GVAR(rain_period_start_time)) min _period; _periodPercent = (_periodPosition / _period) min 1; diff --git a/tools/sqf_validator.py b/tools/sqf_validator.py new file mode 100644 index 0000000000..c80e2e5462 --- /dev/null +++ b/tools/sqf_validator.py @@ -0,0 +1,121 @@ + +import fnmatch +import os +import re +import ntpath +import sys +import argparse + +def check_sqf_syntax(filepath): + bad_count_file = 0 + def pushClosing(t): + closingStack.append(closing.expr) + closing << Literal( closingFor[t[0]] ) + + def popClosing(): + closing << closingStack.pop() + + with open(filepath, 'r') as file: + content = file.read() + brackets_list = [] + + isInCommentBlock = False + checkIfInComment = False + ignoreTillEndOfLine = False + checkIfNextIsClosingBlock = False + isInString = False + + lineNumber = 0 + + for c in content: + if c == '\n': + lineNumber += 1 # so we can print accurate line number information when we detect a possible error + if (isInString): + if (c == inStringType): + isInString = False + elif (isInCommentBlock == False): # if we are not in a comment block, we will check if we are at the start of one or count the () {} and [] + if (checkIfInComment): # This means we have encountered a /, so we are now checking if this is an inline comment or a comment block + checkIfInComment = False + if c == '*': # if the next character after / is a *, we are at the start of a comment block + isInCommentBlock = True + if (c == '/'): # Otherwise, will check if we are in an line comment + ignoreTillEndOfLine = True # and an line comment is a / followed by another / (//) We won't care about anything that comes after it + if (isInCommentBlock == False): + if (ignoreTillEndOfLine): # we are in a line comment, just continue going through the characters until we find an end of line + if (c == '\n'): + ignoreTillEndOfLine = False + else: + if (c == '"'): + isInString = True + inStringType = c + elif (c == '/'): + checkIfInComment = True + elif (c == '('): + brackets_list.append('(') + elif (c == ')'): + if (brackets_list[-1] in ['{', '[']): + print "Possible missing bracket detected at )" + print filepath + "Line number: " + str(lineNumber) + bad_count_file += 1 + brackets_list.append(')') + elif (c == '['): + brackets_list.append('[') + elif (c == ']'): + if (brackets_list[-1] in ['{', '(']): + print "Possible missing bracket detected at ]" + print filepath + "Line number: " + str(lineNumber) + bad_count_file += 1 + brackets_list.append(']') + elif (c == '{'): + brackets_list.append('{') + elif (c == '}'): + if (brackets_list[-1] in ['(', '[']): + print "Possible missing bracket detected at }" + print filepath + "Line number: " + str(lineNumber) + bad_count_file += 1 + brackets_list.append('}') + else: + if (c == '*'): + checkIfNextIsClosingBlock = True; + elif (checkIfNextIsClosingBlock): + if (c == '/'): + isInCommentBlock = False + elif (c != '*'): + checkIfNextIsClosingBlock = False + + if brackets_list.count('[') != brackets_list.count(']'): + print "A possible missing [ or ] in file " + filepath + "[ = " + str(brackets_list.count('[')) + " ] =" + str(brackets_list.count(']')) + bad_count_file += 1 + if brackets_list.count('(') != brackets_list.count(')'): + print "A possible missing ( or ) in file " + filepath + "( = " + str(brackets_list.count('(')) + " ) =" + str(brackets_list.count(')')) + bad_count_file += 1 + if brackets_list.count('{') != brackets_list.count('}'): + print "A possible missing { or } in file " + filepath + "{ = " + str(brackets_list.count('{')) + " } =" + str(brackets_list.count('}')) + bad_count_file += 1 + return bad_count_file + +def main(): + + print("#########################") + print("# Validate SQF files missing brackets #") + print("#########################") + + sqf_list = [] + bad_count = 0 + + parser = argparse.ArgumentParser() + parser.add_argument('-m','--module', help='only search specified module addon folder', required=False, default=".") + args = parser.parse_args() + + for root, dirnames, filenames in os.walk('../addons' + '/' + args.module): + for filename in fnmatch.filter(filenames, '*.sqf'): + sqf_list.append(os.path.join(root, filename)) + + for filename in sqf_list: + bad_count = bad_count + check_sqf_syntax(filename) + + print ("Bad Count {0}".format(bad_count)) + return bad_count + +if __name__ == "__main__": + sys.exit(main())