diff --git a/.editorconfig b/.editorconfig index 5c5dce44..06574b47 100644 --- a/.editorconfig +++ b/.editorconfig @@ -71,5 +71,5 @@ end_of_line = lf [addons/main/LICENSE] end_of_line = lf -[.github/workflows/main.yml] +[.github/workflows/*.yml] end_of_line = lf \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 936f3b72..0e7c0e26 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,4 +9,6 @@ *.md text eol=crlf *.toml text eol=crlf *.txt text eol=crlf -*.xml text eol=crlf \ No newline at end of file +*.xml text eol=crlf +*.rhai text eol=crlf +*.inc text eol=crlf \ No newline at end of file diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 00000000..5ace4600 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e4836f1c..71d8784d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,13 +19,13 @@ jobs: - name: Check for BOM uses: arma-actions/bom-check@master - name: .editorconfig Checker - uses: jokoho48/action-editorconfig-checker@main + uses: editorconfig-checker/action-editorconfig-checker@main - name: Setup Node.js environment - uses: actions/setup-node@v2.1.2 + uses: actions/setup-node@v4 - name: Run Stringtable Checker - run: cd tools/stringtableChecker && npm i &> /dev/null && cd ../../ && node tools/stringtableChecker/stringTableChecker.js + run: cd tools/nodejs_tools && npm i &> /dev/null && cd ../../ && node tools/nodejs_tools/stringTableChecker.js - name: Check Functions - run: node tools/prepchecker.js + run: node tools/nodejs_tools/prepchecker.js lint: runs-on: ubuntu-latest @@ -35,7 +35,7 @@ jobs: - name: Lint (sqflint) uses: jokoho48/sqflint@master continue-on-error: true # No failure due to many false-positives - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: 'sqfLint Log' path: 'sqf.log' @@ -47,15 +47,24 @@ jobs: steps: - uses: actions/checkout@master with: - fetch-depth: 1 - - name: Build addon with HEMTT - uses: arma-actions/hemtt@master - with: - command: 'build --release' - - uses: actions/upload-artifact@master + fetch-depth: 0 + - name: Setup Node.js environment + uses: actions/setup-node@v4 + - name: Setup Node tools + run: cd tools/nodejs_tools && npm i &> /dev/null && cd ../../ + - name: Setup HEMTT + uses: arma-actions/hemtt@v1 + - name: Set Build Version + run: node tools/nodejs_tools/gitversionsetter.js + - name: Run HEMTT build + run: hemtt release + - name: Check Hemtt Annotactions + run: node tools/nodejs_tools/hemttchecker.js + - name: Upload Release + uses: actions/upload-artifact@v4 with: name: '@LambsDanger' - path: 'releases/@LambsDanger*.zip' + path: '.hemttout/release/*' stringtables: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..d5c69567 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Release + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + with: + fetch-depth: 0 + - name: Setup HEMTT + uses: arma-actions/hemtt@main + - name: Setup Node.js environment + uses: actions/setup-node@v4 + - name: Setup Node tools + run: cd tools/nodejs_tools && npm i &> /dev/null && cd ../../ + - name: Set Build Version + run: node tools/nodejs_tools/gitversionsetter.js + - name: Run HEMTT build + run: hemtt release + - run: | + version="${{ github.event.release.tag_name }}" + mv releases/lambs-latest.zip "@LambsDanger_${version//[.]/_}.zip" + - name: Update Release with Files + id: create_version_release + uses: ncipollo/release-action@v1 + with: + allowUpdates: true # Set this to false if you want to prevent updating existing releases + name: ${{ github.event.release.name }} + draft: ${{ github.event.release.unpublished }} + prerelease: ${{ github.event.release.prerelease }} + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: "./@LambsDanger_*.zip" + tag: ${{ github.event.release.tag_name }} + body: ${{ github.event.release.body }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 56045e59..7a627ece 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,10 @@ lint.bat sqf/* -tools/stringtableChecker/node_modules +tools/nodejs_tools/node_modules .vscode/ *.sqfc + +.hemttout/ \ No newline at end of file diff --git a/.hemtt/hooks/pre_release/set_version.rhai b/.hemtt/hooks/pre_release/set_version.rhai new file mode 100644 index 00000000..40325637 --- /dev/null +++ b/.hemtt/hooks/pre_release/set_version.rhai @@ -0,0 +1,14 @@ +// Read the current contents of the mod.cpp +// file from the project source +let version = HEMTT_DIRECTORY + .join("mod.cpp") + .open_file() + .read(); +// Replace the placeholder version with the actual version +version.replace("{version}", HEMTT.project().version().to_string_short()); +// Write the new contents to the build output +// create_file will overwrite the file if it exists +HEMTT_OUTPUT + .join("mod.cpp") + .create_file() + .write(version); \ No newline at end of file diff --git a/.hemtt/project.toml b/.hemtt/project.toml new file mode 100644 index 00000000..de122286 --- /dev/null +++ b/.hemtt/project.toml @@ -0,0 +1,33 @@ +name = "LAMBS Danger" +prefix = "lambs" +author = "LAMBS Dev Team" +mainprefix = "z" + +[version] +path = "addons/main/script_version.hpp" +git_hash = 0 + +[files] +include = [ + "mod.cpp", + "*.paa", + "LICENSE", + "readme.txt", + "readme.md" +] + +[hemtt.signing] +authority = "LambsDanger" + +[hemtt.release] +folder = "lambs_danger" + +[hemtt.launch.default] +workshop = [ + "450814997", # CBA_A3's Workshop ID +] + +parameters = [ + "-world=empty", + "-filePatching", +] \ No newline at end of file diff --git a/README.md b/README.md index e56e297e..2be71620 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Lambs Danger Discord - Lambs Danger Build Status + Lambs Danger Build Status

diff --git a/addons/danger/XEH_preInit.sqf b/addons/danger/XEH_preInit.sqf index 63c6251c..3c1b77e1 100644 --- a/addons/danger/XEH_preInit.sqf +++ b/addons/danger/XEH_preInit.sqf @@ -5,7 +5,7 @@ ADDON = false; // mod check GVAR(Loaded_WP) = isClass (configfile >> "CfgPatches" >> "lambs_wp"); -#include "settings.sqf" +#include "settings.inc.sqf" // FSM priorities ~ this could be made into CBA settings. But I kinda want to explore it a little first - nkenny if (isNil QGVAR(fsmPriorities)) then { @@ -32,18 +32,24 @@ if (isNil QGVAR(dangerUntil)) then { // EH handling reinforcement and combat mode [QEGVAR(main,OnInformationShared), { params [["_unit", objNull], "", ["_target", objNull], ["_groups", []]]; - { private _leader = leader _x; if (local _leader) then { // reinforce - if (!isNull _target && { _x getVariable [QGVAR(enableGroupReinforce), false] } && { (_x getVariable [QGVAR(enableGroupReinforceTime), -1]) < time }) then { + if ( + !isNull _target + && {_x getVariable [QGVAR(enableGroupReinforce), false]} + && {(_x getVariable [QGVAR(enableGroupReinforceTime), -1]) < time } + ) then { [_leader, [getPosASL _unit, (_leader targetKnowledge _target) select 6] select (_leader knowsAbout _target > 1.5)] call FUNC(tacticsReinforce); }; - // set combatMode - if (_leader distance2D _unit < (EGVAR(main,combatShareRange)) && {!(_leader getVariable [QGVAR(disableAI), false])} && {(behaviour _leader) isNotEqualTo "COMBAT"}) then { - [units _x, _target, [_leader, 40, true, true] call EFUNC(main,findBuildings), "information"] call EFUNC(main,doGroupHide); + // reorientate group + if ( + !(_leader getVariable [QGVAR(disableAI), false]) + && {(behaviour _leader) isNotEqualTo "COMBAT"} + ) then { + //[units _x, _target, [_leader, 40, true, true] call EFUNC(main,findBuildings), "information"] call EFUNC(main,doGroupHide); _x setFormDir (_leader getDir _unit); }; }; diff --git a/addons/danger/functions/fnc_brainAssess.sqf b/addons/danger/functions/fnc_brainAssess.sqf index f2c0b2fb..02a2d7f7 100644 --- a/addons/danger/functions/fnc_brainAssess.sqf +++ b/addons/danger/functions/fnc_brainAssess.sqf @@ -29,7 +29,12 @@ params ["_unit", "", "", ["_target", objNull]]; private _timeout = time + 3; // check if stopped -if (!(_unit checkAIFeature "PATH")) exitWith {_timeout}; +if ( + !(_unit checkAIFeature "PATH") + || {((behaviour _unit)) isEqualTo "STEALTH"} + || {(currentCommand _unit) isEqualTo "STOP"} + || {(combatMode _unit) in ["BLUE", "GREEN"]} +) exitWith {_timeout}; // group memory private _groupMemory = (group _unit) getVariable [QEGVAR(main,groupMemory), []]; diff --git a/addons/danger/functions/fnc_brainEngage.sqf b/addons/danger/functions/fnc_brainEngage.sqf index f293b8d2..84eae726 100644 --- a/addons/danger/functions/fnc_brainEngage.sqf +++ b/addons/danger/functions/fnc_brainEngage.sqf @@ -55,6 +55,9 @@ if ( _timeout + 1.4 }; +// set low stance +_unit setUnitPosWeak "MIDDLE"; + // far, try to suppress if ( _distance < 500 @@ -64,11 +67,12 @@ if ( && {_type isEqualTo DANGER_CANFIRE} ) exitWith { private _posASL = ATLtoASL (_unit getHideFrom _target); - if (((ASLtoAGL _posASL) select 2) > 6) exitWith { - _timeout + 3 + if (((ASLtoAGL _posASL) select 2) > 6) then { + _posASL = ASLtoAGL _posASL; + _posASL set [2, 0.5]; + _posASL = AGLToASL _posASL }; _unit forceSpeed 0; - _unit setUnitPosWeak "MIDDLE"; _unit suppressFor 4; [_unit, _posASL vectorAdd [0, 0, 0.8], true] call EFUNC(main,doSuppress); _timeout + 4 diff --git a/addons/danger/functions/fnc_brainVehicle.sqf b/addons/danger/functions/fnc_brainVehicle.sqf index 378a0148..70c4a235 100644 --- a/addons/danger/functions/fnc_brainVehicle.sqf +++ b/addons/danger/functions/fnc_brainVehicle.sqf @@ -51,7 +51,15 @@ _causeArray params ["_cause", "_dangerPos", "", "_dangerCausedBy"]; // "_dangerU _unit setVariable [QEGVAR(main,FSMDangerCauseData), _causeArray, EGVAR(main,debug_functions)]; // is it an attack? -private _attack = _cause in [DANGER_ENEMYDETECTED, DANGER_ENEMYNEAR, DANGER_HIT, DANGER_CANFIRE, DANGER_BULLETCLOSE] && {(side _dangerCausedBy) isNotEqualTo (side _unit)}; +private _attack = _cause in [DANGER_ENEMYDETECTED, DANGER_ENEMYNEAR, DANGER_HIT, DANGER_CANFIRE, DANGER_BULLETCLOSE] && {(side _dangerCausedBy) isNotEqualTo (side _unit)} && {!isNull _dangerCausedBy}; + +// update dangerPos if attacking. Check that the position is not too far above, or below ground. +if (_attack) then { + private _dangerPos = _unit getHideFrom _dangerCausedBy; + if (_dangerPos isEqualTo [0, 0, 0]) exitWith {_attack = false;}; + _dangerPos = ASLtoAGL (ATLtoASL _dangerPos); + if ((_dangerPos select 2) > 6 || {(_dangerPos select 2) < 2}) then {_dangerPos set [2, 1]}; +}; // vehicle type ~ Artillery private _artillery = _vehicle getVariable [QEGVAR(main,isArtillery), getNumber (configOf _vehicle >> "artilleryScanner") > 0]; @@ -80,8 +88,8 @@ if (_vehicle isKindOf "Air") exitWith { // vehicle type ~ Static weapon if (_vehicle isKindOf "StaticWeapon") exitWith { - // get out if enemy near - if ((_unit findNearestEnemy _dangerPos) distance _vehicle < (6 + random 15)) then { + // get out if enemy near OR out of ammunition + if ((count (magazines _vehicle)) isEqualTo 0 || {(_unit findNearestEnemy _dangerPos) distance _vehicle < (6 + random 15)}) then { private _vehicleCrew = (crew _vehicle); _vehicleCrew orderGetIn false; { @@ -127,6 +135,9 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith { private _validTarget = (side _unit) isNotEqualTo (side _dangerCausedBy); private _distance = _vehicle distance _dangerCausedBy; + // keep cargo aboard! + _vehicle setUnloadInCombat [false, false]; + // vehicle jink private _oldDamage = _vehicle getVariable [QGVAR(vehicleDamage), 0]; if (_validTarget && {_distance < (12 + random 15) || {damage _vehicle > _oldDamage}}) exitWith { @@ -135,45 +146,53 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith { [_timeout + _delay] + _causeArray }; - // tank assault - if (_attack && {speed _vehicle < 20}) then { - // rotate - [_vehicle, _dangerCausedBy] call EFUNC(main,doVehicleRotate); - - // assault - if (_distance < 750 && {_dangerCausedBy isKindOf "Man"}) then { - [ - {_this call EFUNC(main,doVehicleAssault)}, - [_unit, _dangerPos, _dangerCausedBy], - _delay - 1 - ] call CBA_fnc_waitAndExecute; - }; - }; - // foot infantry support ~ unload private _group = group _vehicle; private _cargo = ((fullCrew [_vehicle, "cargo"]) apply {_x select 0}); - _cargo append ((fullCrew [_vehicle, "turret"]) apply {_x select 0}); + _cargo append ((fullCrew [_vehicle, "turret"] select {_x select 4}) apply {_x select 0}); if ( _validTarget && {_cargo isNotEqualTo []} - && {!(terrainIntersectASL [eyePos _vehicle, (eyePos _dangerCausedBy) vectorAdd [0, 0, 3]]) || {_distance < 300}} - && {_unit knowsAbout _dangerCausedBy > 1} - ) then { + && {speed _vehicle < 10} + && {_distance < 350} + && {_unit knowsAbout _dangerCausedBy > 2 || {_distance < 220}} + && {!(terrainIntersectASL [eyePos _vehicle, (eyePos _dangerCausedBy) vectorAdd [0, 0, 2]]) || {_distance < 200}} + ) exitWith { // define enemy direction _group setFormDir (_vehicle getDir _dangerCausedBy); + _cargo doMove _dangerPos; // delayed unload [ { params [["_cargo", []], ["_side", EAST], ["_vehicle", objNull]]; _cargo orderGetIn false; + _cargo allowGetIn false; if (EGVAR(main,debug_functions)) then {["%1 %2 unloading %3 carried troops", _side, getText (configOf _vehicle >> "displayName"), count _cargo] call EFUNC(main,debugLog);}; }, [_cargo, side _group, _vehicle], - _delay * 2 + 0.1 ] call CBA_fnc_waitAndExecute; + + // exit + [_timeout + _delay + 1] + _causeArray + }; + + // tank assault + if (_attack && {speed _vehicle < 20}) then { + + // rotate + [_vehicle, _dangerPos] call EFUNC(main,doVehicleRotate); + + // assault + if (_distance < 750 && {_dangerCausedBy isKindOf "Man"}) then { + [ + {_this call EFUNC(main,doVehicleAssault)}, + [_unit, _dangerPos, _dangerCausedBy], + _delay - 1 + ] call CBA_fnc_waitAndExecute; + }; }; // timeout @@ -188,20 +207,19 @@ if (_car) exitWith { private _delay = 0; private _slow = speed _vehicle < 30; - // look to danger - if (!isNull _dangerCausedBy && {_vehicle knowsAbout _dangerCausedBy > 3}) then {_vehicle doWatch ATLtoASL (_vehicle getHideFrom _dangerCausedBy);}; - - // escape - if (_slow && {_vehicle distance _dangerCausedBy < (15 + random 35)}) then { + // escape ~ if enemy within 15-50 meters or explosions are nearby! + if (_slow && {_cause isEqualTo DANGER_EXPLOSION || {_vehicle distanceSqr _dangerCausedBy < (225 + random 1225)}}) exitWith { [_unit] call EFUNC(main,doVehicleJink); - _slow = false; - _delay = 3; + [_timeout + 3] + _causeArray }; + // look to danger + if (_attack && {_vehicle knowsAbout _dangerCausedBy > 3}) then {_vehicle doWatch (AGLtoASL _dangerPos);}; + // suppression if (_attack && {_slow}) then { - [_unit, (_unit getHideFrom _dangerCausedBy) vectorAdd [0, 0, random 1]] call EFUNC(main,doVehicleSuppress); - [{_this call EFUNC(main,doVehicleSuppress)}, [_unit, _dangerPos], 3] call CBA_fnc_waitAndExecute; + [_unit, _dangerPos vectorAdd [0, 0, random 1]] call EFUNC(main,doVehicleSuppress); + [{_this call EFUNC(main,doVehicleSuppress)}, [_unit, _dangerPos vectorAdd [0, 0, random 2]], 3] call CBA_fnc_waitAndExecute; _delay = random 4; }; diff --git a/addons/danger/functions/fnc_tacticsAssault.sqf b/addons/danger/functions/fnc_tacticsAssault.sqf index 2c635a01..25d0a2da 100644 --- a/addons/danger/functions/fnc_tacticsAssault.sqf +++ b/addons/danger/functions/fnc_tacticsAssault.sqf @@ -80,7 +80,7 @@ private _housePos = []; _group setVariable [QEGVAR(main,groupMemory), _housePos]; // add base position -_housePos pushBack _target; +if (_housePos isEqualTo []) then {_housePos pushBack _target;}; // set tasks _unit setVariable [QEGVAR(main,currentTarget), _target, EGVAR(main,debug_functions)]; @@ -103,7 +103,7 @@ if (!GVAR(disableAutonomousSmokeGrenades)) then { [_unit, _target] call EFUNC(main,doSmoke); // grenadier smoke - [{_this call EFUNC(main,doUGL)}, [_units, _target, "shotSmokeX"], 3] call CBA_fnc_waitAndExecute; + [{_this call EFUNC(main,doUGL)}, [_units, _target, "shotSmoke"], 3] call CBA_fnc_waitAndExecute; }; // ready group @@ -117,7 +117,7 @@ _units doWatch objNull; } foreach (_units select {getSuppression _x < 0.7 && {needReload _x > 0.6}}); // execute function -[_cycle, _units, _housePos] call EFUNC(main,doGroupAssault); +[{_this call EFUNC(main,doGroupAssault)}, [_cycle, _units, _housePos], 2 + random 3] call CBA_fnc_waitAndExecute; // debug if (EGVAR(main,debug_functions)) then { diff --git a/addons/danger/functions/fnc_tacticsAssess.sqf b/addons/danger/functions/fnc_tacticsAssess.sqf index 6db6870d..795a21e9 100644 --- a/addons/danger/functions/fnc_tacticsAssess.sqf +++ b/addons/danger/functions/fnc_tacticsAssess.sqf @@ -33,7 +33,7 @@ private _group = group _unit; // set variable _group setVariable [QGVAR(isExecutingTactic), true]; _group setVariable [QGVAR(contact), time + 600]; -_group enableAttack false; +if (isNull objectParent _unit) then {_group enableAttack false;}; // set current task _unit setVariable [QEGVAR(main,currentTarget), objNull, EGVAR(main,debug_functions)]; @@ -126,7 +126,7 @@ if !(_enemies isEqualTo [] || {_unitCount < random 4}) then { && {_inside || {_x call EFUNC(main,isIndoor)}} }; if (_nearIndoorTarget != -1) exitWith { - _plan append [TACTICS_GARRISON, TACTICS_ASSAULT, TACTICS_ASSAULT]; + _plan append [TACTICS_ASSAULT, TACTICS_ASSAULT]; _pos = _unit getHideFrom (_enemies select _nearIndoorTarget); }; @@ -136,7 +136,7 @@ if !(_enemies isEqualTo [] || {_unitCount < random 4}) then { private _currentWP = _waypoints select ((currentWaypoint _group) min ((count _waypoints) - 1)); private _holdWP = ((waypointType _currentWP) isEqualTo "HOLD") && {(waypointPosition _currentWP) distance2D _unit < RANGE_MID}; if (_holdWP) exitWith { - _plan append [TACTICS_GARRISON, TACTICS_HIDE]; + _plan append [TACTICS_HIDE, TACTICS_HIDE]; _pos = waypointPosition _currentWP; breakOut "conditionScope"; }; @@ -159,6 +159,7 @@ if !(_enemies isEqualTo [] || {_unitCount < random 4}) then { }; // enemies near and below + /* private _farNoCoverTarget = _enemies findIf { _unit distance2D _x < RANGE_MID && {((getPosASL _x) select 2) < ((_eyePos select 2) - 15)} @@ -169,6 +170,7 @@ if !(_enemies isEqualTo [] || {_unitCount < random 4}) then { _plan pushBack TACTICS_ATTACK; _pos = _enemies select _farNoCoverTarget; }; + */ // enemy at inside buildings or fortified or far private _fortifiedTarget = _enemies findIf { diff --git a/addons/danger/functions/fnc_tacticsContact.sqf b/addons/danger/functions/fnc_tacticsContact.sqf index ae41279c..e780dfa3 100644 --- a/addons/danger/functions/fnc_tacticsContact.sqf +++ b/addons/danger/functions/fnc_tacticsContact.sqf @@ -59,7 +59,7 @@ _group setVariable [QEGVAR(main,currentTactic), "Contact!", EGVAR(main,debug_fun ] call CBA_fnc_waitAndExecute; // change formation and attack state -_group enableAttack false; +if (isNull objectParent _unit) then {_group enableAttack false;}; _group setFormation (_group getVariable [QGVAR(dangerFormation), formation _unit]); _group setFormDir (_unit getDir _enemy); @@ -68,7 +68,7 @@ _group setFormDir (_unit getDir _enemy); // gesture + callouts for larger units private _stealth = (behaviour _unit) isEqualTo "STEALTH"; -private _units = (units _unit) select {(currentCommand _x) in ["", "MOVE"] && {!isPlayer _x}}; +private _units = (units _unit) select {(currentCommand _x) in ["", "MOVE"] && {!isPlayer _x} && {isNull objectParent _x} && {_x checkAIFeature "MOVE"} && {_x checkAIFeature "PATH"}}; private _count = count _units; if (_count > 2) then { // gesture @@ -123,8 +123,17 @@ if ( { _x setUnitPosWeak selectRandom ["DOWN", "MIDDLE"]; [_x, _posASL vectorAdd [0, 0, 0.8], true] call EFUNC(main,doSuppress); - _x suppressFor 5; - _x setVariable [QEGVAR(main,currentTask), "Suppress (contact)", EGVAR(main,debug_functions)]; + _x suppressFor 7; + [ + { + params ["_unit", "_posASL"]; + if (_unit call EFUNC(main,isAlive) && {!(currentCommand _unit isEqualTo "Suppress")}) then { + [_unit, _posASL vectorAdd [2 - random 4, 2 - random 4, 0.8], true] call EFUNC(main,doSuppress); + }; + }, + [_x, _posASL], + 8 + ] call CBA_fnc_waitAndExecute; } foreach _units; // group variable @@ -155,13 +164,27 @@ if ( ) exitWith { // execute assault ~ forced { - [_x, _buildings] call EFUNC(main,doAssaultMemory); - _x setVariable [QEGVAR(main,currentTask), "Assault (contact)", EGVAR(main,debug_functions)]; - // forced movement _x setVariable [QGVAR(forceMove), true]; - [{_this setVariable [QGVAR(forceMove), nil]}, _x, 5 + random 4] call CBA_fnc_waitAndExecute; - } foreach _units select {getSuppression _x < 0.5}; + [ + { + params ["_unit", "_unitPos"]; + if (_unit call EFUNC(main,isAlive)) then { + _unit setVariable [QGVAR(forceMove), nil]; + _unit setUnitPos _unitPos; + }; + }, + [_x, unitPos _x], + 5 + random 6 + ] call CBA_fnc_waitAndExecute; + + // movement and stance + _x setUnitPos "MIDDLE"; + _x forceSpeed 3; + _x setVariable [QEGVAR(main,currentTask), "Assault (contact)", EGVAR(main,debug_functions)]; + + } foreach _units; + _units doMove (selectRandom _buildings); // group variable _group setVariable [QEGVAR(main,currentTactic), "Contact! (aggressive)", EGVAR(main,debug_functions)]; diff --git a/addons/danger/functions/fnc_tacticsFlank.sqf b/addons/danger/functions/fnc_tacticsFlank.sqf index 74f70142..783e106c 100644 --- a/addons/danger/functions/fnc_tacticsFlank.sqf +++ b/addons/danger/functions/fnc_tacticsFlank.sqf @@ -19,7 +19,7 @@ * * Public: No */ -params ["_group", "_target", ["_units", []], ["_cycle", 4], ["_overwatch", []], ["_delay", 100]]; +params ["_group", "_target", ["_units", []], ["_cycle", 4], ["_overwatch", []], ["_delay", 120]]; // group is missing if (isNull _group) exitWith {false}; @@ -108,7 +108,7 @@ _group setFormation "FILE"; { _x setUnitPos "DOWN"; _x setVariable [QGVAR(forceMove), true]; -} foreach _units; +} foreach (_units select {isNull objectParent _x}); // leader smoke ~ deploy concealment to enable movement if (!GVAR(disableAutonomousSmokeGrenades)) then {[_unit, _overwatch] call EFUNC(main,doSmoke);}; diff --git a/addons/danger/functions/fnc_tacticsReinforce.sqf b/addons/danger/functions/fnc_tacticsReinforce.sqf index 76068240..0e3bb2bb 100644 --- a/addons/danger/functions/fnc_tacticsReinforce.sqf +++ b/addons/danger/functions/fnc_tacticsReinforce.sqf @@ -74,6 +74,13 @@ if (_units isEqualTo []) then { // has artillery? ~ if so fire in support? // is aircraft or tank? Different movement waypoint? +// clear HOLD waypointss +private _waypoints = waypoints _group; +private _currentWP = _waypoints select ((currentWaypoint _group) min ((count _waypoints) - 1)); +if ((waypointType _currentWP) isEqualTo "HOLD") then { + [_group] call CBA_fnc_clearWaypoints; +}; + // formation changes ~ allowed here as Reinforcing units have full autonomy - nkenny private _distance = _unit distance2D _target; if (_distance > 500) then { diff --git a/addons/danger/scripts/lambs_danger.fsm b/addons/danger/scripts/lambs_danger.fsm index fec9fae7..583380b0 100644 --- a/addons/danger/scripts/lambs_danger.fsm +++ b/addons/danger/scripts/lambs_danger.fsm @@ -531,7 +531,7 @@ class FSM priority = 4.000000; to="End_Forced"; precondition = /*%FSM*/""/*%FSM*/; - condition=/*%FSM*/"call lambs_danger_fnc_isForced && {_queue isEqualTo []}"/*%FSM*/; + condition=/*%FSM*/"_queue isEqualTo [] && {call lambs_danger_fnc_isForced}"/*%FSM*/; action=/*%FSM*/""/*%FSM*/; }; /*%FSM*/ diff --git a/addons/danger/scripts/lambs_dangerCivilian.fsm b/addons/danger/scripts/lambs_dangerCivilian.fsm index f25eaa7c..4220543a 100644 --- a/addons/danger/scripts/lambs_dangerCivilian.fsm +++ b/addons/danger/scripts/lambs_dangerCivilian.fsm @@ -15,7 +15,7 @@ item10[] = {"Reset",2,250,-700.000000,1400.000000,-600.000000,1450.000000,0.0000 item11[] = {"Hide_vs__run",2,250,-540.000000,40.000000,-440.000000,100.000000,0.000000,"Hide vs. run"}; item12[] = {"Vehicle",4,218,-920.000000,360.000000,-820.000000,420.000000,1.000000,"Vehicle"}; item13[] = {"Man",8,218,-700.000000,350.000000,-600.000000,400.000000,0.000000,"Man"}; -item14[] = {"Man",2,250,-680.000000,600.000000,-580.000000,660.000000,0.000000,"Man"}; +item14[] = {"Man",2,4346,-680.000000,600.000000,-580.000000,660.000000,0.000000,"Man"}; item15[] = {"Order_out",2,250,-940.000000,600.000000,-840.000000,660.000000,0.000000,"Order out"}; item16[] = {"Always",8,218,-800.000000,600.000000,-700.000000,660.000000,0.000000,"Always"}; item17[] = {"Select_danger",2,250,-820.000000,-160.000000,-720.000000,-100.000000,0.000000,"Select danger"}; @@ -180,8 +180,8 @@ link63[] = {54,2}; link64[] = {55,2}; link65[] = {56,4}; link66[] = {57,58}; -globals[] = {0.000000,0,0,0,0,640,480,1,225,6316128,1,-1872.445801,594.427734,1279.814941,-590.437561,1166,884,1}; -window[] = {2,-1,-1,-1,-1,870,52,673,52,3,1184}; +globals[] = {0.000000,0,0,0,0,640,480,1,225,6316128,1,-1487.644531,43.572693,1070.380371,-90.508331,1166,884,1}; +window[] = {2,-1,-1,-1,-1,1026,208,829,208,3,1184}; *//*%FSM*/ class FSM { @@ -393,13 +393,11 @@ class FSM " _this setUnitPos selectRandom [""DOWN"",""DOWN"",""MIDDLE""];" \n "}; " \n "" \n - "// animation" \n - "if (_this call lambs_danger_fnc_fsmAllowAnimation) then {" \n - " _this playMoveNow selectRandom [""ApanPknlMsprSnonWnonDf"", ""ApanPercMsprSnonWnonDf"", ""ApanPpneMsprSnonWnonDf"", ""ApanPpneMrunSnonWnonDf""];" \n - "}; " \n - "" \n "// execute hide" \n - "[_this, _dangerPos] call lambs_main_fnc_doHide; " \n + "[_this, _dangerPos, 10] call lambs_main_fnc_doHide; " \n + "" \n + "// time dodge" \n + "private _timeDodge = time + 2;" \n "" \n ""/*%FSM*/; precondition = /*%FSM*/""/*%FSM*/; @@ -423,8 +421,8 @@ class FSM priority = 0.000000; to="Clean_up"; precondition = /*%FSM*/""/*%FSM*/; - condition=/*%FSM*/"getSuppression _this > 0.99"/*%FSM*/; - action=/*%FSM*/""/*%FSM*/; + condition=/*%FSM*/"time > _timeDodge && getSuppression _this > 0.99"/*%FSM*/; + action=/*%FSM*/"[_this] call lambs_main_fnc_doFleeing;"/*%FSM*/; }; /*%FSM*/ }; diff --git a/addons/danger/settings.sqf b/addons/danger/settings.inc.sqf similarity index 100% rename from addons/danger/settings.sqf rename to addons/danger/settings.inc.sqf diff --git a/addons/danger/stringtable.xml b/addons/danger/stringtable.xml index a6b30fa2..08f619cd 100644 --- a/addons/danger/stringtable.xml +++ b/addons/danger/stringtable.xml @@ -80,7 +80,7 @@ Wyłącza LAMBS AI dla grupy.\nWyłączenie tej funkcji zapobiega autonomicznym atakom na budynki i czyszeniu ich przez AI, a także ukrywaniu się przed samolotami i czołgami Отключает LAMBS группу ИИ\nОтключение этой функции предотвращает самостоятельную атаку и зачистку автономных помещений, а также прятание в укрытия от самолетов и танков. Disabilita l'IA del gruppo LAMBS\nLa disabilitazione di questa funzione impedisce assalti e sgomberi autonomi di edifici, oltre a nascondersi da aerei e carri armati - 禁用LAMBS 小组 AI\n禁用此功能可防止自动攻击和清除建筑,以及躲避飞机和坦克 + 禁用LAMBS小组AI\n禁用此功能可防止自动攻击和清除建筑,以及躲避飞机和坦克 Enable Dynamic Reinforcement @@ -170,7 +170,7 @@ Przełącza fazę manewru grupowego zainicjowaną przez dowódcę oddziału AI. Wyłączenie tej opcji uniemożliwi liderowi grupy AI wydawaniu nowych rozkazów do flankowania i ostrzeliwania budynków. Переключает фазу группового маневра, инициированную командиром отряда ИИ. Отключение этого не позволит лидеру группы ИИ добавлять приказы о маневрах для обхода и подавления огнем зданий. Attiva/disattiva la fase di manovra di gruppo avviata dal caposquadra AI. Disabilitarlo impedirà al leader del gruppo AI di aggiungere ordini di manovra per fiancheggiare e sopprimere gli edifici. - 切换由 AI 班长发起的小组操作阶段.禁用此功能将阻止 AI 组长添加机动命令来到侧翼和压制建筑物. + 切换由AI组长发起的小组操作阶段.禁用此功能将阻止AI组长添加机动命令来到侧翼和压制建筑物. Disable units hiding @@ -206,7 +206,7 @@ Переключает способность группы ИИ динамически развертывать стационарное/ранцевое оружие Schaltet die Fähigkeit der KI-Gruppe um, statische Waffen dynamisch einzusetzen Attiva/disattiva la capacità del gruppo IA di schierare dinamicamente armi statiche/zaino - 切换 AI 小组自动部署静态/背包武器的功能 + 切换AI小组自动部署静态/背包武器的功能 Disable units manning static weapons @@ -242,7 +242,7 @@ Переключает способность группы ИИ автономно использовать дым для прикрытия групповых маневров Schaltet die Fähigkeit der KI-Gruppe um, autonom Rauchgranaten zu verwenden, um Gruppenmanöver zu verbergen Attiva/disattiva la capacità del gruppo IA di utilizzare autonomamente il fumo per coprire le manovre di gruppo - 切换 AI 小组自动使用烟雾弹掩护小组的功能 + 切换AI小组自动使用烟雾弹掩护小组的功能 Disable units using flares for illumination @@ -260,7 +260,7 @@ Переключает способность группы ИИ автономно использовать осветительные ракеты для освещения в ночное время, если не доступны ПНВ или юнит находится в скрытом режиме. Schaltet die Fähigkeit der KI-Gruppe um, autonom Flares zur nächtlichen Beleuchtung zu verwenden, es sei denn, NVGs sind verfügbar oder die Einheit befindet sich im Schleichen-Modus Attiva o disattiva la capacità del gruppo IA di utilizzare autonomamente i bagliori per l'illuminazione di notte, a meno che non siano disponibili NVG o che l'unità sia in modalità invisibile - 切换 AI 组在夜间自主使用照明弹进行照明的功能除非 NVG 可用或单位处于隐身模式 + 切换AI组在夜间自主使用照明弹进行照明的功能除非NVG可用或单位处于隐身模式 CQB Range diff --git a/addons/eventhandlers/XEH_preInit.sqf b/addons/eventhandlers/XEH_preInit.sqf index 54339843..dd9a2bf1 100644 --- a/addons/eventhandlers/XEH_preInit.sqf +++ b/addons/eventhandlers/XEH_preInit.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" ADDON = false; -#include "settings.sqf" +#include "settings.inc.sqf" #include "XEH_PREP.hpp" diff --git a/addons/eventhandlers/functions/fnc_explosionEH.sqf b/addons/eventhandlers/functions/fnc_explosionEH.sqf index d177e775..a4a959a4 100644 --- a/addons/eventhandlers/functions/fnc_explosionEH.sqf +++ b/addons/eventhandlers/functions/fnc_explosionEH.sqf @@ -16,20 +16,22 @@ */ // init -params ["_unit"]; +params [["_unit", objNull], "", ["_source", objNull]]; // Standing or recent explosions ignored if ( !GVAR(ExplosionEventHandlerEnabled) + || isNull _unit || !(local _unit) || isPlayer _unit || {!isNull objectParent _unit} || {(stance _unit) isEqualTo "PRONE"} || {_unit getVariable [QGVAR(explosionReactionTime), 0] > time} + || {!(_unit call EFUNC(main,isAlive))} // Check alive status - just in case stance doesn't handle it ) exitWith {false}; // settings -private _pos = _unit getPos [4, random 360]; +private _pos = [_source, _unit getPos [4, random 360]] select (isNull _source); private _dir = 360 - (_unit getRelDir _pos); _unit setVariable [QGVAR(explosionReactionTime), time + GVAR(ExplosionReactionTime)]; diff --git a/addons/eventhandlers/settings.sqf b/addons/eventhandlers/settings.inc.sqf similarity index 100% rename from addons/eventhandlers/settings.sqf rename to addons/eventhandlers/settings.inc.sqf diff --git a/addons/formations/CfgFSMs.hpp b/addons/formations/CfgFSMs.hpp index ed69f748..42231b93 100644 --- a/addons/formations/CfgFSMs.hpp +++ b/addons/formations/CfgFSMs.hpp @@ -29,8 +29,8 @@ class CfgFSMs { function = "nothing"; parameters[] = {}; thresholds[] = {}; - } - } + }; + }; }; }; }; diff --git a/addons/formations/CfgVehicles.hpp b/addons/formations/CfgVehicles.hpp index 76dac077..993126d4 100644 --- a/addons/formations/CfgVehicles.hpp +++ b/addons/formations/CfgVehicles.hpp @@ -6,7 +6,9 @@ class CfgVehicles { }; class Land; class Man : Land { - crouchProbabilityCombat = 0.7; // default: 0.4 ~ frankly not sure these have any effect... + crouchProbabilityCombat = 0; // 0.4; + crouchProbabilityEngage = 0; // 0.75; + crouchProbabilityHiding = 0; // 0.8; formationTime = 3; // default: 5 formationX = 4.2; // default: 5 brakeDistance = 1.5; // default: 5 diff --git a/addons/main/XEH_PREP.hpp b/addons/main/XEH_PREP.hpp index 51b69a2c..4f9af4cf 100644 --- a/addons/main/XEH_PREP.hpp +++ b/addons/main/XEH_PREP.hpp @@ -1,4 +1,6 @@ + PREP(addShareInformationHandler); +PREP(checkMagazineAiUsageFlags); PREP(doAnimation); PREP(doCallout); PREP(doGesture); @@ -25,6 +27,7 @@ PREP(showDialog); PREP(parseData); PREP(removeEventhandlers); +PREP(getCompatibleThrowMuzzle); SUBPREP(GroupAction,doGroupAssault); SUBPREP(GroupAction,doGroupFlank); diff --git a/addons/main/XEH_preInit.sqf b/addons/main/XEH_preInit.sqf index 38a20f48..205587a1 100644 --- a/addons/main/XEH_preInit.sqf +++ b/addons/main/XEH_preInit.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" ADDON = false; #include "XEH_PREP.hpp" -#include "settings.sqf" +#include "settings.inc.sqf" GVAR(ChooseDialogSettingsCache) = false call CBA_fnc_createNamespace; // check for WP module diff --git a/addons/main/functions/GroupAction/fnc_doGroupAssault.sqf b/addons/main/functions/GroupAction/fnc_doGroupAssault.sqf index fb84f1c1..87eed7dc 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupAssault.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupAssault.sqf @@ -36,29 +36,23 @@ private _targetPos = _pos select 0; { // get unit private _unit = _x; + private _assaultPos = _targetPos; // manoeuvre _unit forceSpeed 3; - _unit setUnitPos (["UP", "MIDDLE"] select (getSuppression _x isNotEqualTo 0)); + _unit setUnitPos (["UP", "MIDDLE"] select ((getSuppression _x) isNotEqualTo 0 || {_unit distance2D _assaultPos > 8})); _unit setVariable [QGVAR(currentTask), format ["Group Assault (%1c - %2p)", _cycle, count _pos], GVAR(debug_functions)]; _unit setVariable [QEGVAR(danger,forceMove), true]; - // check enemy - /* - private _enemy = _unit findNearestEnemy _unit; - if ( - _unit distance2D _enemy < 12 - && {(vehicle _enemy) isKindOf "CAManBase"} - && {_enemy call FUNC(isAlive)} - ) then { - _targetPos = getPosATL _enemy; - _unit forceSpeed 2; + // modify movement (if far) + if (_unit distanceSqr _assaultPos > 400 && {!([_unit] call FUNC(isIndoor))}) then { + _assaultPos = _unit getPos [20, _unit getDir _assaultPos]; }; - */ - // set movement - if (((expectedDestination _unit) select 0) distance2D _targetPos > 1) then { - _unit doMove _targetPos; + if (((expectedDestination _unit) select 0) distanceSqr _assaultPos > 1) then { + + _unit doMove _assaultPos; + _unit setDestination [_assaultPos, "LEADER PLANNED", true]; }; // remove positions diff --git a/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf b/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf index e79b3d90..c4043912 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf @@ -21,7 +21,7 @@ params ["_cycle", "_units", "_vehicles", "_pos", "_overwatch"]; // update -_units = _units select { _x call FUNC(isAlive) && { !isPlayer _x } }; +_units = _units select { _x call FUNC(isAlive) && { !isPlayer _x } && {_x distance2D _overwatch > 5}}; _vehicles = _vehicles select { canFire _x }; private _posASL = AGLtoASL (selectRandom _pos); @@ -37,7 +37,7 @@ private _posASL = AGLtoASL (selectRandom _pos); // suppress if ( - RND(0.7) + RND(0.6) && {(leader _x) isNotEqualTo _x} && {!(terrainIntersectASL [eyePos _x, _posASL vectorAdd [0, 0, 3]])} ) then { @@ -46,11 +46,15 @@ private _posASL = AGLtoASL (selectRandom _pos); } foreach _units; // vehicles -{ - private _posAGL = selectRandom _pos; - _x doWatch _posAGL; - [_x, _posAGL] call FUNC(doVehicleSuppress); -} foreach _vehicles; +if (_cycle isEqualTo 1) then { + { + private _posAGL = selectRandom _pos; + _x doWatch _posAGL; + [_x, _posAGL] call FUNC(doVehicleSuppress); + } foreach _vehicles; +} else { + _vehicles doMove _overwatch; +}; // recursive cyclic if !(_cycle <= 1 || {_units isEqualTo []}) then { diff --git a/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf b/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf index 10334fba..4c35cfa9 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf @@ -35,7 +35,7 @@ if (_units isEqualTo []) exitWith { _units }; // man empty statics private _weapons = nearestObjects [_unit, ["StaticWeapon"], 75, true]; -_weapons = _weapons select { simulationEnabled _x && { !isObjectHidden _x } && { locked _x != 2 } && { (_x emptyPositions "Gunner") > 0 } }; +_weapons = _weapons select { simulationEnabled _x && { !isObjectHidden _x } && { locked _x != 2 } && { (_x emptyPositions "Gunner") > 0 } && { (count magazines _x) > 0 } }; // orders if !((_weapons isEqualTo []) || (_units isEqualTo [])) then { // De Morgan's laws FTW diff --git a/addons/main/functions/GroupAction/fnc_doGroupSuppress.sqf b/addons/main/functions/GroupAction/fnc_doGroupSuppress.sqf index e2916784..edac4c6b 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupSuppress.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupSuppress.sqf @@ -39,9 +39,21 @@ _vehicles = _vehicles select { canFire _x }; if !(_suppress || {(currentCommand _x isEqualTo "Suppress")}) then { // move forward _x forceSpeed 3; - _x doMove (_x getPos [20 + random 10, _x getDir _posAGL]); + _x doMove (_x getPos [20, _x getDir _posAGL]); _x setVariable [QGVAR(currentTask), "Group Suppress (Move)", GVAR(debug_functions)]; }; + + // follow-up fire + [ + { + params ["_unit", "_posASL"]; + if (_unit call FUNC(isAlive) && {!(currentCommand _unit isEqualTo "Suppress")}) then { + [_unit, _posASL vectorAdd [2 - random 4, 2 - random 4, 0.8], true] call EFUNC(main,doSuppress); + }; + }, + [_x, AGLtoASL _posAGL], + 5 + ] call CBA_fnc_waitAndExecute; } foreach _units; // vehicles diff --git a/addons/main/functions/UnitAction/fnc_doAssault.sqf b/addons/main/functions/UnitAction/fnc_doAssault.sqf index 25d2f0f2..1c474ca3 100644 --- a/addons/main/functions/UnitAction/fnc_doAssault.sqf +++ b/addons/main/functions/UnitAction/fnc_doAssault.sqf @@ -28,12 +28,15 @@ _unit setVariable [QGVAR(currentTask), "Assault", GVAR(debug_functions)]; private _getHide = _unit getHideFrom _target; // check visibility -private _vis = [objNull, "VIEW", objNull] checkVisibility [eyePos _unit, aimPos _target] isNotEqualTo 0; +private _vis = [objNull, "VIEW", objNull] checkVisibility [eyePos _unit, aimPos _target] isEqualTo 1; private _buildings = []; private _pos = call { // can see target! - if (_vis) exitWith {getPosATL _target}; + if (_vis) exitWith { + _unit lookAt (aimPos _target); + getPosATL _target + }; // near buildings private _buildings = [_getHide, _range, true, false] call FUNC(findBuildings); @@ -50,6 +53,7 @@ private _pos = call { }; // select target location + _doMove = true; _getHide }; diff --git a/addons/main/functions/UnitAction/fnc_doAssaultMemory.sqf b/addons/main/functions/UnitAction/fnc_doAssaultMemory.sqf index 82eaa770..cbed40fb 100644 --- a/addons/main/functions/UnitAction/fnc_doAssaultMemory.sqf +++ b/addons/main/functions/UnitAction/fnc_doAssaultMemory.sqf @@ -27,7 +27,7 @@ if (_groupMemory isEqualTo []) then { }; // exit or sort it! -_groupMemory = _groupMemory select {(leader _unit) distance2D _x < 150 && {_unit distance _x > 1.5}}; +_groupMemory = _groupMemory select {_unit distanceSqr _x < 20164 && {_unit distanceSqr _x > 2.25}}; if (_groupMemory isEqualTo []) exitWith { _group setVariable [QGVAR(groupMemory), [], false]; false @@ -35,23 +35,27 @@ if (_groupMemory isEqualTo []) exitWith { // check for enemy get position private _nearestEnemy = _unit findNearestEnemy _unit; -private _vis = [objNull, "VIEW", objNull] checkVisibility [eyePos _unit, aimPos _nearestEnemy] isNotEqualTo 0; if ( - (vehicle _nearestEnemy) isKindOf "CAManBase" - && {_vis || {_unit distance2D _nearestEnemy < 12 && {(round (getposATL _unit select 2)) isEqualTo (round ((getPosATL _nearestEnemy) select 2))}}} + (_unit distanceSqr _nearestEnemy < 5041) + && {(vehicle _nearestEnemy) isKindOf "CAManBase"} + && {[objNull, "VIEW", objNull] checkVisibility [eyePos _unit, aimPos _nearestEnemy] isEqualTo 1 || {_unit distanceSqr _nearestEnemy < 64 && {(round (getposATL _unit select 2)) isEqualTo (round ((getPosATL _nearestEnemy) select 2))}}} ) exitWith { - [_unit, _nearestEnemy, 8, false] call FUNC(doAssault); - _unit setUnitPosWeak "MIDDLE"; + [_unit, _nearestEnemy, 12, true] call FUNC(doAssault); }; // sort positions from nearest to furthest prioritising positions on the same floor -_groupMemory = _groupMemory apply {[(round (getposATL _unit select 2)) isEqualTo (round (_x select 2)), _x distanceSqr _unit, _x]}; +private _unitATL2 = round (getPosATL _unit select 2); +_groupMemory = _groupMemory apply {[_unitATL2 isEqualTo (round (_x select 2)), _x distanceSqr _unit, _x]}; _groupMemory sort true; _groupMemory = _groupMemory apply {_x select 2}; // get distance private _pos = _groupMemory select 0; private _distance2D = _unit distance2D _pos; +private _indoor = _unit call FUNC(isIndoor); +if (_distance2D > 20 && {!_indoor}) then { + _pos = _unit getPos [20, _unit getDir _pos]; +}; if (_pos isEqualType objNull) then {_pos = getPosATL _pos;}; // variables @@ -59,7 +63,7 @@ _unit setVariable [QGVAR(currentTarget), _pos, GVAR(debug_functions)]; _unit setVariable [QGVAR(currentTask), "Assault (sympathetic)", GVAR(debug_functions)]; // set stance -_unit setUnitPosWeak (["UP", "MIDDLE"] select (getSuppression _unit > 0.7 || {_unit call FUNC(isIndoor)})); +_unit setUnitPosWeak (["UP", "MIDDLE"] select (_indoor || {_distance2D > 8} || {(getSuppression _unit) isNotEqualTo 0})); // set speed [_unit, _pos] call FUNC(doAssaultSpeed); @@ -69,11 +73,11 @@ if (_distance2D < 7) then {_unit setVariable ["ace_medical_ai_lastFired", CBA_mi // execute move _unit doMove _pos; -_unit setDestination [_pos, "LEADER PLANNED", _unit distance2D _pos < 18]; +_unit setDestination [_pos, "LEADER PLANNED", _indoor]; // update variable if (RND(0.95)) then {_groupMemory deleteAt 0;}; -_groupMemory = _groupMemory select {[objNull, "VIEW", objNull] checkVisibility [eyePos _unit, (AGLToASL _x) vectorAdd [0, 0, 0.5]] isEqualTo 0}; +_groupMemory = _groupMemory select {_unit distanceSqr _x < 25 && {[objNull, "VIEW", objNull] checkVisibility [eyePos _unit, (AGLToASL _x) vectorAdd [0, 0, 0.5]] isEqualTo 0}}; // variables _group setVariable [QGVAR(groupMemory), _groupMemory, false]; diff --git a/addons/main/functions/UnitAction/fnc_doAssaultSpeed.sqf b/addons/main/functions/UnitAction/fnc_doAssaultSpeed.sqf index 815338ac..5347ec27 100644 --- a/addons/main/functions/UnitAction/fnc_doAssaultSpeed.sqf +++ b/addons/main/functions/UnitAction/fnc_doAssaultSpeed.sqf @@ -19,10 +19,10 @@ params ["_unit", ["_target", objNull]]; // speed if ((behaviour _unit) isEqualTo "STEALTH") exitWith {_unit forceSpeed 1; 1}; -private _distance = _unit distance2D _target; -if ((speedMode _unit) isEqualTo "FULL") exitWith {private _speed = [24, 3] select (_distance < 12); _unit forceSpeed _speed; _speed}; -if (_distance > 80) exitWith {_unit forceSpeed -1; -1}; -if (_distance > 6) exitWith {_unit forceSpeed 3; 3}; -if (_distance > 3) exitWith {_unit forceSpeed 2; 2}; +private _distanceSqr = _unit distanceSqr _target; +if ((speedMode _unit) isEqualTo "FULL") exitWith {private _speed = [24, 3] select (_distanceSqr < 144); _unit forceSpeed _speed; _speed}; +if (_distanceSqr > 6400) exitWith {_unit forceSpeed -1; -1}; +if (_distanceSqr > 36) exitWith {_unit forceSpeed 3; 3}; +if (_distanceSqr > 9) exitWith {_unit forceSpeed 2; 2}; _unit forceSpeed 1; 1 diff --git a/addons/main/functions/UnitAction/fnc_doCheckBody.sqf b/addons/main/functions/UnitAction/fnc_doCheckBody.sqf index 34049418..a79b4dad 100644 --- a/addons/main/functions/UnitAction/fnc_doCheckBody.sqf +++ b/addons/main/functions/UnitAction/fnc_doCheckBody.sqf @@ -22,11 +22,11 @@ params ["_unit", ["_pos", []], ["_radius", 8]]; if (_pos isEqualTo []) then {_pos = getPosASL _unit;}; // find body + rearm -private _bodies = allDeadMen findIf { (_x distance2D _pos) < _radius }; -if (_bodies isEqualTo -1) exitWith {false}; +private _weaponHolders = allDeadMen findIf { (_x distance2D _pos) < _radius }; +if (_weaponHolders isEqualTo -1) exitWith {false}; // body -private _body = allDeadMen select _bodies; +private _body = allDeadMen select _weaponHolders; // execute _unit setUnitPosWeak "MIDDLE"; @@ -37,7 +37,7 @@ _unit setVariable [QEGVAR(danger,forceMove), true]; { // condition params ["_unit", "_body"]; - (_unit distance _body < 0.7) || {!(_unit call FUNC(isAlive))} + (_unit distance _body < 0.8) || {!(_unit call FUNC(isAlive))} }, { // on near body @@ -45,6 +45,26 @@ _unit setVariable [QEGVAR(danger,forceMove), true]; if (_unit call FUNC(isAlive)) then { [QGVAR(OnCheckBody), [_unit, group _unit, _body]] call FUNC(eventCallback); _unit action ["rearm", _body]; + + // get backpack + if ((backpack _unit) isEqualTo "" && {backpack _body isNotEqualTo ""}) then { + private _items = backpackItems _body; + private _backpack = backpack _body; + removeBackpackGlobal _body; + _unit addBackpack _backpack; + {_unit addItemToBackpack _x} forEach _items; + }; + + // get launchers + if (secondaryWeapon _unit isEqualTo "") then { + private _weaponHolders = _body nearSupplies 3; + private _weapons = _weaponHolders apply {getWeaponCargo _x}; + private _index = _weapons findIf {getNumber (configFile >> "CfgWeapons" >> ((_x select 0) select 0) >> "Type") isEqualTo 4}; + if (_index isNotEqualTo -1) then { + _unit action ["TakeWeapon", _weaponHolders select _index, ((_weapons select _index) select 0) select 0]; + }; + }; + _unit doFollow leader _unit; _unit setVariable [QEGVAR(danger,forceMove), nil]; }; diff --git a/addons/main/functions/UnitAction/fnc_doDodge.sqf b/addons/main/functions/UnitAction/fnc_doDodge.sqf index b779851e..410431e1 100644 --- a/addons/main/functions/UnitAction/fnc_doDodge.sqf +++ b/addons/main/functions/UnitAction/fnc_doDodge.sqf @@ -24,6 +24,7 @@ if ( GVAR(disableAIDodge) || {!(_unit checkAIFeature "MOVE")} || {!(_unit checkAIFeature "PATH")} + || {!((currentWeapon _unit) isEqualTo (primaryWeapon _unit))} ) exitWith {false}; // dodge diff --git a/addons/main/functions/UnitAction/fnc_doFleeing.sqf b/addons/main/functions/UnitAction/fnc_doFleeing.sqf index 42300742..f3436db9 100644 --- a/addons/main/functions/UnitAction/fnc_doFleeing.sqf +++ b/addons/main/functions/UnitAction/fnc_doFleeing.sqf @@ -14,7 +14,7 @@ * * Public: No */ -#define SEARCH_FOR_HIDE 4 +#define SEARCH_FOR_HIDE 6 #define SEARCH_FOR_BUILDING 8 params ["_unit"]; @@ -39,12 +39,14 @@ _unit setVariable [QGVAR(currentTarget), objNull, GVAR(debug_functions)]; [QGVAR(OnFleeing), [_unit, group _unit]] call FUNC(eventCallback); // Abandon vehicles in need! +private _vehicle = vehicle _unit; if ( RND(0.5) && {!_onFoot} - && {canUnloadInCombat (vehicle _unit)} - && {(speed (vehicle _unit)) < 3} - && {isTouchingGround vehicle _unit} + && {morale _unit < 0} + && {canUnloadInCombat _vehicle || {_vehicle isKindOf "StaticWeapon"}} + && {(speed _vehicle) < 3} + && {isTouchingGround _vehicle} ) exitWith { [_unit] orderGetIn false; _unit setSuppression 1; // prevents instant laser aim - nkenny @@ -80,7 +82,7 @@ if (_onFootAndSeen) then { }; // calm and inside or under cover! - if ((_suppression < 0.2) && {lineIntersects [_eyePos, _eyePos vectorAdd [0, 0, 10], _unit] || {_distance2D < random 5}}) exitWith { + if ((_suppression < 0.2) && {lineIntersects [_eyePos, _eyePos vectorAdd [0, 0, 10], _unit] || {_distance2D < 15}}) exitWith { _unit setUnitPos "DOWN";// ~ this forces unit stance which may override mission maker. The effect is good however - nkenny doStop _unit; }; @@ -94,12 +96,13 @@ if (_onFootAndSeen) then { // find buildings to hide private _buildings = [_unit, SEARCH_FOR_BUILDING, true, true] call FUNC(findBuildings); - if ((_buildings isNotEqualTo []) && {_distance2D > random 5}) then { + _buildings append (_cover apply {getPos _x}); + if ((_buildings isNotEqualTo []) && {_distance2D > 5}) then { _unit doMove selectRandom _buildings; }; } else { - // follow self! ~ bugfix which prevents untis from getting stuck in fleeing loop inside fsm. - nkenny + // follow self! ~ bugfix which prevents units from getting stuck in fleeing loop inside fsm. - nkenny _unit doFollow (leader _unit); // reset diff --git a/addons/main/functions/UnitAction/fnc_doHide.sqf b/addons/main/functions/UnitAction/fnc_doHide.sqf index 94b1c89d..62f7142b 100644 --- a/addons/main/functions/UnitAction/fnc_doHide.sqf +++ b/addons/main/functions/UnitAction/fnc_doHide.sqf @@ -65,19 +65,20 @@ if (RND(0.1) && { _buildings isNotEqualTo [] }) exitWith { _unit setUnitPosWeak "DOWN"; // check for rear-cover -private _cover = nearestTerrainObjects [ _unit getPos [1, getDir _unit], ["BUSH", "TREE", "SMALL TREE", "HIDE", "ROCK", "WALL", "FENCE"], 9, true, true ]; +private _cover = nearestTerrainObjects [ _unit getPos [1, getDir _unit], ["BUSH", "TREE", "SMALL TREE", "HIDE", "ROCK", "WALL", "FENCE"], 15, true, true ]; // targetPos private _targetPos = if (_cover isEqualTo []) then { _unit getPos [10 + random _range, (_pos getDir _unit) + 45 - random 90] } else { - (_cover select 0) getPos [-1.2, _unit getDir (_cover select 0)] + (_cover select 0) getPos [-0.6, _unit getDir (_cover select 0)] }; // water means hold if (surfaceIsWater _targetPos) then {_targetPos = getPosATL _unit;}; // cover move +doStop _unit; _unit doMove _targetPos; // debug diff --git a/addons/main/functions/UnitAction/fnc_doSmoke.sqf b/addons/main/functions/UnitAction/fnc_doSmoke.sqf index 095de899..a9567a71 100644 --- a/addons/main/functions/UnitAction/fnc_doSmoke.sqf +++ b/addons/main/functions/UnitAction/fnc_doSmoke.sqf @@ -20,7 +20,7 @@ params [ ["_unit", objNull, [grpNull, objNull, []]], ["_pos", [], [[]]], - ["_type", 6, [0]] + ["_type", 4, [0]] ]; // single unit @@ -38,27 +38,18 @@ if (_magazines isEqualTo []) exitWith {false}; // find smoke shell private _smokeshell = _magazines findIf { - private _ammo = getText (configfile >> "CfgMagazines" >> _x >> "Ammo"); - private _aiAmmoUsage = getNumber (configfile >> "CfgAmmo" >> _ammo >> "aiAmmoUsageFlags"); - _aiAmmoUsage isEqualTo _type + [_x, _type] call FUNC(checkMagazineAiUsageFlags); }; // select smoke if (_smokeshell == -1) exitWith {false}; _smokeshell = (_magazines select _smokeshell); -// get muzzle -- This is where Joko could do some fancy caching ~ nkenny -private _muzzleList = "true" configClasses (configFile >> "cfgWeapons" >> "throw"); - -private _muzzle = _muzzleList findIf { - - private _compatible = getArray (configFile >> "cfgWeapons" >> "throw" >> configName _x >> "magazines"); - _smokeshell in _compatible -}; +// get muzzle +private _muzzle = _smokeshell call FUNC(getCompatibleThrowMuzzle); // select muzzle -if (_muzzle == -1) exitWith {false}; -_muzzle = configName (_muzzleList select _muzzle); +if (_muzzle isEqualTo "") exitWith {false}; _unit setVariable [QGVAR(currentTarget), objNull, GVAR(debug_functions)]; // turn towards target diff --git a/addons/main/functions/UnitAction/fnc_doUGL.sqf b/addons/main/functions/UnitAction/fnc_doUGL.sqf index 6357ab6d..8be7dc3f 100644 --- a/addons/main/functions/UnitAction/fnc_doUGL.sqf +++ b/addons/main/functions/UnitAction/fnc_doUGL.sqf @@ -48,7 +48,7 @@ private _unit = _units findIf { private _index = _findFlares findIf { private _ammo = getText (configfile >> "CfgMagazines" >> _x >> "Ammo"); private _flareSimulation = getText (configfile >> "CfgAmmo" >> _ammo >> "simulation"); - _flareSimulation isEqualTo _type + (_flareSimulation find _type) isNotEqualTo -1 }; if (_index == -1) exitWith {false}; diff --git a/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf b/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf index 7eb5ff03..44c4d267 100644 --- a/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf +++ b/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf @@ -46,13 +46,17 @@ if (_buildings isNotEqualTo []) then { }; // add predicted location -- just to ensure shots fired! -if (_buildings isEqualTo []) then {_buildings pushBack _predictedPos;}; +if (_buildings isEqualTo []) then { + _predictedPos = ASLtoAGL (ATLtoASL _predictedPos); + if ((_predictedPos select 2) > 6) then {_predictedPos set [2, 0.5]}; + _buildings pushBack _predictedPos; +}; // pos _pos = selectRandom _buildings; // look at position -_vehicle doWatch _pos; +_vehicle doWatch (AGLtoASL _pos); // suppression private _suppression = [_unit, _pos] call FUNC(doVehicleSuppress); diff --git a/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf b/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf index ac8fc39e..def69989 100644 --- a/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf +++ b/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf @@ -23,24 +23,25 @@ params ["_unit", ["_target", []], ["_threshold", 18]]; if (_target isEqualTo []) then { - _target = getPosATL (_unit findNearestEnemy _unit); + _target = _unit getHideFrom (_unit findNearestEnemy _unit); }; +if (_target isEqualTo [0, 0, 0] || {_unit distanceSqr _target < 2}) exitWith {false}; // cannot move or moving -if (!canMove _unit || {currentCommand _unit isEqualTo "MOVE"}) exitWith {true}; +if (!canMove _unit || {currentCommand _unit isEqualTo "MOVE"}) exitWith {false}; -// CQB tweak -- look instead -if (_unit distance _target < 75) exitWith { - (vehicle _unit) doWatch _target; - true +// CQB tweak -- target within 75m - look instead +if (_unit distanceSqr _target < 5625) exitWith { + (vehicle _unit) doWatch (ATLtoASL _target); + false }; _unit setVariable [QGVAR(currentTarget), _target, GVAR(debug_functions)]; _unit setVariable [QGVAR(currentTask), "Vehicle Rotate", GVAR(debug_functions)]; -// within acceptble limits -- suppress instead +// within acceptble limits if (_unit getRelDir _target < _threshold || {_unit getRelDir _target > (360-_threshold)}) exitWith { - true + false }; // settings diff --git a/addons/main/functions/fnc_checkMagazineAiUsageFlags.sqf b/addons/main/functions/fnc_checkMagazineAiUsageFlags.sqf new file mode 100644 index 00000000..12ce0869 --- /dev/null +++ b/addons/main/functions/fnc_checkMagazineAiUsageFlags.sqf @@ -0,0 +1,37 @@ +#include "script_component.hpp" +/* + * Author: joko // Jonas + * Checks if a given ammo has a aiUsageFlagSet + * + * Arguments: + * 0: Ammo + * 1: Flags + * + * Return Value: + * boolean + * + * Example: + * "SmokeShell" call lambs_main_fnc_checkMagazineAiUsageFlags; + * + * Public: Yes +*/ + +if (isNil QGVAR(aiUsageFlagCache)) then { + GVAR(aiUsageFlagCache) = createHashMap; +}; + +params [["_magazine", ""], ["_flags", 0]]; + +private _hasFlags = GVAR(aiUsageFlagCache) get _magazine; +if (!isNil "_hasFlags") exitWith { + _hasFlags +}; + +// find smoke shell +private _ammo = getText (configfile >> "CfgMagazines" >> _magazine >> "Ammo"); +private _aiAmmoUsage = getNumber (configfile >> "CfgAmmo" >> _ammo >> "aiAmmoUsageFlags"); +_hasFlags = [_aiAmmoUsage, _flags] call BIS_fnc_bitflagsCheck; + +GVAR(aiUsageFlagCache) set [_magazine, _hasFlags]; + +_hasFlags; \ No newline at end of file diff --git a/addons/main/functions/fnc_doCallout.sqf b/addons/main/functions/fnc_doCallout.sqf index 1a094097..e012d36f 100644 --- a/addons/main/functions/fnc_doCallout.sqf +++ b/addons/main/functions/fnc_doCallout.sqf @@ -82,9 +82,6 @@ if (isNil "_cachedSounds") then { if (_sound select [0, 1] != "\") then { _sound = (getArray (configFile >> "CfgVoice" >> _speaker >> "directories") select 0) + _sound; }; - if (_sound select [0, 1] == "\") then { - _sound = _sound select [1]; - }; }; _cachedSounds set [_forEachIndex, _sound]; } forEach _cachedSounds; @@ -107,7 +104,7 @@ if (_cachedSounds isEqualTo []) exitWith { }; private _sound = selectRandom _cachedSounds; -playSound3D [_sound, _unit, isNull (objectParent _unit), getPosASL _unit, 5, pitch _unit, _distance]; +playSound3D [_sound, _unit, isNull (objectParent _unit), eyePos _unit, 5, pitch _unit, _distance]; [_unit, true] remoteExecCall ["setRandomLip", 0]; [{ _this remoteExecCall ["setRandomLip", 0]; diff --git a/addons/main/functions/fnc_doShareInformation.sqf b/addons/main/functions/fnc_doShareInformation.sqf index 16147c3a..44a4ae1d 100644 --- a/addons/main/functions/fnc_doShareInformation.sqf +++ b/addons/main/functions/fnc_doShareInformation.sqf @@ -64,7 +64,7 @@ if !(isNull _target) then { private _knowsAbout = (_unit knowsAbout _target) min GVAR(maxRevealValue); { [_x, [_target, _knowsAbout]] remoteExec ["reveal", leader _x]; - } forEach _groups; + } forEach (_groups select {_unit distance2D (leader _x) < GVAR(combatShareRange)}); }; [QGVAR(OnInformationShared), [_unit, group _unit, _target, _groups]] call FUNC(eventCallback); @@ -81,17 +81,20 @@ if ( // debug if (EGVAR(main,debug_functions)) then { // debug message - ["%1 share information (%2 knows %3 to %4 groups @ %5m range)", side _unit, name _unit, (_unit knowsAbout _target) min 1, count _groups, round _range] call FUNC(debugLog); + ["%1 share information (%2 knows %3 to %4 groups @ %5m range)", side _unit, name _unit, (_unit knowsAbout _target) min GVAR(maxRevealValue), count _groups, round _range] call FUNC(debugLog); // debug marker - private _zm = [_unit, [_range,_range], _unit call FUNC(debugMarkerColor), "Border"] call FUNC(zoneMarker); - private _markers = [_zm]; + private _zm = [_unit, [_range, _range], _unit call FUNC(debugMarkerColor), "Border"] call FUNC(zoneMarker); + private _zmm = [_unit, [_range min GVAR(combatShareRange), _range min GVAR(combatShareRange)], _unit call FUNC(debugMarkerColor), "SolidBorder"] call FUNC(zoneMarker); + _zmm setMarkerAlphaLocal 0.3; + private _markers = [_zm, _zmm]; // enemy units { private _m = [_unit getHideFrom _x, "", _x call FUNC(debugMarkerColor), "mil_triangle"] call FUNC(dotMarker); _m setMarkerSizeLocal [0.5, 0.5]; _m setMarkerDirLocal (getDir _x); + _m setMarkerTextLocal str (_unit knowsAbout _x); _markers pushBack _m; } foreach ((units _target) select {_unit knowsAbout _x > 0}); diff --git a/addons/main/functions/fnc_findBuildings.sqf b/addons/main/functions/fnc_findBuildings.sqf index ef6dbd49..f9dca8fc 100644 --- a/addons/main/functions/fnc_findBuildings.sqf +++ b/addons/main/functions/fnc_findBuildings.sqf @@ -27,7 +27,7 @@ params [ // houses private _houses = nearestObjects [_unit, ["House", "Strategic", "Ruins"], _range, true]; -_houses = _houses select {((_x buildingPos -1) isNotEqualTo [])}; +_houses = _houses select {((_x buildingPos -1) isNotEqualTo []) && {(alive _x) && !(isObjectHidden _x)}}; // find house positions if (!_useHousePos) exitWith {_houses}; // return if not use House Pos @@ -37,10 +37,10 @@ private _housePos = []; _housePos append (_house buildingPos -1); if (_findDoors) then { { - if ("door" in toLower (_x)) then { + if ("door" in _x) then { _housePos pushBack (_house modelToWorld (_house selectionPosition _x)); }; - } forEach (selectionNames _house); + } forEach (_house selectionNames "viewgeometry"); }; } forEach _houses; diff --git a/addons/main/functions/fnc_findCover.sqf b/addons/main/functions/fnc_findCover.sqf index ac35434d..67d90481 100644 --- a/addons/main/functions/fnc_findCover.sqf +++ b/addons/main/functions/fnc_findCover.sqf @@ -99,11 +99,7 @@ if (GVAR(debug_functions) && {(_ret isNotEqualTo [])}) then { private _add = if ((_x select 1) isEqualTo "UP") then { 2 } else { - if ((_x select 1) isEqualTo "MIDDLE") then { - 1 - } else { - 0.2 - }; + [0.2, 1] select (_x select 1 isEqualTo "MIDDLE"); }; "Sign_Arrow_Large_Blue_F" createVehicleLocal ((_x select 0) vectorAdd [0, 0, _add]); } forEach _ret; diff --git a/addons/main/functions/fnc_findReadyVehicles.sqf b/addons/main/functions/fnc_findReadyVehicles.sqf index 0c7e7233..d84991ca 100644 --- a/addons/main/functions/fnc_findReadyVehicles.sqf +++ b/addons/main/functions/fnc_findReadyVehicles.sqf @@ -25,6 +25,7 @@ private _vehicles = (units _unit) select { (_unit distance2D _x) < _range && { !(isNull objectParent _x) } && { canFire vehicle _x } + && { (magazines vehicle _x) isNotEqualTo [] } && { isTouchingGround vehicle _x } }; diff --git a/addons/main/functions/fnc_getCompatibleThrowMuzzle.sqf b/addons/main/functions/fnc_getCompatibleThrowMuzzle.sqf new file mode 100644 index 00000000..10f2753f --- /dev/null +++ b/addons/main/functions/fnc_getCompatibleThrowMuzzle.sqf @@ -0,0 +1,42 @@ +#include "script_component.hpp" +/* + * Author: joko // Jonas + * Finds a Compatible Throwing Muzzle for a given Throwing Weapon + * + * Arguments: + * 0: Magazine + * + * Return Value: + * String: Muzzle Classname + * + * Example: + * "SmokeShell" call lambs_main_fnc_getCompatibleThrowMuzzle; + * + * Public: Yes +*/ +params [["_magazine", "", [""]]]; + +if (isNil QGVAR(cachedThrowingWeapons)) then { + GVAR(cachedThrowingWeapons) = "true" configClasses (configFile >> "cfgWeapons" >> "throw"); + GVAR(cachedThrowingWeaponsHash) = createHashMap; +}; + +private _muzzle = GVAR(cachedThrowingWeaponsHash) get _magazine; +if (!isNil "_muzzle") exitWith { + _muzzle; +}; + +private _muzzleIdx = GVAR(cachedThrowingWeapons) findIf { + private _compatible = getArray (_x >> "magazines"); + _magazine in _compatible +}; + +if (_muzzleIdx == -1) then { + _muzzle = ""; +} else { + _muzzle = GVAR(cachedThrowingWeapons) select _muzzleIdx; +}; + +GVAR(cachedThrowingWeaponsHash) set [_magazine, _muzzle]; + +_muzzle \ No newline at end of file diff --git a/addons/main/functions/fnc_getShareInformationParams.sqf b/addons/main/functions/fnc_getShareInformationParams.sqf index 05d77f85..0acd584d 100644 --- a/addons/main/functions/fnc_getShareInformationParams.sqf +++ b/addons/main/functions/fnc_getShareInformationParams.sqf @@ -38,10 +38,10 @@ private _units = units _unit select { && {_x call FUNC(isAlive)} }; private _index = _units findIf { - _x getVariable [QEGVAR(danger,dangerRadio), false] - || {(!isNull objectParent _x && {_x distance2D _unit < 70})} - || {"b_radiobag_01_" in (toLower backpack _x)} - || {(getNumber (configFile >> "CfgVehicles" >> (backpack _x) >> "tf_hasLRradio")) isEqualTo 1} + _x getVariable [QEGVAR(danger,dangerRadio), false] + //|| {(!isNull objectParent _x && {_x distance2D _unit < 70})} + || {"b_radiobag_01_" in (toLower backpack _x)} + || {(getNumber (configFile >> "CfgVehicles" >> (backpack _x) >> "tf_hasLRradio")) isEqualTo 1} }; _radio = _index isNotEqualTo -1; if (_radio) then { diff --git a/addons/main/functions/fnc_isIndoor.sqf b/addons/main/functions/fnc_isIndoor.sqf index 776a26a9..104e5410 100644 --- a/addons/main/functions/fnc_isIndoor.sqf +++ b/addons/main/functions/fnc_isIndoor.sqf @@ -10,7 +10,7 @@ * unit indoor or not * * Example: - * [bob] call lambs_main_fnc_inside; + * [bob] call lambs_main_fnc_isIndoor; * * Public: No */ diff --git a/addons/main/functions/fnc_showDialog.sqf b/addons/main/functions/fnc_showDialog.sqf index a8af3956..a0d81820 100644 --- a/addons/main/functions/fnc_showDialog.sqf +++ b/addons/main/functions/fnc_showDialog.sqf @@ -1,5 +1,5 @@ #include "script_component.hpp" -#include "\a3\ui_f\hpp\definedikcodes.inc" +#include "\a3\ui_f\hpp\defineDIKCodes.inc" /* * Author: joko // Jonas * Parses Data from UI Elements from Show Dialog @@ -157,7 +157,7 @@ private _fnc_AddBoolean = { }; private _fnc_AddDropDown = { - params ["_text", "", ["_tooltip", ""], ["_values", [], []], ["_default", 0, [0]]]; + params ["_text", "", ["_tooltip", ""], ["_values", [], [[]]], ["_default", 0, [0]]]; if (isLocalized _tooltip) then { _tooltip = localize _tooltip; }; diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index e15faaba..3e239305 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ -#define MAJOR 0 -#define MINOR 0 -#define PATCHLVL 0 +#define MAJOR 2 +#define MINOR 6 +#define PATCHLVL 1 #define BUILD 0 diff --git a/addons/main/settings.sqf b/addons/main/settings.inc.sqf similarity index 100% rename from addons/main/settings.sqf rename to addons/main/settings.inc.sqf diff --git a/addons/main/stringtable.xml b/addons/main/stringtable.xml index 7f4a12ad..5978b2b1 100644 --- a/addons/main/stringtable.xml +++ b/addons/main/stringtable.xml @@ -156,7 +156,7 @@ Kiedy opcja nie jest zaznaczona, pozwala pojazdowi samemu wybrać amunicję pasującą do rodzaju przeciwnika. Np. AP przeciwko celom opancerzonym, HE przeciwko celom nieopancerzonym Wenn diese Option deaktiviert ist, kann das Fahrzeug autonom den Munitionstyp zugunsten des aktuellen Ziels wechseln. Z.B. AP gegen gepanzerte Ziele, HE gegen ungepanzerte Quando non è selezionato, consente al veicolo di cambiare autonomamente il tipo di munizione in favore del bersaglio attuale. Ad esempio, AP contro bersagli corazzati, HE contro quelli non corazzati - 未选中时允许车辆自动切换弹药类型以对抗当前目标.例如,AP 对抗装甲目标,HE 对抗无装甲目标 + 未选中时允许车辆自动切换弹药类型以对抗当前目标.例如,AP对抗装甲目标,HE对抗无装甲目标 Debug @@ -210,7 +210,7 @@ Debug Civ Отладка Civ Debug Civile - 调试平民 + Debug平民 Shows FSM debug messages for civilians @@ -300,7 +300,7 @@ Dystans na którym AI może komunikować się bez pomocy radia Дальность на которой ИИ обмениваются информацией без радио Le unità IA di portata condividono le informazioni senza radio - 在范围内的 AI 单位无需无线电即可共享信息 + 在范围内的AI单位无需无线电即可共享信息 Base West @@ -390,7 +390,7 @@ Maksymalna wartość „knowsAbout” dzielona między jednostki.\nUstawienie tej wartości większej niż 1 może spowodować, że odlegli sojusznicy przejdą w tryb zagrożenia. Максимальное значение "knowsAbout", разделяемое между группами.\nНастройка больше 1 может привести к тому, что союзники на далеком расстоянии перейдут в режим полной опасности. Valore massimo 'knowsAbout' condiviso tra i gruppi.\nL'impostazione maggiore di 1 può far sì che gli alleati distanti entrino in modalità di pericolo completo. - 组之间共享的最大“knowsAbout”.\n设置大于 1 可能会导致远处的盟友进入完全危险模式. + 组之间共享的最大“knowsAbout”.\n设置大于1可能会导致远处的盟友进入完全危险模式. Range combat mode is shared @@ -408,7 +408,7 @@ Дружественные группы в пределах досягаемости будут настроены на боевое поведение. Юниты в боевом режиме будут искать укрытие и и поворачиваются к ближайшей известной угрозе. Verbündete Gruppen in Reichweite wechseln in den Kampfmodus. Einheiten im Kampfmodus suchen Deckung, Verstecken und wenden sich der nächsten bekannten Bedrohung zu. I gruppi amici nel raggio d'azione saranno impostati per combattere il comportamento. Le unità in modalità combattimento cercheranno copertura e occultamento e si rivolgeranno alla minaccia nota più vicina. - 射程内的友好团体将被设置为战斗行为.在战斗模式下,单位将寻找掩护和隐藏,并转向最近的已知威胁. + 射程内的友好团体将被设置为战斗行为.在战斗模式下,单位将寻找掩护和隐藏,并转向最近的已知威胁. Settings Suppression @@ -453,7 +453,7 @@ Poniżej tej odległości AI nie strzela ogniem zaporowym На этом расстоянии ИИ не будет вести огонь на подавление Se il bersaglio o un ostacolo si trova entro questa distanza, l'IA non eseguirà il fuoco di soppressione - 如果目标或障碍物在此距离内,AI 将不会执行火力压制 + 如果目标或障碍物在此距离内,AI将不会执行火力压制 Minimum safe zone for Suppression Fire @@ -487,7 +487,7 @@ Wyświetla informacje dla wszystkich jednostek na pokładzie pojazdu. Domyślnie pokazuje tylko dla dowódcy. (Funkcja wymaga włączonej opcji Debug Draw) Zeichnet Informationsbanner für alle in Fahrzeugen sitzenden Einheiten. Standard zeigt nur den effektiven Kommandanten an. (Funktion erfordert aktiviertes Debug Zeichnen) Disegna banner informativi per tutte le unità imbarcate sui veicoli. L'impostazione predefinita mostra solo il comandante effettivo. (La funzione richiede l'attivazione di Debug Draw) - 为载具内的所有单位绘制信息标语.默认值仅显示有效的指挥官.(功能需要启用Debug Draw) + 为载具内的所有单位绘制信息标语.默认值仅显示有效的指挥官.(功能需要启用Debug Draw) Min Obstacle Proximity Distance diff --git a/addons/wp/XEH_preInit.sqf b/addons/wp/XEH_preInit.sqf index 4b100e8f..7ced66ec 100644 --- a/addons/wp/XEH_preInit.sqf +++ b/addons/wp/XEH_preInit.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" ADDON = false; -#include "settings.sqf" +#include "settings.inc.sqf" #include "XEH_PREP.hpp" if (isServer) then { diff --git a/addons/wp/ZEN_CfgContext.hpp b/addons/wp/ZEN_CfgContext.hpp index 976b84a4..80617c14 100644 --- a/addons/wp/ZEN_CfgContext.hpp +++ b/addons/wp/ZEN_CfgContext.hpp @@ -5,38 +5,38 @@ class ZEN_context_menu_actions { priority = 3; class CreateTarget { displayName = CSTRING(Context_CreateTarget); - statement = QUOTE([ARR_2(_objects, _position)] call FUNC(setTarget)); + statement = QUOTE([ARR_2(_objects,_position)] call FUNC(setTarget)); icon = "\a3\3den\Data\CfgWaypoints\destroy_ca.paa"; }; class TaskArtilleryRegister { displayName = CSTRING(Module_TaskArtilleryRegister_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setArtilleryRegister)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setArtilleryRegister)); icon = "\A3\ui_f\data\igui\cfg\simpleTasks\types\intel_ca.paa"; }; class TaskCamp { displayName = CSTRING(Module_TaskCamp_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setCamp)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setCamp)); icon = "\a3\3DEN\Data\CfgWaypoints\Guard_ca.paa"; }; class TaskCQB { displayName = CSTRING(Module_TaskCQB_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setCQB)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setCQB)); icon = "\a3\3DEN\Data\CfgWaypoints\Scripted_ca.paa"; }; class TaskGarrison { displayName = CSTRING(Module_TaskGarrison_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setGarrison)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setGarrison)); icon = "\a3\3DEN\Data\CfgWaypoints\Guard_ca.paa"; }; class TaskPatrol { displayName = CSTRING(Module_TaskPatrol_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setPatrol)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setPatrol)); icon = "\A3\3DEN\Data\CfgWaypoints\Loiter_ca.paa"; }; class TaskReset { displayName = CSTRING(Module_TaskReset_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setReset)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setReset)); icon = "\a3\3DEN\Data\CfgWaypoints\cycle_ca.paa"; }; }; @@ -46,17 +46,17 @@ class ZEN_context_menu_actions { condition = QUOTE((_groups isNotEqualTo []) || (_objects isNotEqualTo [])); class TaskCreep { displayName = CSTRING(Module_TaskCreep_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setCreep)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setCreep)); icon = "\a3\3DEN\Data\CfgWaypoints\Sentry_ca.paa"; }; class TaskHunt { displayName = CSTRING(Module_TaskHunt_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setHunt)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setHunt)); icon = "\a3\3DEN\Data\CfgWaypoints\Sentry_ca.paa"; }; class TaskRush { displayName = CSTRING(Module_TaskRush_DisplayName); - statement = QUOTE([ARR_2(_groups, _objects)] call FUNC(setRush)); + statement = QUOTE([ARR_2(_groups,_objects)] call FUNC(setRush)); icon = "\a3\3DEN\Data\CfgWaypoints\Sentry_ca.paa"; }; }; diff --git a/addons/wp/functions/fnc_doArtillery.sqf b/addons/wp/functions/fnc_doArtillery.sqf index 8cc45115..1fd1df78 100644 --- a/addons/wp/functions/fnc_doArtillery.sqf +++ b/addons/wp/functions/fnc_doArtillery.sqf @@ -45,10 +45,14 @@ if !(canFire _gun && {(_caller call EFUNC(main,isAlive))}) exitWith { // turn gun _gun doWatch _pos; +// set group task +(group _gun) setVariable [QEGVAR(main,currentTactic), "taskArtillery", EGVAR(main,debug_functions)]; + // settings private _direction = _gun getDir _pos; private _center = _pos getPos [_accuracy * 0.33, -_direction]; private _offset = 0; +private _salvo = 1; // heavier artillery fires more rounds, more accurately if !((vehicle _gun) isKindOf "StaticMortar") then { @@ -56,6 +60,24 @@ if !((vehicle _gun) isKindOf "StaticMortar") then { _accuracy = _accuracy * 0.5; }; +// MRLS weapons fire almost entire magazine, but with less accuracy +private _isMLRS = _gun getVariable [QEGVAR(main,isArtilleryMRLS), false]; +if (_isMLRS) then { + _skipCheckrounds = true; + _salvo = (gunner _gun) Ammo (currentMuzzle (gunner _gun)); + _rounds = 1; + if ((_salvo mod 6) isEqualTo 0) then { + _rounds = floor (_salvo * 0.334); + _salvo = 3; + }; + if ((_salvo mod 10) isEqualTo 0) then { + if (_salvo > 20) then {_salvo = 20;}; + _rounds = floor (_salvo * 0.2); + _salvo = 5; + }; + _accuracy = _accuracy * 1.5; +}; + private _ammo = (getArtilleryAmmo [_gun]) param [0, ""]; private _time = _gun getArtilleryETA [_center, _ammo]; @@ -137,7 +159,7 @@ if (canFire _gun && {(_caller call EFUNC(main,isAlive))}) then { if (_target inRangeOfArtillery [[_gun], _ammo]) then { // fire round - _gun commandArtilleryFire [_target, _ammo, 1]; + _gun commandArtilleryFire [_target, _ammo, _salvo]; // debug if (EGVAR(main,debug_functions)) then { @@ -146,7 +168,9 @@ if (canFire _gun && {(_caller call EFUNC(main,isAlive))}) then { }; // waituntil + if (_isMLRS) then {sleep 1.3;}; waitUntil {unitReady _gun}; + } else { if (EGVAR(main,debug_functions)) then { ["Error Target position is not reachable with artillery"] call EFUNC(main,debugLog); @@ -156,7 +180,7 @@ if (canFire _gun && {(_caller call EFUNC(main,isAlive))}) then { // debug if (EGVAR(main,debug_functions)) then { - ["%1 Artillery strike complete: %2 fired %3 shots at %4m", side _gun, getText (configOf _gun >> "displayName"), _rounds, round (_gun distance2D _pos)] call EFUNC(main,debugLog); + ["%1 Artillery strike complete: %2 fired %3 shots at %4m", side _gun, getText (configOf _gun >> "displayName"), _rounds * _salvo, round (_gun distance2D _pos)] call EFUNC(main,debugLog); }; }; @@ -172,5 +196,8 @@ if (_markerList isNotEqualTo []) then { // delay sleep _checkRounds; +// set group task +(group _gun) setVariable [QEGVAR(main,currentTactic), nil, EGVAR(main,debug_functions)]; + // ready up again [QGVAR(RegisterArtillery), [_gun]] call CBA_fnc_serverEvent; diff --git a/addons/wp/functions/fnc_taskArtilleryRegister.sqf b/addons/wp/functions/fnc_taskArtilleryRegister.sqf index a417b4a8..bffba3a6 100644 --- a/addons/wp/functions/fnc_taskArtilleryRegister.sqf +++ b/addons/wp/functions/fnc_taskArtilleryRegister.sqf @@ -34,6 +34,26 @@ private _artillery = []; private _artillery = _artillery select { getNumber (configOf _x >> "artilleryScanner") > 0 }; if (_artillery isEqualTo []) exitWith {false}; +// check for MLRS +{ + private _assignedRoles = assignedVehicleRole (gunner _x); + + // gunner doesn't have a proper turret! + if ((count _assignedRoles) < 2) then { + _x setVariable [QEGVAR(main,isArtilleryMRLS), false]; + } else { + // get the callout for what this vehicle shoots! + private _turretPath = _assignedRoles select 1; + private _turret = (_x weaponsTurret _turretPath) select 0; + private _nameSound = getText (configFile >> "CfgWeapons" >> _turret >> "nameSound"); + if (_nameSound isEqualTo "rockets") then { + _x setVariable [QEGVAR(main,isArtilleryMRLS), true]; + } else { + _x setVariable [QEGVAR(main,isArtilleryMRLS), false]; + }; + }; +} forEach _artillery; + // add to faction global [QGVAR(RegisterArtillery), _artillery] call CBA_fnc_serverEvent; diff --git a/addons/wp/modules.hpp b/addons/wp/modules.hpp index ea39a8d4..c50efa5c 100644 --- a/addons/wp/modules.hpp +++ b/addons/wp/modules.hpp @@ -606,7 +606,6 @@ class GVAR(TaskRush) : GVAR(BaseModule) { validate = "number"; condition = "0"; typeName = "NUMBER"; - defaultValue = TASK_RUSH_CYCLETIME; }; class ModuleDescription: ModuleDescription {}; }; diff --git a/addons/wp/settings.sqf b/addons/wp/settings.inc.sqf similarity index 100% rename from addons/wp/settings.sqf rename to addons/wp/settings.inc.sqf diff --git a/addons/wp/stringtable.xml b/addons/wp/stringtable.xml index 8bb42cc5..5cb353ed 100644 --- a/addons/wp/stringtable.xml +++ b/addons/wp/stringtable.xml @@ -17,7 +17,7 @@ Pojazd będzie automatycznie zarejestrowany jako dostępna artyleria do dynamicznych ataków Машина будет автоматически зарегистрирована как доступная артиллерия для динамических ударов. Il veicolo verrà automaticamente registrato come artiglieria disponibile per attacchi dinamici - 车辆将自动指示为可用于动态打击的火炮 + 载具将为具有动态击打的火炮提供自动指示 Dynamic Target @@ -44,7 +44,7 @@ Ta pozycja będzie ostrzelana przez pierwszą dostępną artylerię po danej stronie. Artyleria musi być zarejestrowana dla strony i być w zasięgu. Это место нацелено на первую доступную артиллерийскую установку с юнитом данной стороны. Юнит Артиллерии должен зарегистрирован за сторону и находиться в пределах досягаемости залпа Questa posizione è presa di mira dalla prima unità di artiglieria disponibile di un dato lato. L'unità di artiglieria deve essere registrata a lato ed essere a distanza di tiro - 该位置是给定一方的第一个可用炮兵部队的目标.炮兵部队必须在一方指示并在打击距离内 + 该位置是给定一方的第一个可用炮兵部队的目标.炮兵部队必须在一方指示并在击打距离内 Side @@ -74,13 +74,8 @@ 主炮齐射 - Number of rounds in the main salvo - Počet střel v hlavní salvě - Anzahl an Schüssen der Hauptsalve. - Liczba pocisków w głównej salwie - Количество снарядов в главном залпе - Numero di colpi nella salva principale - 主炮齐射的炮弹回合 + Number of rounds in the main salvo. MLRS artillery ignore this value. + Anzahl an Schüssen der Hauptsalve. MLRS-Artillerie ignoriert diesen Wert. Spread @@ -89,7 +84,7 @@ Rozrzut Разброс Propagazione - 扩散 + 散布 Default dispersion of the main salvo @@ -277,7 +272,7 @@ Zadanie - Obóz sprawia, że przydzielone jednostki gromadzą się wokół jednego punktu, zazwyczaj obozu. Niektóre jednostki mogą się oddzielić, żeby obsadzić broń statyczną, garnizonować budynki lub patrolować teren. <br\> Ustaw obszar w 3DEN. Задание лагерь создает впечатление, что отряд собирается вокруг одной точки, обычно лагеря. Некоторые юниты будут садиться за стационарное оружие, входить в здания и патрулировать территорию. Compito magazzino fa sembrare che l'unità si raccolga intorno a un singolo punto, in genere un campeggio. Alcune unità si sposteranno per utilizzare armi statiche, presidiare edifici e pattugliare l'area.<br/>Imposta l'area in 3DEN. - 营地任务使单位看起来聚集在一个点周围,通常是一个露营地。 一些单位会离开以操作静态武器、驻军建筑物并在该区域巡逻.<br/>gt;在 3DEN 中设置区域. + 营地任务使单位看起来聚集在一个点周围,通常是一个露营地.一些单位会离开以操作静态武器、驻军建筑物并在该区域巡逻.<br/>gt;在3DEN中设置区域. Radius @@ -376,7 +371,7 @@ Gdy dynamiczne centrum jest widoczne, jest możliwe, żeby poruszać centralnym punktem przeszukiwania budynku. При наличии динамического центра можно перемещать центральную точку шаблона поиска здания. Con il centro dinamico presente, è possibile spostare il punto centrale del pattern di ricerca dell'edificio - 在存在动态中心的情况下,可以移动建筑物搜索模式的中心点 + 在存在动态中心的情况下,可以移动建筑物搜索模式的中心点 Radius @@ -403,7 +398,7 @@ Zadanie - CQB pozwala jednostkom przeszukiwać budynki w okolicy. Ustaw zasięg modułu w 3DEN, żeby konfigurować obszar przeszukiwania. Moduł można przesunąć, żeby dynamicznie zmieniać przeszukiwany obszar. <br\> <br\> Moduł działa najlepiej na małym obszarze. Wskazane jest użycie wielu modułów o małym obszarze działania i połączenie ich w jedną trasę. Задача CQB заставляет юнит обыскивать постройки в данной области. Установите размер модуля в 3DEN, чтобы настроить область поиска. Модуль можно перемещать, чтобы динамически перемещать область поиска. <br\> <br\> В целом модуль лучше всего работает с меньшим AOE. Лучше связать несколько модулей или путевых точек вместе, чем иметь один массив. Группы одной стороны поделятся информацией, какие здания были зачищены, а какие еще требуют поиска. Il compito CQB fa sì che l'unità cerchi gli edifici con l'area. Imposta la dimensione del modulo in 3DEN per configurare l'area di ricerca. Il modulo può essere spostato per spostare dinamicamente l'area di ricerca.<br/><br/>In generale il modulo funziona meglio con un AOE più piccolo. Meglio mettere insieme più moduli o waypoint piuttosto che averne uno enorme. I gruppi dello stesso lato condivideranno quali edifici sono stati sgomberati e quali devono ancora essere perquisiti. - 指派任务 CQB 使单位搜索该区域的建筑物. 在 3DEN 中设置模块大小以配置搜索区域. 可以移动模块以动态移动搜索区域.<br/><br/>通常,该模块在较小的 AOE 下效果最佳.将多个模块或路径点串在一起比一个庞大的模块或航路点更好.同一方的小组将共享哪些建筑物已被清除哪些仍需要搜索. + 指派任务CQB使单位搜索该区域的建筑物. 在3DEN中设置模块大小以配置搜索区域. 可以移动模块以动态移动搜索区域.<br/><br/>通常,该模块在较小的AOE下效果最佳.将多个模块或路径点串在一起比一个庞大的模块或航路点更好.同一方的小组将共享哪些建筑物已被清除哪些仍需要搜索. Task Garrison @@ -475,7 +470,7 @@ Trigger zakończenia Выйти из триггера Esci dal grilletto - 离开起因 + 离开的诱因 The condition for units to leave their garrisoned position.\nOptions are being hit, shooting own weapon, hearing enemy fire or all of them. Default is random. @@ -493,7 +488,7 @@ Zadanie - Garnizon pozwala jednostkom znajdującym się na obszarze określonym przez moduł, zajmować pozycje w domach i obsadzać broń stacjonarną. Задача занятие позиций заставляет юниты занимать позиции в зданиях и управлять доступными турелями и статическим оружием в пределах области, определяемой атрибутами 3DEN Compito Guarnigione fa sì che l'unità prenda posizione negli edifici e metta a disposizione torrette e armi statiche all'interno di un'area definita dagli attributi 3DEN. - 驻军任务使该单位占据建筑物中的位置并在由 3DEN 属性定义的区域内配备可用的火炮和静态武器. + 驻军任务使该单位占据建筑物中的位置并在由3DEN属性定义的区域内配备可用的火炮和静态武器. Dynamic patrol @@ -511,7 +506,7 @@ Отряд создаст подгруппу для патрулирования местности.\nNB: патруль покинет свою первоначальную группу, чтобы сформировать новую. Die Einheit erstellt eine Untergruppe, um das Gebiet zu patrouillieren.\nNB: Die Patrouille wird ihre ursprüngliche Gruppe verlassen, um eine neue zu bilden. L'unità creerà un sottogruppo per pattugliare l'area.\nNB: La pattuglia lascerà il gruppo originale per formarne uno nuovo. - 该部队将成立一个小组在该地区巡逻.\nNB:巡逻队将离开原来的小组,组建一个新的小组. + 该部队将成立一个小组在该地区巡逻.\nNB:巡逻队将离开原来的小组,组建一个新的小组. Task Patrol @@ -583,7 +578,7 @@ Zadanie - Patrol pozwala jednostkom na patrolowanie obszaru. Задача патруль выполняет патрулирование юнита в пределах области, заданной атрибутами 3DEN. Task Patrol effettua il pattugliamento dell'unità all'interno dell'area impostata dagli attributi 3DEN. - 任务巡逻使单位在 3DEN 属性设置的区域内巡逻. + 任务巡逻使单位在3DEN属性设置的区域内巡逻. Task Reset @@ -601,7 +596,7 @@ Resetuje wszystkie skrypty LAMBS działające na jednostce. Этот модуль сбрасывает все пользовательские скрипты LAMBS, запущенные на устройстве. Questo modulo ripristina tutti gli script LAMBS personalizzati in esecuzione sull'unità - 此模块重置单位上运行的所有自定义 LAMBS 脚本 + 此模块重置单位上运行的所有自定义LAMBS脚本 Task Creep @@ -691,7 +686,7 @@ Zadanie - Zasadzka pozwala jednostkom przeprowadzenie zasadzki na przeciwników. Grupa będzie używać osłon i trzymać się nisko w celu utrzymania anonimowości. Задача подкрасться заставляет юнита попытаться устроить засаду на врагов в пределах области, установленной атрибутами 3DEN. Группа будет использовать доступное укрытие и сохранять низкую стойку, чтобы оставаться незамеченной. <br/><br/> По умолчанию поисковые модули нацелены только на враждебных игроков. Task Creep fa sì che l'unità tenti di tendere un'imboscata ai nemici all'interno dell'area impostata dagli attributi 3DEN. Il gruppo utilizzerà la copertura disponibile e manterrà una posizione bassa per rimanere nascosto.<br/><br/>Per impostazione predefinita, i moduli di ricerca prendono di mira solo i giocatori ostili. - 匍匐小组变使单位尝试在 3DEN 属性设置的区域内伏击敌人.该小组将使用可用的掩护并保持低姿态以保持不被发现.<br/><br/>默认情况下搜索模块仅针对敌对玩家 + 匍匐小组变使单位尝试在3DEN属性设置的区域内伏击敌人.该小组将使用可用的掩护并保持低姿态以保持不被发现.<br/><br/>默认情况下搜索模块仅针对敌对玩家 Task Hunt @@ -709,7 +704,7 @@ Zadanie - Zasadzka pozwala jednostkom przeprowadzenie zasadzki na przeciwników. Grupa będzie używać osłon i trzymać się nisko w celu uniknięcia wykrycia. Domyślnie moduł wyszukuje tylko wrogich graczy. Задача охота заставляет отряд патрулировать область в пределах области, установленной атрибутами 3DEN. Группа будет случайно двигаться в поисковой схеме, постепенно приближаясь к цели. Юниты будут включать фонарики, если они доступны. <br/><br/> По умолчанию поисковые модули нацелены только на враждебных игроков. Task Hunt fa in modo che l'unità pattuglia l'area all'interno dell'area impostata dagli attributi 3DEN. Il gruppo si sposterà casualmente in uno schema di ricerca avvicinandosi gradualmente al bersaglio. L'unità abiliterà le torce, se disponibili.<br/><br/>Per impostazione predefinita, i moduli di ricerca prendono di mira solo i giocatori ostili. - 搜寻任务使单位在 3DEN 属性设置的区域内巡逻. 该小组将以搜索模式随意移动逐渐接近目标。.如果可用该单元将启用手电筒.<br/><br/>默认情况下,搜索模块仅针对敌对玩家. + 搜寻任务使单位在3DEN属性设置的区域内巡逻.该小组将以搜索模式随意移动逐渐接近目标.如果可用该单元将启用手电筒.<br/><br/>默认情况下,搜索模块仅针对敌对玩家. Use group as center @@ -745,7 +740,7 @@ Grupa użyje lidera jako centrum wzoru wyszukiwania. Wyłączenie opcji sprawi, że jednostka użyje zamiast tego pozycji modułu, co skutkuje tym, że grupa jest bardziej defensywna. Группа поиска будет использовать лидера группы в качестве центра схемы поиска. Отключите, чтобы устройство использовало вместо этого позицию модуля. Это создает более оборонительную группу Il gruppo di caccia utilizzerà il capogruppo come centro per il modello di ricerca. Disabilitare l'utilizzo della posizione del modulo da parte dell'unità. Questo crea un gruppo più difensivo - 搜寻组将使用组长作为搜索模式的中心. 禁用让单位使用模块位置. 这创造了一个更具防御性的群体 + 搜寻组将使用组长作为搜索模式的中心.禁用让单位使用模块位置.这创造了一个更具防御性的群体 Script interval @@ -815,7 +810,7 @@ Zadanie - Szturm sprawia, że jednostki agresywnie szturmują naprzeciw wrogom. Jednostki będą poruszać się bardzo agresywnie, często ignorując osłonę i ogień zaporowy.<br/><br/>Domyślnie, moduł jest stworzony aby używać go przeciwko wrogim graczom. Wyłącz FSM dla jednostek, dla prawdziwie przerażających przeciwników. Задача Нападение заставляет отряд попытаться агрессивно бежать к врагам в пределах области, установленной атрибутами 3DEN. Отряд будет двигаться чрезвычайно агрессивно, часто игнорируя укрытие и подавление.<br/><br/> По умолчанию поисковые модули нацелены только на враждебных игроков. Отключает юнит FSM для поистине устрашающего врага Task Rush fa sì che l'unità tenti di correre in modo aggressivo verso i nemici all'interno dell'area impostata dagli attributi 3DEN. L'unità si muoverà in modo estremamente aggressivo, spesso ignorando la copertura e la soppressione.<br/><br/>Per impostazione predefinita, i moduli di ricerca prendono di mira solo i giocatori ostili. Disabilita l'unità FSM per un nemico davvero terrificante. - 使单位尝试向 3DEN 属性设置的区域内的敌人发起攻击. 该单位将极其激进地移动,通常无视掩护和压制.<br/><br/>默认情况下,搜索模块仅针对敌对玩家.禁用FSM单位以获得真正可怕的敌人. + 使单位尝试向3DEN属性设置的区域内的敌人发起攻击.该单位将极其激进地移动,通常无视掩护和压制.<br/><br/>默认情况下,搜索模块仅针对敌对玩家.禁用FSM单位以获得真正可怕的敌人. Use group as center @@ -950,7 +945,7 @@ Ustawia centrum dla wykonywanego skryptu. Moduł może być Dynamicznym Celem LAMBS wybranym z listy lub własną pozycją Устанавливает центр выполнения скрипта. Это может быть собственная или динамическая цель LAMBS, выбранная из списка. Imposta il centro per l'esecuzione dello script. Questo può essere se stesso o un target dinamico LAMBS selezionato dall'elenco - 设置脚本执行的中心. 这可以是自己或从列表中选择的 LAMBS 动态目标 + 设置脚本执行的中心.这可以是自己或从列表中选择的LAMBS动态目标 None @@ -1224,7 +1219,7 @@ Rejestruje artylerię do dynamicznego użytku Registriert Artillerie für den dynamischen Einsatz Registri artiglieria per uso dinamico - 指示火炮以供动态使用 + 动态使用方面的火炮指示 diff --git a/hemtt.toml b/hemtt.toml deleted file mode 100644 index 32c5c861..00000000 --- a/hemtt.toml +++ /dev/null @@ -1,113 +0,0 @@ -name = "LAMBS Danger" -prefix = "lambs" -author = "LAMBS Dev Team" -sig_version = 3 -version = "2.6.0" -reuse_private_key = false -files = [ - "mod.cpp", - "*.paa", - "LICENSE", - "readme.txt", - "readme.md" -] -include = ["./include"] - -key_name = "{{prefix}}_danger_{{version}}" -authority = "{{prefix}}_danger_{{version}}-{{git \"id 8\"}}" - -check = [ - "!version_set", - "!compile_scripts" -] - -postbuild = [ - "!version_unset", - "!remove_compiled_scripts" -] - -releasebuild = [ - "!version_set_release", - "@zip @LambsDanger_{{semver.major}}_{{semver.minor}}_{{semver.patch}}" -] - -[header_exts] -version = "{{version}}_{{git \"id 8\"}}" - -[scripts.version_set] -steps_linux = [ - "echo 'Setting version'", - "sed -i -r -s 's/#define MAJOR 0/#define MAJOR {{semver.major}}/g' addons/main/script_version.hpp", - "sed -i -r -s 's/#define MINOR 0/#define MINOR {{semver.minor}}/g' addons/main/script_version.hpp", - "sed -i -r -s 's/#define PATCHLVL 0/#define PATCHLVL {{semver.patch}}/g' addons/main/script_version.hpp", -] -steps_windows = [ - "echo 'Setting version'", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define MAJOR 0', '#define MAJOR {{semver.major}}' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define MINOR 0', '#define MINOR {{semver.minor}}' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define PATCHLVL 0', '#define PATCHLVL {{semver.patch}}' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", -] -only_release = true -show_output = true - -[scripts.version_unset] -steps_linux = [ - "echo 'Unsetting version'", - "sed -i -r -s 's/#define MAJOR {{semver.major}}/#define MAJOR 0/g' addons/main/script_version.hpp", - "sed -i -r -s 's/#define MINOR {{semver.minor}}/#define MINOR 0/g' addons/main/script_version.hpp", - "sed -i -r -s 's/#define PATCHLVL {{semver.patch}}/#define PATCHLVL 0/g' addons/main/script_version.hpp", -] -steps_windows = [ - "echo 'Unsetting version'", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define MAJOR {{semver.major}}', '#define MAJOR 0' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define MINOR {{semver.minor}}', '#define MINOR 0' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", - "powershell -Command foreach ($f in 'addons/main/script_version.hpp') {(Get-Content $f) -replace '#define PATCHLVL {{semver.patch}}', '#define PATCHLVL 0' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", -] -only_release = true -show_output = true - -[scripts.version_set_release] -steps_linux = [ - "sed -i -r -s 's/\\{version\\}/{{semver.major}}.{{semver.minor}}.{{semver.patch}}/g' releases/{{semver.major}}.{{semver.minor}}.{{semver.patch}}/@lambs/mod.cpp", -] -steps_windows = [ - "powershell -Command foreach ($f in 'releases/{{semver.major}}.{{semver.minor}}.{{semver.patch}}/@lambs/mod.cpp') {(Get-Content $f) -replace '{version}', '{{semver.major}}.{{semver.minor}}.{{semver.patch}}' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", -] -only_release = true -show_output = true - -[scripts.uncomment_isdev] -steps_linux = [ - "echo 'Uncommenting #define ISDEV'", - "sed -i -r -s 's:// #define ISDEV:#define ISDEV:g' addons/Streamator/macros.hpp", -] -steps_windows = [ - "echo 'Uncommenting #define ISDEV'", - "powershell -Command foreach ($f in 'addons/Streamator/macros.hpp') {(Get-Content $f) -replace '// #define ISDEV', '#define ISDEV' -join \"`n\" ^| Set-Content -NoNewline $f; Add-Content -NoNewline \"`n\" $f}", -] - -only_release = true -show_output = true - -[scripts.compile_scripts] -steps_windows = [ - "echo 'Compile Arma Scripts'", - "ArmaScriptCompiler.exe" -] - -steps_linux = [ - "echo 'Compiling Arma Scripts does not work yet on Linux'" -] -only_release = true -show_output = false - -[scripts.remove_compiled_scripts] -steps_windows = [ - "echo 'remove Compiled Scripts'", - "powershell -Command Remove-Item './addons/*' -Recurse -Include *.sqfc" -] -steps_linux = [ - "echo 'Compiling Arma Scripts does not work yet on Linux'" -] -only_release = true -show_output = true diff --git a/include/a3/ui_f/hpp/defineDIKCodes.inc b/include/a3/ui_f/hpp/defineDIKCodes.inc new file mode 100644 index 00000000..c641d601 --- /dev/null +++ b/include/a3/ui_f/hpp/defineDIKCodes.inc @@ -0,0 +1,190 @@ +#ifndef DIK_ESCAPE + +/**************************************************************************** + * + * DirectInput keyboard scan codes + * + ****************************************************************************/ + +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 + +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ + +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_ABNT_C1 0x73 /* / ? on Portugese (Brazilian) keyboards */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_ABNT_C2 0x7E /* Numpad . on Portugese (Brazilian) keyboards */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NEXTTRACK 0x99 /* Next Track */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_MUTE 0xA0 /* Mute */ +#define DIK_CALCULATOR 0xA1 /* Calculator */ +#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */ +#define DIK_MEDIASTOP 0xA4 /* Media Stop */ +#define DIK_VOLUMEDOWN 0xAE /* Volume - */ +#define DIK_VOLUMEUP 0xB0 /* Volume + */ +#define DIK_WEBHOME 0xB2 /* Web home */ +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_PAUSE 0xC5 /* Pause */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ +#define DIK_POWER 0xDE /* System Power */ +#define DIK_SLEEP 0xDF /* System Sleep */ +#define DIK_WAKE 0xE3 /* System Wake */ +#define DIK_WEBSEARCH 0xE5 /* Web Search */ +#define DIK_WEBFAVORITES 0xE6 /* Web Favorites */ +#define DIK_WEBREFRESH 0xE7 /* Web Refresh */ +#define DIK_WEBSTOP 0xE8 /* Web Stop */ +#define DIK_WEBFORWARD 0xE9 /* Web Forward */ +#define DIK_WEBBACK 0xEA /* Web Back */ +#define DIK_MYCOMPUTER 0xEB /* My Computer */ +#define DIK_MAIL 0xEC /* Mail */ +#define DIK_MEDIASELECT 0xED /* Media Select */ + +/* + * Alternate names for keys, to facilitate transition from DOS. + */ +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +/* + * Alternate names for keys originally not used on US keyboards. + */ +#define DIK_CIRCUMFLEX DIK_PREVTRACK /* Japanese keyboard */ + + +/* + * Combination keys + */ +#define INPUT_CTRL_OFFSET 512 +#define INPUT_SHIFT_OFFSET 1024 +#define INPUT_ALT_OFFSET 2048 + + +#endif /* DIK_ESCAPE */ + diff --git a/sqfc.json b/sqfc.json deleted file mode 100644 index 48e18b3d..00000000 --- a/sqfc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "inputDirs": ["P:/z/lambs/addons"], - "includePaths": ["P:/"], - "excludeList": ["settings.sqf"], - "outputDir": "P:/", - "workerThreads": 0 -} diff --git a/tools/stringtableChecker/duplicatedEntry.js b/tools/nodejs_tools/duplicatedEntry.js similarity index 77% rename from tools/stringtableChecker/duplicatedEntry.js rename to tools/nodejs_tools/duplicatedEntry.js index 6fae455a..aba1a7f6 100644 --- a/tools/stringtableChecker/duplicatedEntry.js +++ b/tools/nodejs_tools/duplicatedEntry.js @@ -5,8 +5,7 @@ const fs = require('fs'); const EOL = require('os').EOL; const path = require('path'); const xml = require("xml2js"); -const { Console } = require('console'); -const { fail } = require('assert'); +const core = require('@actions/core'); const PREFIX = "Lambs"; @@ -38,14 +37,14 @@ function getDirFiles(p, module) { projectFiles.push(data); if (!file.endsWith(".xml")) continue; filePath = path.join(p, file); - var xmlData = fs.readFileSync(filePath).toString(); + var xmlData = fs.readFileSync(filePath, { encoding: 'utf8', flag: 'r' }); running++; xml.parseString(xmlData, function (err, result) { if (result.Project.Package[0].Key) { - ParseString(result.Project.Package[0].Key); + ParseString(result.Project.Package[0].Key, filePath, xmlData); } else if (result.Project.Package[0].Container) { for (const entry of result.Project.Package[0].Container) { - ParseString(entry.Key); + ParseString(entry.Key, filePath, xmlData); } } running--; @@ -54,14 +53,21 @@ function getDirFiles(p, module) { } } -function ParseString(Keys) { +function ParseString(Keys, file, data) { for (const entry of Keys) { for (const key in entry) { - if (key != "$" && entry.hasOwnProperty(key)) { + if (key != "$" && Object.hasOwnProperty.call(entry, key)) { const element = entry[key][0]; const index = stringtableEntries.indexOf(element); if (index != -1 && !stringtableIDs.includes(entry.$.ID)) { const log = `${entry.$.ID} is a Duplicated string ${stringtableIDs[index]} : ${key}`; + + var start_line = data.split("\n").findIndex(x => x.includes(key)); + core.warning(log, { + file: file, + startLine: start_line, + }) + fs.appendFileSync("duplicated.log", log + EOL); console.log(log); failedCount++; @@ -75,7 +81,7 @@ function ParseString(Keys) { getDirFiles("addons", ""); -while (running != 0) {} +while (running != 0) { } if (failedCount == 0) { console.log("No Duplicated Entrys found"); } else { diff --git a/tools/nodejs_tools/gitversionsetter.js b/tools/nodejs_tools/gitversionsetter.js new file mode 100644 index 00000000..108475e2 --- /dev/null +++ b/tools/nodejs_tools/gitversionsetter.js @@ -0,0 +1,41 @@ +const fs = require('fs'); +const fsp = fs.promises; +const spawn = require('child_process').spawn; + +async function exec(command, params) { + return new Promise((resolve, reject) => { + let stdout = ''; + let stderr = ''; + + let process = spawn(command, params); + + process.stdout.on('data', (data) => { + if (data == undefined) + return; + + stdout += data.toString(); + }); + + process.stderr.on('data', (data) => { + stderr += data; + }); + + process.on('close', (code) => { + if (code == 0) { + return resolve(stdout); + } + return resolve(stdout); + }); + }); +} + +async function main() { + const filePath = "addons/main/script_version.hpp"; + let version = await fsp.readFile(filePath, { encoding: 'utf-8' }); + const gitVersion = await exec('git', ['rev-list', '--count', 'HEAD']); + version = version.replace("#define BUILD 0", "#define BUILD " + gitVersion); + await fsp.writeFile(filePath, version); +} + + +main(); diff --git a/tools/nodejs_tools/hemttchecker.js b/tools/nodejs_tools/hemttchecker.js new file mode 100644 index 00000000..df020ca0 --- /dev/null +++ b/tools/nodejs_tools/hemttchecker.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const core = require('@actions/core'); + +if (!fs.existsSync('.hemttout/ci_annotations.txt')) return; + +const ci_annotations = fs.readFileSync('.hemttout/ci_annotations.txt', { encoding: 'utf8', flag: 'r' }).split('\n'); + +for (const annotation of ci_annotations) { + if (annotation === '') continue; + const [start_line, end_line, start_column, end_column, type, message, recommendation, file] = annotation.split('||'); + var data = { + file: file, + startLine: parseInt(start_line), + endLine: parseInt(end_line), + title: recommendation, + }; + if (start_line === end_line) { + data.startColumn = start_column; + data.endColumn = end_column; + } + switch (type) { + case 'error': + core.error(message, data); + break; + case 'warning': + core.warning(message, data); + break; + case 'notice': + core.notice(message, data); + break; + default: + core.warning(message, data); + break; + } +} diff --git a/tools/nodejs_tools/package-lock.json b/tools/nodejs_tools/package-lock.json new file mode 100644 index 00000000..6e0fbb0d --- /dev/null +++ b/tools/nodejs_tools/package-lock.json @@ -0,0 +1,95 @@ +{ + "name": "stringtableChecker", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "stringtableChecker", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.1", + "xml2js": "^0.5.0" + } + }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", + "integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/undici": { + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + } + } +} diff --git a/tools/stringtableChecker/package.json b/tools/nodejs_tools/package.json similarity index 90% rename from tools/stringtableChecker/package.json rename to tools/nodejs_tools/package.json index 0f7348c5..8dbbec46 100644 --- a/tools/stringtableChecker/package.json +++ b/tools/nodejs_tools/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { + "@actions/core": "^1.10.1", "xml2js": "^0.5.0" } } diff --git a/tools/prepchecker.js b/tools/nodejs_tools/prepchecker.js similarity index 86% rename from tools/prepchecker.js rename to tools/nodejs_tools/prepchecker.js index b0750507..d5f14ff5 100644 --- a/tools/prepchecker.js +++ b/tools/nodejs_tools/prepchecker.js @@ -4,6 +4,7 @@ const path = require('path'); const fs = require('fs'); +const core = require('@actions/core'); const PREFIX = "Lambs"; @@ -52,7 +53,7 @@ function getDirFiles(p, module) { }; function getFunctions(file, module) { - let content = fs.readFileSync(file).toString(); + let content = fs.readFileSync(file, { encoding: 'utf8', flag: 'r' }); content = content.replace(commentRegex, ''); let match; @@ -85,6 +86,7 @@ function CheckFunctions() { } let content = fs.readFileSync(data.path).toString(); + const lines = content.split("\n") content = content.replace(commentRegex, ''); let match; while ((match = funcPrep.exec(content)) !== null) { @@ -101,6 +103,17 @@ function CheckFunctions() { if (fncName) { if (!prepedFunctions.includes(fncName.toLowerCase())) { console.log(`Use of not Existing Functions: ${fncName} in ${data.path}`) + var key; + if (match[1]) { + key = `FUNC(${match[1]})`; + } else if (match[2] && match[3]) { + key = `EFUNC(${match[2]},${match[3]})`; + } + var line = lines.findIndex(x => x.includes(key)) + core.error(`Use of not Existing Functions: ${fncName}`, { + file: data.path, + startLine: line + }); failedCount++; } } diff --git a/tools/stringtableChecker/stringTableChecker.js b/tools/nodejs_tools/stringTableChecker.js similarity index 89% rename from tools/stringtableChecker/stringTableChecker.js rename to tools/nodejs_tools/stringTableChecker.js index a0c73275..cfd16c58 100644 --- a/tools/stringtableChecker/stringTableChecker.js +++ b/tools/nodejs_tools/stringTableChecker.js @@ -4,7 +4,8 @@ const fs = require('fs'); const path = require('path'); const xml = require("xml2js"); -const { Console } = require('console'); +const core = require('@actions/core'); + const PREFIX = "Lambs"; @@ -73,6 +74,11 @@ function CheckStringtables() { stringtableEntries[strName] = true; } else { console.log(`Stringtable Entry ${strName} does not exist in ${data.path}`); + core.notice(`Stringtable Entry ${strName} does not exist`, { + title: "Missing Stringtable Entry", + file: data.path, + }); + failedCount++; } } @@ -80,6 +86,9 @@ function CheckStringtables() { for (var stringtableEntry in stringtableEntries) { if (stringtableEntries.hasOwnProperty(stringtableEntry) && !stringtableEntries[stringtableEntry]) { console.log(`Stringtable Entry ${stringtableEntry} is Unused!`); + core.notice(`Stringtable Entry ${stringtableEntry} is Unused!`, { + title: "Unused Stringtable Entry", + }); } } } diff --git a/tools/sqf_linter_LogChecker.py b/tools/sqf_linter_LogChecker.py index a4fa9957..4300e35e 100644 --- a/tools/sqf_linter_LogChecker.py +++ b/tools/sqf_linter_LogChecker.py @@ -1,7 +1,7 @@ import sys import os -defaultFalsePositives = 18 +defaultFalsePositives = 20 def main(): f = open("sqf.log", "r") log = f.readlines() diff --git a/tools/stringtableChecker/package-lock.json b/tools/stringtableChecker/package-lock.json deleted file mode 100644 index 2a96f2d5..00000000 --- a/tools/stringtableChecker/package-lock.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "stringtableChecker", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - } - } -}