diff --git a/AUTHORS.txt b/AUTHORS.txt index 29861f1e50..0b794b493c 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -51,6 +51,7 @@ Bla1337 BlackPixxel BlackQwar Brakoviejo +Brandon (TCVM) Brisse Brostrom.A | Evul BullHorn diff --git a/addons/apl/ACE_CSW_Bag.p3d b/addons/apl/ACE_CSW_Bag.p3d new file mode 100644 index 0000000000..d80bde086d Binary files /dev/null and b/addons/apl/ACE_CSW_Bag.p3d differ diff --git a/addons/apl/ACE_CSW_m3_tripod.p3d b/addons/apl/ACE_CSW_m3_tripod.p3d new file mode 100644 index 0000000000..1d112d5a17 Binary files /dev/null and b/addons/apl/ACE_CSW_m3_tripod.p3d differ diff --git a/addons/apl/ACE_CSW_mortarBaseplate.p3d b/addons/apl/ACE_CSW_mortarBaseplate.p3d new file mode 100644 index 0000000000..9da30112b1 Binary files /dev/null and b/addons/apl/ACE_CSW_mortarBaseplate.p3d differ diff --git a/addons/apl/data/m3tripod.rvmat b/addons/apl/data/m3tripod.rvmat new file mode 100644 index 0000000000..1739f48550 --- /dev/null +++ b/addons/apl/data/m3tripod.rvmat @@ -0,0 +1,98 @@ +#define _ARMA_ + +ambient[] = {1,1,1,1.0}; +diffuse[] = {1,1,1,1.0}; +forcedDiffuse[] = {0.0,0.0,0.0,0.0}; +emmisive[] = {0.0,0.0,0.0,1.0}; +specular[] = {1,1,1,1.0}; +specularPower = 40.0; +PixelShaderID = "super"; +VertexShaderID = "super"; +class Stage1 +{ + texture = "z\ace\addons\apl\data\m3tripod_nohq.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage2 +{ + texture = "a3\weapons_f\Data\DetailMaps\metal_detail_dt.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {8.0,0.0,0.0}; + up[] = {0.0,8.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage3 +{ + texture = "#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage4 +{ + texture = "#(argb,8,8,3)color(1,1,1,1,AS)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage5 +{ + texture = "z\ace\addons\apl\data\m3tripod_SMDI.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage6 +{ + texture = "#(ai,32,128,1)fresnel(3.38,5.33)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage7 +{ + texture = "a3\data_f\env_land_co.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class StageTI +{ + texture = "a3\data_f\default_vehicle_ti_ca.paa"; +}; diff --git a/addons/apl/data/m3tripod_co.paa b/addons/apl/data/m3tripod_co.paa new file mode 100644 index 0000000000..994bf342cc Binary files /dev/null and b/addons/apl/data/m3tripod_co.paa differ diff --git a/addons/apl/data/m3tripod_nohq.paa b/addons/apl/data/m3tripod_nohq.paa new file mode 100644 index 0000000000..46c64a4f48 Binary files /dev/null and b/addons/apl/data/m3tripod_nohq.paa differ diff --git a/addons/apl/data/m3tripod_smdi.paa b/addons/apl/data/m3tripod_smdi.paa new file mode 100644 index 0000000000..0c43002132 Binary files /dev/null and b/addons/apl/data/m3tripod_smdi.paa differ diff --git a/addons/apl/data/mortarBaseplate.rvmat b/addons/apl/data/mortarBaseplate.rvmat new file mode 100644 index 0000000000..13739500c6 --- /dev/null +++ b/addons/apl/data/mortarBaseplate.rvmat @@ -0,0 +1,95 @@ +ambient[]={1,1,1,1.000000}; +diffuse[]={1,1,1,1.000000}; +forcedDiffuse[]={0.000000,0.000000,0.000000,0.000000}; +emmisive[]={0.000000,0.000000,0.000000,1.000000}; +specular[]={1,1,1,1.000000}; +specularPower=40.000000; +PixelShaderID="super"; +VertexShaderID="super"; +class Stage1 +{ + texture="z\ace\addons\apl\data\mortarBaseplate_nohq.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage2 +{ + texture="a3\weapons_f\Data\DetailMaps\metal_detail_dt.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={8.0000,0.000000,0.000000}; + up[]={0.000000,8.0000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage3 +{ + texture="#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage4 +{ + texture="z\ace\addons\apl\data\mortarBaseplate_as.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage5 +{ + texture="z\ace\addons\apl\data\mortarBaseplate_smdi.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage6 +{ + texture = "#(ai,32,128,1)fresnel(3.38,5.33)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage7 +{ + texture="a3\data_f\env_land_co.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class StageTI { + texture = "a3\data_f\default_vehicle_ti_ca.paa"; +}; diff --git a/addons/apl/data/mortarBaseplate_as.paa b/addons/apl/data/mortarBaseplate_as.paa new file mode 100644 index 0000000000..7cafb83c0d Binary files /dev/null and b/addons/apl/data/mortarBaseplate_as.paa differ diff --git a/addons/apl/data/mortarBaseplate_co.paa b/addons/apl/data/mortarBaseplate_co.paa new file mode 100644 index 0000000000..3dfe27f12c Binary files /dev/null and b/addons/apl/data/mortarBaseplate_co.paa differ diff --git a/addons/apl/data/mortarBaseplate_nohq.paa b/addons/apl/data/mortarBaseplate_nohq.paa new file mode 100644 index 0000000000..f177b8d5c2 Binary files /dev/null and b/addons/apl/data/mortarBaseplate_nohq.paa differ diff --git a/addons/apl/data/mortarBaseplate_smdi.paa b/addons/apl/data/mortarBaseplate_smdi.paa new file mode 100644 index 0000000000..9b71d965ec Binary files /dev/null and b/addons/apl/data/mortarBaseplate_smdi.paa differ diff --git a/addons/apl/data/static.rvmat b/addons/apl/data/static.rvmat new file mode 100644 index 0000000000..88c9f8e629 --- /dev/null +++ b/addons/apl/data/static.rvmat @@ -0,0 +1,98 @@ +#define _ARMA_ + +class StageTI +{ + texture = "a3\weapons_f\ammoboxes\bags\data\backpacks_ti_ca.paa"; +}; +ambient[] = {1.0,1.0,1.0,1.0}; +diffuse[] = {1.0,1.0,1.0,1.0}; +forcedDiffuse[] = {0.0,0.0,0.0,0.0}; +emmisive[] = {0.0,0.0,0.0,1.0}; +specular[] = {0.0,0.0,0.0,1.0}; +specularPower = 0.0; +PixelShaderID = "Super"; +VertexShaderID = "Super"; +class Stage1 +{ + texture = "z\ace\addons\apl\data\static_nohq.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage2 +{ + texture = "#(argb,8,8,3)color(0.5,0.5,0.5,1,DT)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage3 +{ + texture = "#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage4 +{ + texture = "#(argb,8,8,3)color(1,1,1,1,AS)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage5 +{ + texture = "#(argb,8,8,3)color(0,0,1,1,SMDI)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage6 +{ + texture = "#(ai,32,128,1)fresnel(1.58,0.71)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage7 +{ + texture = "a3\data\env2_co.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; diff --git a/addons/apl/data/static_co.paa b/addons/apl/data/static_co.paa new file mode 100644 index 0000000000..4130790f24 Binary files /dev/null and b/addons/apl/data/static_co.paa differ diff --git a/addons/apl/data/static_nohq.paa b/addons/apl/data/static_nohq.paa new file mode 100644 index 0000000000..5d22d896f3 Binary files /dev/null and b/addons/apl/data/static_nohq.paa differ diff --git a/addons/common/functions/fnc_claim.sqf b/addons/common/functions/fnc_claim.sqf index 5c291c78da..3c30b8f28f 100644 --- a/addons/common/functions/fnc_claim.sqf +++ b/addons/common/functions/fnc_claim.sqf @@ -30,7 +30,7 @@ _target setVariable [QGVAR(owner), _unit, true]; // lock target object if (_lockTarget) then { - private _canBeDisassembled = !([] isEqualTo getArray (_target call CBA_fnc_getObjectConfig >> "assembleInfo" >> "dissasembleTo")); + private _canBeDisassembled = !([] isEqualTo getArray (_target call CBA_fnc_getObjectConfig >> "assembleInfo" >> "dissasembleTo")) && { !([false, true] select (_target getVariable [QEGVAR(csw,assemblyMode), 0])) }; if (!isNull _unit) then { [QGVAR(lockVehicle), _target, _target] call CBA_fnc_targetEvent; if (_canBeDisassembled) then { diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index 2c4b3aecfd..440d26e867 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -1298,5 +1298,37 @@ Flaga (ACE - Biała) Флаг (ACE - Белый) + + Players only + Игроков + Tylko dla graczy + Solo jugadores + Nur Spieler + Pouze hráči + Somente jogadores + Joueur uniquement + Csak játékosok + Solo giocatori + プレイヤーのみ + 플레이어만 + 只限玩家 + 只限玩家 + + + Players and AI + Игроков и ботов + Gracze oraz AI + Jugadores e IA + Spieler und KI + Hráči a AI + Jogadores e IA + Joueurs et IA + Játékosok és AI + Giocatori ed IA + プレイヤーと AI + 플레이어 및 인공지능 + 玩家与AI + 玩家與AI + diff --git a/addons/csw/$PBOPREFIX$ b/addons/csw/$PBOPREFIX$ new file mode 100644 index 0000000000..366f3a5648 --- /dev/null +++ b/addons/csw/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\csw \ No newline at end of file diff --git a/addons/csw/CfgEventHandlers.hpp b/addons/csw/CfgEventHandlers.hpp new file mode 100644 index 0000000000..afe6392a7c --- /dev/null +++ b/addons/csw/CfgEventHandlers.hpp @@ -0,0 +1,15 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preStart)); + }; +}; +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + }; +}; +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE( call COMPILE_FILE(XEH_postInit) ); + }; +}; diff --git a/addons/csw/CfgMagazineGroups.hpp b/addons/csw/CfgMagazineGroups.hpp new file mode 100644 index 0000000000..8a9e0ed31b --- /dev/null +++ b/addons/csw/CfgMagazineGroups.hpp @@ -0,0 +1,81 @@ +class GVAR(groups) { + // A3 .50 BMG (12.7x99mm) + class GVAR(100Rnd_127x99_mag) { + 500Rnd_127x99_mag = 1; + 200Rnd_127x99_mag = 1; + 100Rnd_127x99_mag = 1; + rhs_mag_100rnd_127x99_mag = 1; + rhs_mag_200rnd_127x99_mag = 1; + CUP_100Rnd_127x99_M = 1; + }; + class GVAR(100Rnd_127x99_mag_red) { + 500Rnd_127x99_mag_Tracer_Red = 1; + 200Rnd_127x99_mag_Tracer_Red = 1; + 100Rnd_127x99_mag_Tracer_Red = 1; + rhs_mag_100rnd_127x99_mag_Tracer_Red = 1; + rhs_mag_200rnd_127x99_mag_Tracer_Red = 1; + CUP_100Rnd_TE4_Red_Tracer_127x99_M = 1; + }; + class GVAR(100Rnd_127x99_mag_green) { + 500Rnd_127x99_mag_Tracer_Green = 1; + 200Rnd_127x99_mag_Tracer_Green = 1; + 100Rnd_127x99_mag_Tracer_Green = 1; + rhs_mag_100rnd_127x99_mag_Tracer_Green = 1; + CUP_100Rnd_TE4_Green_Tracer_127x99_M = 1; + }; + class GVAR(100Rnd_127x99_mag_yellow) { + 500Rnd_127x99_mag_Tracer_Yellow = 1; + 200Rnd_127x99_mag_Tracer_Yellow = 1; + 100Rnd_127x99_mag_Tracer_Yellow = 1; + rhs_mag_100rnd_127x99_mag_Tracer_Yellow = 1; + CUP_100Rnd_TE4_Yellow_Tracer_127x99_M = 1; + }; + + // Soviet HMG (12.7x108mm) + class GVAR(50Rnd_127x108_mag) { + rhs_mag_127x108mm_50 = 1; + rhs_mag_127x108mm_100 = 1; + rhs_mag_127x108mm_150 = 1; + CUP_150Rnd_127x108_KORD_M = 1; + CUP_50Rnd_127x108_KORD_M = 1; + CUP_50Rnd_TE3_LRT5_127x107_DSHKM_M = 1; // not sure why cup uses 107 for the DSHKM? + CUP_150Rnd_TE3_LRT5_127x107_DSHKM_M = 1; + }; + + // A3 20mm GMG + class GVAR(20Rnd_20mm_G_belt) { + 40Rnd_20mm_G_belt = 1; + 200Rnd_20mm_G_belt = 1; + }; + + // A3 82mm mortar shells (Allows the normal mk6 to be reloaded from the mk6 ammo handling mags) + class ACE_1Rnd_82mm_Mo_HE { + ACE_1Rnd_82mm_Mo_HE = 1; + 8Rnd_82mm_Mo_shells = 1; + }; + class ACE_1Rnd_82mm_Mo_Smoke { + ACE_1Rnd_82mm_Mo_Smoke = 1; + 8Rnd_82mm_Mo_Smoke_white = 1; + }; + class ACE_1Rnd_82mm_Mo_Illum { + ACE_1Rnd_82mm_Mo_Illum = 1; + 8Rnd_82mm_Mo_Flare_white = 1; + }; + class ACE_1Rnd_82mm_Mo_HE_Guided { + ACE_1Rnd_82mm_Mo_HE_Guided = 1; + 8Rnd_82mm_Mo_guided = 1; + }; + class ACE_1Rnd_82mm_Mo_HE_LaserGuided { + ACE_1Rnd_82mm_Mo_HE_LaserGuided = 1; + 8Rnd_82mm_Mo_LG = 1; + }; + + // A3 Titans (Spike) - just use handheld magazines + class Titan_AT { + 1Rnd_GAT_missiles = 1; + }; + class Titan_AA { + 1Rnd_GAA_missiles = 1; + }; +}; + diff --git a/addons/csw/CfgMagazines.hpp b/addons/csw/CfgMagazines.hpp new file mode 100644 index 0000000000..6102fa48f4 --- /dev/null +++ b/addons/csw/CfgMagazines.hpp @@ -0,0 +1,65 @@ +class CfgMagazines { + class 100Rnd_127x99_mag; + class GVAR(100Rnd_127x99_mag): 100Rnd_127x99_mag { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(127x99_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + mass = 96; + ACE_isBelt = 1; + }; + class 100Rnd_127x99_mag_Tracer_Red; + class GVAR(100Rnd_127x99_mag_red): 100Rnd_127x99_mag_Tracer_Red { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(127x99_red_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + mass = 96; + ACE_isBelt = 1; + }; + class 100Rnd_127x99_mag_Tracer_Green; + class GVAR(100Rnd_127x99_mag_green): 100Rnd_127x99_mag_Tracer_Green { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(127x99_green_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + mass = 96; + ACE_isBelt = 1; + }; + class 100Rnd_127x99_mag_Tracer_Yellow; + class GVAR(100Rnd_127x99_mag_yellow): 100Rnd_127x99_mag_Tracer_Yellow { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(127x99_yellow_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + mass = 96; + ACE_isBelt = 1; + }; + + class 50Rnd_127x108_Ball; + class GVAR(50Rnd_127x108_mag): 50Rnd_127x108_Ball { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(127x108_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + mass = 50; + ACE_isBelt = 1; + }; + + class 40Rnd_20mm_G_belt; + class GVAR(20Rnd_20mm_G_belt): 40Rnd_20mm_G_belt { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(GMGBelt_displayName); + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; + picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa); + type = 256; + count = 20; + mass = 96; + ACE_isBelt = 1; + }; +}; diff --git a/addons/csw/CfgVehicles.hpp b/addons/csw/CfgVehicles.hpp new file mode 100644 index 0000000000..812943d346 --- /dev/null +++ b/addons/csw/CfgVehicles.hpp @@ -0,0 +1,217 @@ +#define ENABLE_CSW_ATTRIBUTE class Attributes { \ + class GVAR(enableCSW) { \ + property = QGVAR(enableCSW); \ + control = "Checkbox"; \ + displayName = CSTRING(eden_enableCSW); \ + tooltip = CSTRING(eden_enableCSW_tooltip); \ + expression = QUOTE(_this setVariable[ARR_3(QQGVAR(enableCSW), _value, true)];); \ + typeName = "BOOL"; \ + condition = "objectVehicle"; \ + defaultValue = true; \ + }; \ + } + + +class CfgVehicles { + class Man; + class CAManBase: Man { + class ACE_SelfActions { + class GVAR(deploy) { + displayName = CSTRING(PlaceTripod_displayName); + condition = QUOTE(call FUNC(assemble_canDeployTripod)); + statement = QUOTE(call FUNC(assemble_deployTripod)); + exceptions[] = {}; + }; + }; + }; + + + // Tripods: + class ThingX; + class GVAR(baseTripod): ThingX { + side = 3; + typicalCargo[] = {}; + armor = 500000; + mapSize = 0.4; + nameSound = "Bunker"; + accuracy = 1000; + destrType = "DestructDefault"; + + ace_dragging_canDrag = 1; + ace_dragging_dragPosition[] = {0, 2, 0}; + ace_dragging_canCarry = 1; + ace_dragging_carryPosition[] = {0, 2, 0}; + + class ACE_Actions { + class ACE_MainActions { + displayName = CSTRING(Tripod_displayName); + selection = ""; + distance = 2.5; + condition = "true"; + class GVAR(pickUp) { + displayName = CSTRING(Pickup_displayName); + condition = QUOTE(call FUNC(assemble_canPickupTripod)); + statement = QUOTE(call FUNC(assemble_pickupTripod)); + }; + class GVAR(mountWeapon) { + displayName = CSTRING(MountWeapon_displayName); + condition = QUOTE(call FUNC(assemble_canDeployWeapon)); + statement = QUOTE(call FUNC(assemble_deployWeapon)); + modifierFunction = QUOTE(call FUNC(assemble_deployWeaponModifier)); + }; + }; + }; + }; + class GVAR(m3Tripod): GVAR(baseTripod) { + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_m3_tripod.p3d); + displayName = CSTRING(Tripod_displayName); + class ADDON { + disassembleTo = QGVAR(m3CarryTripod); + }; + }; + class GVAR(m3TripodLow): GVAR(m3Tripod) { + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_m3_tripod.p3d); + displayName = CSTRING(Tripod_displayName); + class ADDON { + disassembleTo = QGVAR(m3CarryTripodLow); + }; + }; + class GVAR(mortarBaseplate): GVAR(m3Tripod) { + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_mortarBaseplate.p3d); + displayName = CSTRING(mortarBaseplate_displayName); + class ADDON { + disassembleTo = QGVAR(carryMortarBaseplate); + }; + }; + + + // Static Weapons: + class LandVehicle; + class StaticWeapon: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + class GVAR(getIn) { + displayName = CSTRING(GetIn_displayName); + condition = QUOTE(call FUNC(canGetIn)); + statement = QUOTE(call FUNC(getIn)); + }; + }; + }; + }; + + class StaticMGWeapon: StaticWeapon {}; + + class HMG_01_base_F: StaticMGWeapon { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(HMG_Static); + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticHMGCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3TripodLow); // turret [CfgVehicles] + desiredAmmo = 100; + ammoLoadTime = 7; + ammoUnloadTime = 5; + }; + }; + + class HMG_01_high_base_F: HMG_01_base_F { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(HMG_Static); + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticHMGCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3Tripod); // turret [CfgVehicles] + desiredAmmo = 100; + ammoLoadTime = 7; + ammoUnloadTime = 5; + }; + }; + + class HMG_01_A_base_F: HMG_01_base_F { + class ADDON { + enabled = 0; + }; + }; + + + class GMG_TriPod; + class GMG_01_base_F: GMG_TriPod { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(GMG_20mm); // Weapon Proxy (Shorter Reload Time) [CfgWeapons] + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticGMGCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3TripodLow); // turret [CfgVehicles] + desiredAmmo = 40; + ammoLoadTime = 7; + ammoUnloadTime = 5; + }; + }; + + class GMG_01_high_base_F: GMG_01_base_F { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(GMG_20mm); // Weapon Proxy (Shorter Reload Time) [CfgWeapons] + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticGMGCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3Tripod); // turret [CfgVehicles] + desiredAmmo = 40; + ammoLoadTime = 7; + ammoUnloadTime = 5; + }; + }; + + class GMG_01_A_base_F: GMG_01_base_F { + class ADDON { + enabled = 0; + }; + }; + + + class AT_01_base_F: StaticMGWeapon { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(Titan_AT_Static); + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticATCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3Tripod); // turret [CfgVehicles] + desiredAmmo = 40; + ammoLoadTime = 15; // 4 rounds per minute + ammoUnloadTime = 10; + }; + }; + + class AA_01_base_F: StaticMGWeapon { + class ADDON { + enabled = 1; + proxyWeapon = QGVAR(Titan_AA_Static); // Weapon Proxy (Shorter Reload Time) [CfgWeapons] + magazineLocation = "_target selectionPosition 'magazine'"; + disassembleWeapon = QGVAR(staticAACarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(m3Tripod); // turret [CfgVehicles] + desiredAmmo = 40; + ammoLoadTime = 15; // 4 rounds per minute + ammoUnloadTime = 10; + }; + }; + + + class StaticMortar: StaticWeapon {}; + class Mortar_01_base_F: StaticMortar { + class ADDON { + enabled = 1; + magazineLocation = ""; + disassembleWeapon = QGVAR(staticMortarCarry); // carry weapon [CfgWeapons] + disassembleTurret = QGVAR(mortarBaseplate); // turret [CfgVehicles] + desiredAmmo = 1; + ammoLoadTime = 3; + ammoUnloadTime = 3; + }; + }; +}; + diff --git a/addons/csw/CfgWeapons.hpp b/addons/csw/CfgWeapons.hpp new file mode 100644 index 0000000000..c70e17b0b1 --- /dev/null +++ b/addons/csw/CfgWeapons.hpp @@ -0,0 +1,221 @@ +class CfgWeapons { + class Launcher; + class Launcher_Base_F: Launcher { + class WeaponSlotsInfo; + }; + + + // Tripods: + class GVAR(m3CarryTripod): Launcher_Base_F { + class ADDON { + type = "mount"; + deployTime = 4; + pickupTime = 4; + deploy = QGVAR(m3Tripod); + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 440; + }; + displayName = CSTRING(TripodFolded_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\Tripod_Icon.paa); + }; + class GVAR(m3CarryTripodLow): GVAR(m3CarryTripod) { + class ADDON: ADDON { + deploy = QGVAR(m3TripodLow); + }; + displayName = CSTRING(TripodLowFolded_displayName); + }; + class GVAR(carryMortarBaseplate): Launcher_Base_F { + class ADDON { + type = "mount"; + deployTime = 2; + pickupTime = 2; + deploy = QGVAR(mortarBaseplate); + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 290; // M3A1 baseblate weight + }; + displayName = CSTRING(mortarBaseplate_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\Tripod_Icon.paa); // todo + }; + + + // Weapons: + class GVAR(staticATCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 15; + pickupTime = 20; + class assembleTo { + GVAR(m3Tripod) = "B_static_AT_F"; + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 320; // 9M113 Konkurs Weight + }; + displayName = CSTRING(StaticATBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticAT_Icon.paa); + }; + + class GVAR(staticAACarry): GVAR(staticATCarry) { + class ADDON { + type = "weapon"; + deployTime = 15; + pickupTime = 20; + class assembleTo { + GVAR(m3Tripod) = "B_static_AA_F"; + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 320; + }; + displayName = CSTRING(StaticAABag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticAT_Icon.paa); + }; + + class GVAR(staticHMGCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 7; + pickupTime = 10; + class assembleTo { + GVAR(m3Tripod) = "B_HMG_01_high_F"; + GVAR(m3TripodLow) = "B_HMG_01_F"; + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 840; + }; + displayName = CSTRING(StaticHMGBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticHGMG_Icon.paa); + }; + + class GVAR(staticGMGCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 5; + pickupTime = 6; + class assembleTo { + GVAR(m3Tripod) = "B_GMG_01_high_F"; + GVAR(m3TripodLow) = "B_GMG_01_F"; + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 780; + }; + displayName = CSTRING(StaticGMGBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticHGMG_Icon.paa); + }; + + + class GVAR(staticMortarCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 20; + pickupTime = 25; + class assembleTo { + GVAR(mortarBaseplate) = "B_Mortar_01_F"; + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 620; // M252 Mortar Weight + }; + displayName = CSTRING(StaticMortarBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticHGMG_Icon.paa); + }; + + // Proxy Weapons + + class HMG_static; + class GVAR(HMG_Static): HMG_Static { + magazineReloadTime = 0.5; + }; + + class GMG_20mm; + class GVAR(GMG_20mm): GMG_20mm { + magazineReloadTime = 0.5; + }; + + class missiles_titan_static; + class EGVAR(javelin,Titan_Static): missiles_titan_static {}; // if ace_javelin does not exist, this will just inherit from the base weapon + class GVAR(Titan_AT_Static): EGVAR(javelin,Titan_Static) { + EGVAR(javelin,enabled) = 1; // needs to be explicitly enabled + magazineReloadTime = 0.5; + }; + class GVAR(Titan_AA_Static) : missiles_titan_static { + magazineReloadTime = 0.5; + }; + + + /* + class GVAR(staticAutoHMGCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 4; + pickupTime = 4; + class assembleTo { + GVAR(m3Tripod) = GVAR(staticAutoHMGWeapon); + }; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 840; + }; + + displayName = CSTRING(StaticAutoHMGBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticHGMG_Icon.paa); + }; + + + class GVAR(staticAutoGMGCarry): Launcher_Base_F { + class GVAR(options) { + assembleTo = QGVAR(staticAutoGMGWeapon); + baseTripod = QGVAR(m3Tripod); + type = "weapon"; + }; + class WeaponSlotsInfo: WeaponSlotsInfo { + mass = 780; + }; + + displayName = CSTRING(StaticAutoGMGBag_displayName); + author = ECSTRING(common,ACETeam); + scope = 2; + model = QPATHTOEF(apl,ACE_CSW_Bag.p3d); + modes[] = {}; + picture = QPATHTOF(UI\StaticHGMG_Icon.paa); + }; + + */ +}; + diff --git a/addons/csw/README.md b/addons/csw/README.md new file mode 100644 index 0000000000..8729a7fa31 --- /dev/null +++ b/addons/csw/README.md @@ -0,0 +1,12 @@ +ace_csw +=============== + +Crew Served Weapons - Static weapons that are served by multiple people + + +## Maintainers + +The people responsible for merging changes to this component or answering potential questions. + +- [TCVM](https://github.com/TheCandianVendingMachine) + diff --git a/addons/csw/UI/StaticAT_Icon.paa b/addons/csw/UI/StaticAT_Icon.paa new file mode 100644 index 0000000000..6dcf90093a Binary files /dev/null and b/addons/csw/UI/StaticAT_Icon.paa differ diff --git a/addons/csw/UI/StaticHGMG_Icon.paa b/addons/csw/UI/StaticHGMG_Icon.paa new file mode 100644 index 0000000000..12143ee2e1 Binary files /dev/null and b/addons/csw/UI/StaticHGMG_Icon.paa differ diff --git a/addons/csw/UI/Tripod_Icon.paa b/addons/csw/UI/Tripod_Icon.paa new file mode 100644 index 0000000000..02429a0e6d Binary files /dev/null and b/addons/csw/UI/Tripod_Icon.paa differ diff --git a/addons/csw/UI/ammoBox_50bmg_ca.paa b/addons/csw/UI/ammoBox_50bmg_ca.paa new file mode 100644 index 0000000000..6ceaa76fe0 Binary files /dev/null and b/addons/csw/UI/ammoBox_50bmg_ca.paa differ diff --git a/addons/csw/XEH_PREP.hpp b/addons/csw/XEH_PREP.hpp new file mode 100644 index 0000000000..455ffa5e0a --- /dev/null +++ b/addons/csw/XEH_PREP.hpp @@ -0,0 +1,32 @@ +TRACE_1("",QUOTE(ADDON)); + +PREP(ai_handleFired); + +PREP(assemble_canDeployTripod); +PREP(assemble_canDeployWeapon); +PREP(assemble_canPickupTripod); +PREP(assemble_canPickupWeapon); +PREP(assemble_deployTripod); +PREP(assemble_deployWeapon); +PREP(assemble_deployWeaponModifier); +PREP(assemble_pickupTripod); +PREP(assemble_pickupWeapon); + +PREP(canGetIn); +PREP(getIn); + +PREP(proxyWeapon); + +PREP(reload_actionsLoad); +PREP(reload_actionsUnload); +PREP(reload_canLoadMagazine); +PREP(reload_canUnloadMagazine); +PREP(reload_getLoadableMagazines); +PREP(reload_getVehicleMagazine); +PREP(reload_handleAddTurretMag); +PREP(reload_handleRemoveTurretMag); +PREP(reload_handleReturnAmmo); +PREP(reload_loadMagazine); + +PREP(staticWeaponInit); +PREP(staticWeaponInit_unloadExtraMags); diff --git a/addons/csw/XEH_postInit.sqf b/addons/csw/XEH_postInit.sqf new file mode 100644 index 0000000000..69137296c5 --- /dev/null +++ b/addons/csw/XEH_postInit.sqf @@ -0,0 +1,26 @@ +#include "script_component.hpp" + +GVAR(vehicleMagCache) = call CBA_fnc_createNamespace; + +["ace_settingsInitialized", { + TRACE_3("settingsInit",GVAR(defaultAssemblyMode),GVAR(handleExtraMagazines),GVAR(ammoHandling)); + ["StaticWeapon", "init", LINKFUNC(staticWeaponInit), true, [], true] call CBA_fnc_addClassEventHandler; +}] call CBA_fnc_addEventHandler; + + +// Event handlers: +[QGVAR(disableVanillaAssembly), { + params ["_staticWeapon"]; + TRACE_1("disableVanillaAssembly eh",_staticWeapon); + _staticWeapon enableWeaponDisassembly false; +}] call CBA_fnc_addEventHandler; + +[QGVAR(addTurretMag), LINKFUNC(reload_handleAddTurretMag)] call CBA_fnc_addEventHandler; +[QGVAR(removeTurretMag), LINKFUNC(reload_handleRemoveTurretMag)] call CBA_fnc_addEventHandler; +[QGVAR(returnAmmo), LINKFUNC(reload_handleReturnAmmo)] call CBA_fnc_addEventHandler; + + + +#ifdef DEBUG_MODE_FULL +call compile preprocessFileLineNumbers QPATHTOF(dev\checkStaticWeapons.sqf); +#endif diff --git a/addons/csw/XEH_preInit.sqf b/addons/csw/XEH_preInit.sqf new file mode 100644 index 0000000000..6ecb2a0c2f --- /dev/null +++ b/addons/csw/XEH_preInit.sqf @@ -0,0 +1,14 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +#include "initSettings.sqf" + +GVAR(initializedStaticTypes) = []; + +ADDON = true; + diff --git a/addons/csw/XEH_preStart.sqf b/addons/csw/XEH_preStart.sqf new file mode 100644 index 0000000000..022888575e --- /dev/null +++ b/addons/csw/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/csw/config.cpp b/addons/csw/config.cpp new file mode 100644 index 0000000000..4aef60630b --- /dev/null +++ b/addons/csw/config.cpp @@ -0,0 +1,22 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {"ace_csw_carryTripod", "ace_csw_staticATWeapon"}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_interaction"}; + author = ECSTRING(common,ACETeam); + authors[] = {"TCVM"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgVehicles.hpp" +#include "CfgWeapons.hpp" +#include "CfgMagazines.hpp" +#include "CfgMagazineGroups.hpp" + diff --git a/addons/csw/cswDesign.txt b/addons/csw/cswDesign.txt new file mode 100644 index 0000000000..960fb43bf6 --- /dev/null +++ b/addons/csw/cswDesign.txt @@ -0,0 +1,53 @@ +Settings: + + defaultBehaviour: + Normal - Untouched [full mags, normal backpack disassemble] + Advanced - [Realistic mags, side unloading] + handleExtraMagazines + Extra magazines on ground + Ignore extra magazines + +Vehicle: + 3den attribute controls if [useSetting, normal or advanced] + +configs: + +CfgWeapons: + class GVAR(m3CarryTripod): Launcher_Base_F { + class ADDON { + type = "mount"; + deployTime = 3; + pickupTime = 3; + deploy = QGVAR(m3Tripod); + }; + + class GVAR(staticATCarry): Launcher_Base_F { + class ADDON { + type = "weapon"; + deployTime = 8; + pickupTime = 15; + class assembleTo { + tripodCfgVehicle = staticCfgVehicle; + }; + }; + + + + +CfgVehicles: + class GVAR(m3Tripod): // Tripod Example + class ADDON { + disassembleTo = QGVAR(m3CarryTripod); + + + class Mortar_01_base_F: // Static Weapon Example + class ADDON { + enabled = 1; + magazineLocation = ""; + disassembleWeapon = ""; // secondary weapon classname + disassembleTurret = ""; // CfgVehicle + desiredAmmo = 100; // + ammoLoadTime = 5; + ammoUnloadTime = 5; + + diff --git a/addons/csw/data/model.cfg b/addons/csw/data/model.cfg new file mode 100644 index 0000000000..aa9fa5af7c --- /dev/null +++ b/addons/csw/data/model.cfg @@ -0,0 +1,51 @@ +class CfgSkeletons { + class Default { + isDiscrete = 1; + skeletonInherit = ""; + skeletonBones[] = {}; + }; + class ACE_CSW_Tripod_Skeleton: Default {}; + class ACE_CSW_M3_Tripod_Skeleton: Default {}; + // class ACE_CSW_FoldedTripod_Skeleton: Default {}; + // class ACE_CSW_ammoBox_Skeleton: Default {}; + class ACE_CSW_WeaponBag_Skeleton: Default {}; + class ACE_CSW_mortarBaseplate_Skeleton: Default {}; +}; +class CfgModels { + class Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = ""; + }; + class ACE_CSW_Tripod : Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_Tripod_Skeleton"; + }; + class ACE_CSW_M3_Tripod : Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_M3_Tripod_Skeleton"; + }; + /* class ACE_CSW_FoldedTripod: Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_FoldedTripod_Skeleton"; + }; + class ACE_CSW_ammoBox: Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_ammoBox_Skeleton"; + }; */ + class ACE_CSW_Bag: Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_WeaponBag_Skeleton"; + }; + class ACE_CSW_mortarBaseplate: Default { + sectionsInherit = ""; + sections[] = {}; + skeletonName = "ACE_CSW_mortarBaseplate_Skeleton"; + }; +}; + diff --git a/addons/csw/dev/checkStaticWeapons.sqf b/addons/csw/dev/checkStaticWeapons.sqf new file mode 100644 index 0000000000..6ad8985b98 --- /dev/null +++ b/addons/csw/dev/checkStaticWeapons.sqf @@ -0,0 +1,76 @@ +#define DEBUG_MODE_FULL +#include "\z\ace\addons\csw\script_component.hpp" + +// Dev only function to search for weapons used by static weapons +// and check if their magazinese are compatible +INFO("Checking static weapons"); + +private _staticWeaponConfigs = configProperties [configFile >> "CfgVehicles", "(isClass _x) && {(configName _x) isKindOf 'StaticWeapon'}", true]; +private _staticPublic = _staticWeaponConfigs select {(getNumber (_x >> "scope")) == 2}; +INFO_2("Static Weapons [%1] - CSW Enabled [%2]",count _staticPublic, {(getNumber (_x >> "ace_csw" >> "enabled")) == 1} count _staticPublic); + +INFO("------ Checking static weapons inheritance ------"); +private _explicitBases = []; +private _inherited = []; +{ + private _config = _x; + private _configEnabled = (getNumber (_config >> "ace_csw" >> "enabled")) == 1; + if (_configEnabled) then { + private _configExplicit = (count configProperties [_config, "configName _x == 'ace_csw'", false]) == 1; + if (_configExplicit) then { + _explicitBases pushBack (configName _config); + _inherited pushBack []; + } else { + if ((getNumber (_config >> "scope")) < 2) exitWith {}; + private _parent = inheritsFrom _config; + while {isClass _parent} do { + private _className = configName _parent; + private _index = _explicitBases findIf {_className == _x}; + if (_index > -1) exitWith { + (_inherited select _index) pushBack (configName _config); + }; + _parent = inheritsFrom _parent; + }; + }; + }; +} forEach _staticWeaponConfigs; +{ + INFO_2("%1 inherited by %2",_x,_inherited select _forEachIndex); +} forEach _explicitBases; + + + + +INFO("------ Logging static magazines with no carry version -------"); +private _hash = [] call CBA_fnc_hashCreate; +// private _logAll = true; // logs all possible weapon magazines (even if not used in a static weapon) +private _logAll = false; +{ + private _vehicleType = configName _x; + private _turretConfig = [_vehicleType, [0]] call CBA_fnc_getTurret; + private _weapons = getArray (_turretConfig >> "weapons"); + private _loadedMags = getArray (_turretConfig >> "magazines"); + { + private _weapMags = getArray (configFile >> "CfgWeapons" >> _x >> "magazines"); + { + private _xMag = _x; + private _groups = "getNumber (_x >> _xMag) == 1" configClasses (configFile >> QGVAR(groups)); + private _carryMag = configName (_groups param [0, configNull]); + if ((_carryMag == "") && {_logAll || {_xMag in _loadedMags}}) then { + private _vehs = [_hash, _xMag] call CBA_fnc_hashGet; + if (isNil "_vehs") then {_vehs = [];}; + if (_xMag in _loadedMags) then { + _vehs pushBack _vehicleType; + }; + [_hash, _xMag, _vehs] call CBA_fnc_hashSet; + }; + } forEach _weapMags; + } forEach _weapons; +} forEach _staticWeaponConfigs; + +[_hash, { + //IGNORE_PRIVATE_WARNING ["_key", "_value"]; + INFO_2("[%1] has no carry varient - Used in %2",_key,_value); +}] call CBA_fnc_hashEachPair; + +INFO("------ End -------"); diff --git a/addons/csw/functions/fnc_ai_handleFired.sqf b/addons/csw/functions/fnc_ai_handleFired.sqf new file mode 100644 index 0000000000..43876f3b87 --- /dev/null +++ b/addons/csw/functions/fnc_ai_handleFired.sqf @@ -0,0 +1,96 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Initializes weapon to disable weapon disassembling + * + * Arguments: + * 0: Weapon + * + * Return Value: + * None + * + * Example: + * [weapon] call ace_csw_fnc_ai_handleFired + * + * Public: No + */ + +params ["_staticWeapon", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"]; +TRACE_8("firedEH:",_staticWeapon, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile, _gunner); + +if ((!local _gunner) || {[_gunner] call EFUNC(common,isPlayer)}) exitWith {}; +if (someAmmo _staticWeapon) exitWith {}; + +TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon); + +private _turretPath = [_gunner] call EFUNC(common,getTurretIndex); +private _reloadSource = objNull; +private _reloadMag = ""; +private _reloadNeededAmmo = -1; + +// Find if there is anything we can reload with +{ + scopeName "findSource"; + private _xSource = _x; + + private _cswMagazines = []; + { + if (isClass (configFile >> QGVAR(groups) >> _x)) then { _cswMagazines pushBackUnique _x; }; + } forEach (if (_xSource isKindOf "CaManBase") then {magazines _x} else {magazineCargo _x}); + TRACE_2("",_xSource,_cswMagazines); + + private _compatibleMags = [_magazine] + ([_weapon] call CBA_fnc_compatibleMagazines); // Check current mag first + + { + private _xWeaponMag = _x; + { + if ((getNumber (configFile >> QGVAR(groups) >> _x >> _xWeaponMag)) == 1) then { + private _loadInfo = [_staticWeapon, _turretPath, _reloadMag, objNull] call FUNC(reload_canLoadMagazine); + if (_loadInfo select 0) then { + _reloadMag = _x; + _reloadSource = _xSource; + _reloadNeededAmmo = _loadInfo select 2; + TRACE_3("found mag",_reloadMag,_reloadSource,_x); + breakOut "findSource"; + }; + }; + } forEach _cswMagazines; + } forEach _compatibleMags; +} forEach ([_gunner] + (_staticWeapon nearEntities [["groundWeaponHolder", "ReammoBox_F"], 10])); +if (_reloadMag == "") exitWith {TRACE_1("could not find mag",_reloadMag);}; + +// Figure out what we can add from the magazines we have +private _bestAmmoToSend = -1; +{ + _x params ["_xMag", "_xAmmo"]; + TRACE_2("",_xMag,_xAmmo); + if (_xMag == _reloadMag) then { + if ((_bestAmmoToSend == -1) || {(_xAmmo > _bestAmmoToSend) && {_xAmmo <= _reloadNeededAmmo}}) then { + _bestAmmoToSend = _xAmmo; + }; + }; +} forEach (if (_reloadSource isKindOf "CaManBase") then {magazinesAmmo _reloadSource} else {magazinesAmmoCargo _reloadSource}); +TRACE_4("",_reloadSource,_reloadMag,_reloadNeededAmmo,_bestAmmoToSend); +if (_bestAmmoToSend == -1) exitWith {ERROR("No ammo");}; + +// Remove the mag from the source +if (_reloadSource isKindOf "CaManBase") then { + [_reloadSource, _reloadMag, _bestAmmoToSend] call ace_common_fnc_removeSpecificMagazine; +} else { + [_reloadSource, _reloadMag, 1, _bestAmmoToSend] call CBA_fnc_removeMagazineCargo; +}; + +private _timeToLoad = 1; +if (!isNull(configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "ammoLoadTime")) then { + _timeToLoad = getNumber(configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "ammoLoadTime"); +}; + +TRACE_1("Reloading in progress",_timeToLoad); +[{ + params ["_staticWeapon", "_turretPath", "_gunner", "_reloadMag", "_bestAmmoToSend"]; + if ((!alive _staticWeapon) || {!alive _gunner} || {(_staticWeapon distance _gunner) > 10}) exitWith {TRACE_1("invalid state",_this);}; + + // Reload the static weapon + TRACE_5("calling addTurretMag event",_staticWeapon, _turretPath, _gunner, _reloadMag, _bestAmmoToSend); + [QGVAR(addTurretMag), _this] call CBA_fnc_globalEvent; +}, [_staticWeapon, _turretPath, _gunner, _reloadMag, _bestAmmoToSend], _timeToLoad] call CBA_fnc_waitAndExecute; diff --git a/addons/csw/functions/fnc_assemble_canDeployTripod.sqf b/addons/csw/functions/fnc_assemble_canDeployTripod.sqf new file mode 100644 index 0000000000..a890e746ea --- /dev/null +++ b/addons/csw/functions/fnc_assemble_canDeployTripod.sqf @@ -0,0 +1,21 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Checks if the player can deploy the tripod. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Can deploy + * + * Example: + * [player] call ace_csw_fnc_canDeployTripod + * + * Public: No + */ + +params ["_player"]; + +(getText(configFile >> "CfgWeapons" >> (secondaryWeapon _player) >> QUOTE(ADDON) >> "type") == "mount") + diff --git a/addons/csw/functions/fnc_assemble_canDeployWeapon.sqf b/addons/csw/functions/fnc_assemble_canDeployWeapon.sqf new file mode 100644 index 0000000000..b0659e2f01 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_canDeployWeapon.sqf @@ -0,0 +1,25 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Checks if you can deploy a weapon on the tripod + * + * Arguments: + * 0: Target Tripod + * 0: Player + * + * Return Value: + * Wether or not you can deploy the weapon + * + * Example: + * [cursorObject, player] call ace_csw_fnc_assemble_canDeployWeapon + * + * Public: No + */ + +params ["_target", "_player", "", "_carryWeaponClassname"]; +if (isNil "_carryWeaponClassname") then { _carryWeaponClassname = secondaryWeapon _player }; + +// If the current launcher has a config-value that defines the tripod, it is a CSW +(alive _target) && +{(getText(configFile >> "CfgWeapons" >> _carryWeaponClassname >> QUOTE(ADDON) >> "assembleTo" >> (typeOf _target))) != ""} + diff --git a/addons/csw/functions/fnc_assemble_canPickupTripod.sqf b/addons/csw/functions/fnc_assemble_canPickupTripod.sqf new file mode 100644 index 0000000000..a5cd0d5c0c --- /dev/null +++ b/addons/csw/functions/fnc_assemble_canPickupTripod.sqf @@ -0,0 +1,22 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Checks if the player can pick-up the tripod. + * + * Arguments: + * 0: Tripod + * 1: Unit + * + * Return Value: + * Can pickup + * + * Example: + * [tripod, player] call ace_csw_fnc_assemble_canPickupTripod + * + * Public: No + */ + +params ["_tripod", "_player"]; + +((secondaryWeapon _player) isEqualTo "") && {alive _tripod} + diff --git a/addons/csw/functions/fnc_assemble_canPickupWeapon.sqf b/addons/csw/functions/fnc_assemble_canPickupWeapon.sqf new file mode 100644 index 0000000000..21a88709d6 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_canPickupWeapon.sqf @@ -0,0 +1,25 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * If the CSW is mounted or in use this will not allow you to dismount the weapon + * + * Arguments: + * 0: Static Weapon + * + * Return Value: + * Can Dismount + * + * Example: + * [cursorObject] call ace_csw_fnc_assemble_canPickupWeapon + * + * Public: No + */ + +params ["_staticWeapon"]; + +private _assemblyMode = [false, true, GVAR(defaultAssemblyMode)] select (_staticWeapon getVariable [QGVAR(assemblyMode), 2]); +private _crewed = (crew _staticWeapon) isEqualTo []; +private _deadCrew = !(alive (gunner _staticWeapon)); // need to eject body??? + +_assemblyMode && {(!_crewed) || _deadCrew} + diff --git a/addons/csw/functions/fnc_assemble_deployTripod.sqf b/addons/csw/functions/fnc_assemble_deployTripod.sqf new file mode 100644 index 0000000000..7bae44a350 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_deployTripod.sqf @@ -0,0 +1,66 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Deploys the tripod + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call ace_csw_fnc_assemble_deployTripod + * + * Public: No + */ + +[{ + params ["_player"]; + TRACE_1("assemble_deployTripod",_player); + + // Remove the tripod from the launcher slot + private _secondaryWeaponClassname = secondaryWeapon _player; + _player removeWeaponGlobal (secondaryWeapon _player); + + private _onFinish = { + params ["_args"]; + _args params ["_player", "_secondaryWeaponClassname"]; + TRACE_2("deployTripod finish",_player,_secondaryWeaponClassname); + + private _tripodClassname = getText(configFile >> "CfgWeapons" >> _secondaryWeaponClassname >> QUOTE(ADDON) >> "deploy"); + + // Create a tripod + private _cswTripod = createVehicle [_tripodClassname, [0, 0, 0], [], 0, "NONE"]; + + private _posATL = _player getRelPos [2, 0]; + _posATL set [2, ((getPosATL _player) select 2) + 0.5]; + + _cswTripod setDir (direction _player); + _cswTripod setPosATL _posATL; + _cswTripod setVectorUp (surfaceNormal _posATL); + + [_player, "PutDown"] call EFUNC(common,doGesture); + + // drag after deploying + if ((missionNamespace getVariable [QGVAR(dragAfterDeploying), false]) && {["ACE_dragging"] call EFUNC(common,isModLoaded)}) then { + if ([_player, _cswTripod] call EFUNC(dragging,canCarry)) then { + TRACE_1("starting carry",_cswTripod); + [_player, _cswTripod] call EFUNC(dragging,startCarry); + } else { + TRACE_1("cannot carry",_cswTripod); + }; + }; + }; + + private _onFailure = { + params ["_args"]; + _args params ["_player", "_secondaryWeaponClassname"]; + TRACE_2("deployTripod failure",_player,_secondaryWeaponClassname); + + _player addWeaponGlobal _secondaryWeaponClassname; + }; + + private _deployTime = getNumber(configFile >> "CfgWeapons" >> _secondaryWeaponClassname >> QUOTE(ADDON) >> "deployTime"); + [TIME_PROGRESSBAR(_deployTime), [_player, _secondaryWeaponClassname], _onFinish, _onFailure, localize LSTRING(PlaceTripod_progressBar)] call EFUNC(common,progressBar); +}, _this] call CBA_fnc_execNextFrame; diff --git a/addons/csw/functions/fnc_assemble_deployWeapon.sqf b/addons/csw/functions/fnc_assemble_deployWeapon.sqf new file mode 100644 index 0000000000..1c27352606 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_deployWeapon.sqf @@ -0,0 +1,74 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Deploys the current CSW + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call ace_csw_fnc_assemble_deployWeapon + * + * Public: No + */ + +[{ + params ["_tripod", "_player", "", "_carryWeaponClassname"]; + if (isNil "_carryWeaponClassname") then { _carryWeaponClassname = secondaryWeapon _player }; + TRACE_3("assemble_deployWeapon_carryWeaponClassname",_tripod,_player,_carryWeaponClassname); + + private _tripodClassname = typeOf _tripod; + _player removeWeaponGlobal _carryWeaponClassname; + + private _assembledClassname = getText(configfile >> "CfgWeapons" >> _carryWeaponClassname >> QUOTE(ADDON) >> "assembleTo" >> _tripodClassname); + private _deployTime = getNumber(configfile >> "CfgWeapons" >> _carryWeaponClassname >> QUOTE(ADDON) >> "deployTime"); + if (!isClass (configFile >> "CfgVehicles" >> _assembledClassname)) exitWith {ERROR_1("bad static classname [%1]",_assembledClassname);}; + + TRACE_4("",_carryWeaponClassname,_tripodClassname,_assembledClassname,_deployTime); + + private _onFinish = { + params ["_args"]; + _args params ["_tripod", "_player", "_assembledClassname"]; + TRACE_3("deployWeapon finish",_tripod,_player,_assembledClassname); + + private _tripodPos = getPosATL _tripod; + private _tripodDir = getDir _tripod; + deleteVehicle _tripod; + + _tripodPos set [2, (_tripodPos select 2) + 0.1]; + // Delay a frame so tripod has a chance to be deleted + [{ + params ["_assembledClassname", "_tripodDir", "_tripodPos"]; + private _csw = createVehicle [_assembledClassname, [0, 0, 0], [], 0, "NONE"]; + _csw setVariable [QGVAR(assemblyMode), 1, true]; // Explicitly set advanced assembly mode and broadcast + _csw setVariable [QGVAR(emptyWeapon), true, false]; // unload gun, shouldn't need broadcast for this as it will be local to us + if (!GVAR(defaultAssemblyMode)) then { + TRACE_1("global disableVanillaAssembly event",_csw); // handles it being assembled when setting is disabled + [QGVAR(disableVanillaAssembly), [_csw]] call CBA_fnc_globalEvent; + }; + _csw setDir _tripodDir; + _csw setPosATL _tripodPos; + _csw setVectorUp (surfaceNormal _tripodPos); + }, [_assembledClassname, _tripodDir, _tripodPos]] call CBA_fnc_execNextFrame; + }; + + private _onFailure = { + params ["_args"]; + _args params ["", "_player", "", "_carryWeaponClassname"]; + TRACE_2("deployWeapon failure",_player,_carryWeaponClassname); + + _player addWeaponGlobal _carryWeaponClassname; + }; + + private _codeCheck = { + params ["_args"]; + _args params ["_tripod"]; + !isNull _tripod; + }; + + [TIME_PROGRESSBAR(_deployTime), [_tripod, _player, _assembledClassname, _carryWeaponClassname], _onFinish, _onFailure, localize LSTRING(AssembleCSW_progressBar), _codeCheck] call EFUNC(common,progressBar); +}, _this] call CBA_fnc_execNextFrame; + diff --git a/addons/csw/functions/fnc_assemble_deployWeaponModifier.sqf b/addons/csw/functions/fnc_assemble_deployWeaponModifier.sqf new file mode 100644 index 0000000000..b1b89d8f09 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_deployWeaponModifier.sqf @@ -0,0 +1,28 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Modifies interaction for deploying weapon + * + * Arguments: + * 0: Target + * 1: Player + * 2: Args + * 3: Action Data + * + * Return Value: + * None + * + * Example: + * [cursorObject, player, [], []] call ace_csw_fnc_assemble_deployWeaponModifier + * + * Public: No + */ + +params ["_target", "_player", "", "_actionData"]; + +private _carryWeaponClassname = secondaryWeapon _player; +private _assembleTo = (getText(configFile >> "CfgWeapons" >> _carryWeaponClassname >> QUOTE(ADDON) >> "assembleTo" >> (typeOf _target))); +private _icon = getText (configFile >> "CfgVehicles" >> _assembleTo >> "picture"); +TRACE_2("",_assembleTo,_icon); + +_actionData set [2, _icon]; diff --git a/addons/csw/functions/fnc_assemble_pickupTripod.sqf b/addons/csw/functions/fnc_assemble_pickupTripod.sqf new file mode 100644 index 0000000000..0167254795 --- /dev/null +++ b/addons/csw/functions/fnc_assemble_pickupTripod.sqf @@ -0,0 +1,47 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Picks up the tripod and adds it to the player launcher slot + * + * Arguments: + * 0: Tripod + * 1: Unit + * + * Return Value: + * None + * + * Example: + * [tripod, player] call ace_csw_fnc_assemble_pickupTripod + * + * Public: No + */ + +[{ + params ["_tripod", "_player"]; + TRACE_2("assemble_pickupTripod",_tripod,_player); + + private _tripodClassname = getText(configFile >> "CfgVehicles" >> (typeof _tripod) >> QUOTE(ADDON) >> "disassembleTo"); + private _pickupTime = getNumber(configFile >> "CfgWeapons" >> _tripodClassname >> QUOTE(ADDON) >> "pickupTime"); + + private _onFinish = { + params ["_args"]; + _args params ["_tripod", "_player", "_tripodClassname"]; + TRACE_3("assemble_pickupTripod finish",_tripod,_player,_tripodClassname); + + deleteVehicle _tripod; + _player addWeaponGlobal _tripodClassname; + [_player, "PutDown"] call EFUNC(common,doGesture); + }; + + private _condition = { + params ["_args"]; + _args params ["_tripod", "_player"]; + + !(isNull _tripod) && { (secondaryWeapon _player) isEqualTo "" } + + }; + + TRACE_3("",_pickupTime,typeOf _tripod,_tripodClassname); + [TIME_PROGRESSBAR(_pickupTime), [_tripod, _player, _tripodClassname], _onFinish, {}, localize LSTRING(PickupTripod_progressBar), _condition] call EFUNC(common,progressBar); +}, _this] call CBA_fnc_execNextFrame; + diff --git a/addons/csw/functions/fnc_assemble_pickupWeapon.sqf b/addons/csw/functions/fnc_assemble_pickupWeapon.sqf new file mode 100644 index 0000000000..bc35f44f6d --- /dev/null +++ b/addons/csw/functions/fnc_assemble_pickupWeapon.sqf @@ -0,0 +1,91 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Dismounts the weapon from the tripod and drops its backpack beside + * + * Arguments: + * 0: Static Weapon + * + * Return Value: + * None + * + * Example: + * [weapon] call ace_csw_fnc_assemble_pickupWeapon + * + * Public: No + */ + +[{ + params ["_staticWeapon", "_player"]; + TRACE_2("assemble_pickupWeapon",_staticWeapon,_player); + + private _onDisassembleFunc = getText(configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "disassembleFunc"); + private _carryWeaponClassname = getText(configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "disassembleWeapon"); + private _turretClassname = getText(configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "disassembleTurret"); + private _pickupTime = getNumber(configFile >> "CfgWeapons" >> _carryWeaponClassname >> QUOTE(ADDON) >> "pickupTime"); + TRACE_4("",typeOf _staticWeapon,_carryWeaponClassname,_turretClassname,_pickupTime); + if (!isClass (configFile >> "CfgWeapons" >> _carryWeaponClassname)) exitWith {ERROR_1("bad weapon classname [%1]",_carryWeaponClassname);}; + if (!isClass (configFile >> "CfgVehicles" >> _turretClassname)) exitWith {ERROR_1("bad turret classname [%1]",_turretClassname);}; + + private _onFinish = { + params ["_args"]; + _args params ["_staticWeapon", "_player", "_carryWeaponClassname", "_turretClassname", "_onDisassembleFunc"]; + TRACE_4("disassemble finish",_staticWeapon,_player,_carryWeaponClassname,_turretClassname); + + private _weaponPos = getPosATL _staticWeapon; + _weaponPos set [2, (_weaponPos select 2) + 0.1]; + private _weaponDir = getDir _staticWeapon; + + LOG("remove ammo"); + { + _x params ["_xMag", "", "_xAmmo"]; + + private _carryMag = GVAR(vehicleMagCache) getVariable _xMag; + if (isNil "_carryMag") then { + private _groups = "getNumber (_x >> _xMag) == 1" configClasses (configFile >> QGVAR(groups)); + _carryMag = configName (_groups param [0, configNull]); + GVAR(vehicleMagCache) setVariable [_xMag, _carryMag]; + TRACE_2("setting cache",_xMag,_carryMag); + }; + if ((_xAmmo > 0) && {_carryMag != ""}) then { + TRACE_2("Removing ammo",_xMag,_carryMag); + [_player, _carryMag, _xAmmo] call FUNC(reload_handleReturnAmmo); + }; + } forEach (magazinesAllTurrets _staticWeapon); + + private _cswTripod = createVehicle [_turretClassname, [0, 0, 0], [], 0, "NONE"]; + [_cswTripod, _staticWeapon] call (missionNamespace getVariable _onDisassembleFunc); + + LOG("delete weapon"); + deleteVehicle _staticWeapon; + + // Delay a frame so weapon has a chance to be deleted + [{ + params ["_player", "_cswTripod", "_weaponDir", "_weaponPos", "_carryWeaponClassname"]; + _cswTripod setDir _weaponDir; + _cswTripod setPosATL _weaponPos; + _cswTripod setVelocity [0, 0, -0.05]; + _cswTripod setVectorUp (surfaceNormal _weaponPos); + + if ((alive _player) && {(secondaryWeapon _player) == ""}) exitWith { + _player addWeapon _carryWeaponClassname; + }; + private _weaponRelPos = _cswTripod getRelPos RELATIVE_DIRECTION(90); + private _weaponHolder = createVehicle ["groundWeaponHolder", [0, 0, 0], [], 0, "NONE"]; + _weaponHolder setDir random [0, 180, 360]; + _weaponHolder setPosATL [_weaponRelPos select 0, _weaponRelPos select 1, _weaponPos select 2]; + _weaponHolder addWeaponCargoGlobal [_carryWeaponClassname, 1]; + }, [_player, _cswTripod, _weaponDir, _weaponPos, _carryWeaponClassname]] call CBA_fnc_execNextFrame; + + LOG("end"); + }; + + private _condition = { + params ["_args"]; + _args params ["_staticWeapon"]; + ((crew _staticWeapon) isEqualTo []) && (alive _staticWeapon) + }; + + [TIME_PROGRESSBAR(_pickupTime), [_staticWeapon, _player, _carryWeaponClassname, _turretClassname, _onDisassembleFunc], _onFinish, {}, localize LSTRING(DisassembleCSW_progressBar), _condition] call EFUNC(common,progressBar); +}, _this] call CBA_fnc_execNextFrame; + diff --git a/addons/csw/functions/fnc_canGetIn.sqf b/addons/csw/functions/fnc_canGetIn.sqf new file mode 100644 index 0000000000..92b05b1c2c --- /dev/null +++ b/addons/csw/functions/fnc_canGetIn.sqf @@ -0,0 +1,28 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Checks if the player can get in the weapon + * + * Arguments: + * 0: Static Weapon + * + * Return Value: + * None + * + * Example: + * [cursorObject] call ace_csw_fnc_canGetIn + * + * Public: No + */ + +// hide this action if quick mount is enabled +if ((missionNamespace getVariable [QEGVAR(quickmount,enabled), false]) && {(missionNamespace getVariable [QEGVAR(quickmount,enableMenu), -1]) in [1, 3]}) exitWith { + false +}; + +params ["_staticWeapon"]; + +alive _staticWeapon +&& {!(alive (gunner _staticWeapon))} +&& {(locked _staticWeapon) < 2} +&& {0.3 < ((vectorUp _staticWeapon) select 2)} diff --git a/addons/csw/functions/fnc_getIn.sqf b/addons/csw/functions/fnc_getIn.sqf new file mode 100644 index 0000000000..338d17e03e --- /dev/null +++ b/addons/csw/functions/fnc_getIn.sqf @@ -0,0 +1,24 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * An action for the player to get in the CSW + * Due to the fact that the default static weapons "Get In" memory point is at the front of + * the gun and can't be acssesed from the back, I am implementing this to get around that issue. + * + * Arguments: + * 0: Static Weapon + * 1: Unit + * + * Return Value: + * None + * + * Example: + * [cursorObject, player] call ace_csw_fnc_getIn + * + * Public: No + */ + +params ["_staticWeapon", "_player"]; +TRACE_2("getIn",_staticWeapon,_player); + +_player moveInTurret [_staticWeapon, [0]]; diff --git a/addons/csw/functions/fnc_proxyWeapon.sqf b/addons/csw/functions/fnc_proxyWeapon.sqf new file mode 100644 index 0000000000..198a4fbe28 --- /dev/null +++ b/addons/csw/functions/fnc_proxyWeapon.sqf @@ -0,0 +1,41 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM), PabstMirror + * Handles the use of proxy weapons to fix engine-reload times + * + * Arguments: + * 0: Weapon + * 1: Turret + * 2: Proxy weapon needed + * + * Return Value: + * None + * + * Example: + * [weapon, [0], true] call ace_csw_fnc_proxyWeapon + * + * Public: No + */ + +params ["_staticWeapon", "_turret", "_needed"]; + +if (_staticWeapon getVariable [format [QGVAR(proxyHandled_%1), _turret], false]) exitWith { TRACE_1("proxy weapon already handled",_staticWeapon); }; + +private _typeOf = typeOf _staticWeapon; +private _proxyWeapon = getText(configFile >> "CfgVehicles" >> _typeOf >> "ace_csw" >> "proxyWeapon"); +TRACE_5("proxyWeapon",_staticWeapon,_turret,_needed,_typeOf,_proxyWeapon); + +if (_proxyWeapon == "") exitWith { TRACE_1("proxyWeapon not defined",_proxyWeapon); }; + +private _currentWeapon = (_staticWeapon weaponsTurret [0]) param [0, "#none"]; +if ((missionNamespace getVariable [_proxyWeapon, objNull]) isEqualType {}) then { // check if string is a function + TRACE_1("Calling proxyWeapon function",_proxyWeapon); + _proxyWeapon = [_staticWeapon, _turret, _currentWeapon, _needed] call (missionNamespace getVariable _proxyWeapon); + _needed = _proxyWeapon != ""; +}; +if (!_needed) exitWith { TRACE_2("not needed",_needed,_proxyWeapon); }; + +TRACE_2("swapping to proxy weapon",_currentWeapon,_proxyWeapon); +_staticWeapon removeWeaponTurret [_currentWeapon, _turret]; +_staticWeapon addWeaponTurret [_proxyWeapon, _turret]; +_staticWeapon setVariable [format [QGVAR(proxyHandled_%1), _turret], true, true]; diff --git a/addons/csw/functions/fnc_reload_actionsLoad.sqf b/addons/csw/functions/fnc_reload_actionsLoad.sqf new file mode 100644 index 0000000000..c5e7a3b574 --- /dev/null +++ b/addons/csw/functions/fnc_reload_actionsLoad.sqf @@ -0,0 +1,56 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Gets sub actions for what the player can load into the static weapon + * + * Arguments: + * 0: Static Weapon + * 1: Player + * + * Return Value: + * Actions + * + * Example: + * [cursorObject, player] call ace_csw_fnc_reload_actionsLoad + * + * Public: No + */ + +params ["_vehicle", "_player"]; + +private _actions = []; +private _loadableMagazines = [_vehicle, _player] call FUNC(reload_getLoadableMagazines); + +private _statement = { + params ["_target", "_player", "_params"]; + _params params ["_carryMag", "_turretPath"]; + + [_target, _turretPath, _carryMag, _player] call FUNC(reload_loadMagazine); +}; + +private _condition = { + params ["_target", "_player", "_params"]; + _params params ["_carryMag", "_turretPath"]; + + ([_target, _turretPath, _carryMag, _player] call FUNC(reload_canLoadMagazine)) select 0 +}; + +{ + _x params ["_carryMag", "_turretPath", "_loadInfo"]; + _loadInfo params ["", "", "", "_isBeltLinking"]; + + private _displayName = getText (configFile >> "CfgMagazines" >> _carryMag >> "displayName"); + private _picture = getText (configFile >> "CfgMagazines" >> _carryMag >> "picture"); + private _text = if (_isBeltLinking) then { + format [localize LSTRING(actionLink), _displayName]; + } else { + format [localize LSTRING(loadX), _displayName]; + }; + + private _action = [format ["load_%1", _forEachIndex], _text, _picture, _statement, _condition, {}, _x] call EFUNC(interact_menu,createAction); + _actions pushBack [_action, [], _vehicle]; +} forEach _loadableMagazines; + +TRACE_1("loadActions",count _actions); +_actions + diff --git a/addons/csw/functions/fnc_reload_actionsUnload.sqf b/addons/csw/functions/fnc_reload_actionsUnload.sqf new file mode 100644 index 0000000000..34b77b3c6b --- /dev/null +++ b/addons/csw/functions/fnc_reload_actionsUnload.sqf @@ -0,0 +1,81 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Gets sub actions for what the player can load into the static weapon + * + * Arguments: + * 0: Target + * 1: Player + * + * Return Value: + * Actions + * + * Example: + * [cursorObject, player] call ace_csw_fnc_reload_actionsUnload + * + * Public: No + */ + +params ["_vehicle", "_player"]; + +private _statement = { + params ["_target", "_player", "_params"]; + _params params ["_vehMag", "_turretPath", "_carryMag"]; + TRACE_5("starting unload",_target,_turretPath,_player,_carryMag,_vehMag); + + private _timeToUnload = 1; + if (!isNull(configFile >> "CfgVehicles" >> (typeOf _target) >> QUOTE(ADDON) >> "ammoUnloadTime")) then { + _timeToUnload = getNumber(configFile >> "CfgVehicles" >> (typeOf _target) >> QUOTE(ADDON) >> "ammoUnloadTime"); + }; + + [ + TIME_PROGRESSBAR(_timeToUnload), + [_target, _turretPath, _player, _carryMag, _vehMag], + { + (_this select 0) params ["_target", "_turretPath", "", "_carryMag", "_vehMag"]; + TRACE_5("unload progressBar finish",_target,_turretPath,_carryMag,_vehMag,_player); + [QGVAR(removeTurretMag), [_target, _turretPath, _carryMag, _vehMag, _player]] call CBA_fnc_globalEvent; + }, + {TRACE_1("unload progressBar fail",_this);}, + format [localize LSTRING(unloadX), getText (configFile >> "CfgMagazines" >> _carryMag >> "displayName")], + {(_this select 0) call FUNC(reload_canUnloadMagazine)}, + ["isNotInside"] + ] call EFUNC(common,progressBar); +}; + +private _condition = { + params ["_target", "_player", "_params"]; + _params params ["_vehMag", "_turretPath", "_carryMag"]; + [_target, _turretPath, _player, _carryMag, _vehMag] call FUNC(reload_canUnloadMagazine) +}; + +private _actions = []; +private _handeledMagTypes = []; + +// Go through magazines on static weapon and check if any are unloadable +{ + _x params ["_xMag", "_xTurret", "_xAmmo"]; + + if ((_xAmmo > 0) && {!(_xMag in _handeledMagTypes)}) then { + _handeledMagTypes pushBack _xMag; + private _carryMag = GVAR(vehicleMagCache) getVariable _xMag; + + if (isNil "_carryMag") then { + private _groups = "getNumber (_x >> _xMag) == 1" configClasses (configFile >> QGVAR(groups)); + _carryMag = configName (_groups param [0, configNull]); + GVAR(vehicleMagCache) setVariable [_xMag, _carryMag]; + TRACE_2("setting cache",_xMag,_carryMag); + }; + if (_carryMag == "") exitWith {}; + + private _displayName = getText (configFile >> "CfgMagazines" >> _carryMag >> "displayName"); + private _text = format [LLSTRING(unloadX), _displayName]; + private _picture = getText (configFile >> "CfgMagazines" >> _carryMag >> "picture"); + private _action = [format ["unload_%1", _forEachIndex], _text, _picture, _statement, _condition, {}, [_xMag, _xTurret, _carryMag]] call EFUNC(interact_menu,createAction); + _actions pushBack [_action, [], _vehicle]; + }; +} forEach (magazinesAllTurrets _vehicle); + +TRACE_1("unloadActions",count _actions); +_actions + diff --git a/addons/csw/functions/fnc_reload_canLoadMagazine.sqf b/addons/csw/functions/fnc_reload_canLoadMagazine.sqf new file mode 100644 index 0000000000..505c920333 --- /dev/null +++ b/addons/csw/functions/fnc_reload_canLoadMagazine.sqf @@ -0,0 +1,59 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror & TCVM + * Tests if unit can load a magazine into a static weapon. + * + * Arguments: + * 0: Static Weapon + * 1: Turret Path + * 2: Carryable Magazine + * 3: Player + * + * Return Value: + * [CanLoad, LoadedMag, AmmoNeeded, IsBeltLinking] + * + * Example: + * [cursorObject, [0], "ACE_csw_100Rnd_127x99_mag_red", player] call ace_csw_fnc_reload_canLoadMagazine + * + * Public: No + */ + +params ["_vehicle", "_turret", "_carryMag", ["_unit", objNull]]; +// TRACE_4("reload_canLoadMagazine",_vehicle,_turret,_carryMag,_unit); + +// Handle disassembled or deleted +if (!alive _vehicle) exitWith { [false, "", -1, false] }; +// Verify unit has carry magazine +if ((!isNull _unit) && {((_vehicle distance _unit) > 5) || {((magazines _unit) findIf {_x == _carryMag}) == -1}}) exitWith { [false, "", -2, false] }; + +private _desiredAmmo = getNumber (configFile >> "CfgVehicles" >> (typeOf _vehicle) >> QUOTE(ADDON) >> "desiredAmmo"); +if (_desiredAmmo == 0) then { _desiredAmmo = 100; }; +private _ammoNeeded = _desiredAmmo min getNumber (configFile >> "CfgMagazines" >> _carryMag >> "count"); // assume it needs full carry mag +private _loadedMag = ""; +private _isBeltLinking = false; + +scopeName "main"; +{ + _x params ["_xMag", "_xTurret", "_xAmmo"]; + if (_xTurret isEqualTo _turret) then { + if (_loadedMag != "") exitWith { [false, _loadedMag, -3, false] breakOut "main"; }; // Exit if static has multiple mags + _loadedMag = _xMag; + if (_xAmmo > 0) then { + // There is a magazine with ammo loaded in the turret (are there any multi-muzzle static weapons??), see if we can add to this mag + if (getNumber (configFile >> QGVAR(groups) >> _carryMag >> _xMag) != 1) exitWith { + [false, _loadedMag, -4, false] breakOut "main"; // Carry mag cannot be added to existing vehicle mag (e.g. red to green tracers) + }; + if (getNumber (configFile >> "CfgMagazines" >> _carryMag >> "ACE_isBelt") == 0) exitWith { + [false, _loadedMag, -5, false] breakOut "main"; // Non-linkable mag loaded, can't add any more + }; + private _maxMagazineAmmo = _desiredAmmo min getNumber (configFile >> "CfgMagazines" >> _xMag >> "count"); + if (_xAmmo >= _maxMagazineAmmo) exitWith { + [false, _loadedMag, -6, false] breakOut "main"; // Already at capicity + }; + _ammoNeeded = _maxMagazineAmmo - _xAmmo; + _isBeltLinking = true; + }; + }; +} forEach (magazinesAllTurrets _vehicle); + +[true, _loadedMag, _ammoNeeded, _isBeltLinking] diff --git a/addons/csw/functions/fnc_reload_canUnloadMagazine.sqf b/addons/csw/functions/fnc_reload_canUnloadMagazine.sqf new file mode 100644 index 0000000000..2ce6b6e591 --- /dev/null +++ b/addons/csw/functions/fnc_reload_canUnloadMagazine.sqf @@ -0,0 +1,33 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Tests if unit can unload a magazine from a static weapon. + * + * Arguments: + * 0: Static Weapon + * 1: Turret Path + * 2: Player + * 3: Carryable Magazine + * 4: Vehicle Magazine + * + * Return Value: + * + * + * Example: + * [cursorTarget, [0], player, "ACE_csw_100Rnd_127x99_mag_red", "200Rnd_127x99_mag_Tracer_Red"] call ace_csw_fnc_reload_canUnloadMagazine + * + * Public: No + */ + +params ["_vehicle", "_turretPath", "_unit", "_carryMag", "_vehMag"]; + +// handle disassembled or deleted +if ((!alive _vehicle) || {(_vehicle distance _unit) > 5}) exitWith {false}; + +private _return = false; +{ + _x params ["_xMag", "_xTurret", "_xAmmo"]; + if ((_xMag == _vehMag) && {_xTurret isEqualTo _turretPath} && {_xAmmo > 0}) exitWith { _return = true }; +} forEach (magazinesAllTurrets _vehicle); + +_return diff --git a/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf b/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf new file mode 100644 index 0000000000..bbf2b8dc39 --- /dev/null +++ b/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf @@ -0,0 +1,52 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Gets magazines that the player is carrying that can be loaded into the static weapon + * + * Arguments: + * 0: Vehicle + * 1: Player + * + * Return Value: + * Mags + * [Carry Magazine , Turret Path , Ammo Needed ] + * + * Example: + * [cursorObject, player] call ace_csw_fnc_reload_getLoadableMagazines + * + * Public: No + */ + +params ["_vehicle", "_player"]; + +private _carriedMagazines = []; + +{ + if (isClass (configFile >> QGVAR(groups) >> _x)) then { + _carriedMagazines pushBackUnique _x; + }; +} forEach (magazines _player); + +if (_carriedMagazines isEqualTo []) exitWith { [] }; // fast exit if no carry mags + +private _loadInfo = []; +private _return = []; +// Go through turrets and find weapons that we could reload +{ + private _turretPath = _x; + { + private _weapon = _x; + { + private _carryMag = _x; + private _carryGroup = configFile >> QGVAR(groups) >> _carryMag; + { + if (((getNumber (_carryGroup >> _x)) == 1) && {_loadInfo = [_vehicle, _turretPath, _carryMag, _player] call FUNC(reload_canLoadMagazine); _loadInfo select 0}) exitWith { + _return pushBack [_carryMag, _turretPath, _loadInfo]; + }; + } forEach (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines")); + } forEach _carriedMagazines; + } forEach (_vehicle weaponsTurret _turretPath); +} forEach (allTurrets _vehicle); +// Note: these nested forEach's looks terrible, but most only have one element + +_return diff --git a/addons/csw/functions/fnc_reload_getVehicleMagazine.sqf b/addons/csw/functions/fnc_reload_getVehicleMagazine.sqf new file mode 100644 index 0000000000..b6265852c9 --- /dev/null +++ b/addons/csw/functions/fnc_reload_getVehicleMagazine.sqf @@ -0,0 +1,45 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Finds the best vehicle magazines to create from a carryable magazine for a given weapon. + * + * Arguments: + * 0: Weapon + * 1: Magazine that is carryable + * + * Return Value: + * Vehicle Magazine + * + * Example: + * [cursorObject, [0], "ace_csw_100Rnd_127x99_mag"] call ace_csw_fnc_reload_getVehicleMagazine + * + * Public: No + */ + +params ["_vehicle", "_turret", "_carryMag"]; +TRACE_3("reload_getVehicleMagazine",_vehicle,_turret,_carryMag); + +private _carryGroupCfg = configFile >> QGVAR(groups) >> _carryMag; +private _desiredAmmo = getNumber (configFile >> "CfgVehicles" >> (typeOf _vehicle) >> QUOTE(ADDON) >> "desiredAmmo"); +if (_desiredAmmo == 0) then { _desiredAmmo = 100; }; + +private _bestMag = "#"; +private _bestMagCount = -1; + +{ + private _weapon = _x; + { + if ((getNumber (_carryGroupCfg >> _x)) == 1) then { + private _xAmmo = getNumber (configFile >> "CfgMagazines" >> _x >> "ammo"); + if (((_xAmmo >= _bestMagCount) && {_bestMagCount < _desiredAmmo}) || {(_xAmmo >= _desiredAmmo) && {_xAmmo < _bestMagCount}}) then { + _bestMag = _x; + _bestMagCount = _xAmmo; + }; + }; + } forEach (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines")); +} forEach (_vehicle weaponsTurret _turret); +TRACE_3("best fit",_desiredAmmo,_bestMag,_bestMagCount); + +if (_bestMag == "#") then { ERROR_1("veh mag not found for %1",_carryMag); }; + +_bestMag diff --git a/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf b/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf new file mode 100644 index 0000000000..55d10dd4b7 --- /dev/null +++ b/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf @@ -0,0 +1,66 @@ +#include "script_component.hpp" +/* + * Author: TCVM, PabstMirror + * Handles adding ammo to a turret + * Called from a global event but only runs where turret is local + * + * Arguments: + * 0: Static Weapon + * 1: Turret Path + * 2: Unit doing action + * 3: Vehicle Magazine + * 4: Ammo in magazine + * + * Return Value: + * None + * + * Example: + * [cursorTarget, [0], player, "200Rnd_127x99_mag_Tracer_Red", 70] call ace_csw_fnc_reload_handleAddTurretMag + * + * Public: No + */ + +params ["_vehicle", "_turret", "_unit", "_carryMag" ,"_ammoRecieved"]; +TRACE_5("reload_handleAddTurretMag",_vehicle,_turret,_unit,_carryMag,_ammoRecieved); + +TRACE_2("",local _vehicle, _vehicle turretLocal _turret); +if (!(_vehicle turretLocal _turret)) exitWith {}; + +([_vehicle, _turret, _carryMag] call FUNC(reload_canLoadMagazine)) params ["_canAdd", "_loadedMag", "_neededAmmo", "_isBeltLinking"]; +TRACE_4("canLoad",_canAdd,_loadedMag,_neededAmmo,_isBeltLinking); + +private _ammoRemaining = _ammoRecieved; +if (_canAdd) then { + private _ammoUsed = _neededAmmo min _ammoRecieved; + _ammoRemaining = _ammoRemaining - _ammoUsed; + + if (_isBeltLinking) then { + private _currentAmmo = _vehicle magazineTurretAmmo [_loadedMag, _turret]; + _currentAmmo = _currentAmmo + _ammoUsed; + TRACE_2("Setting mag ammo",_loadedMag,_currentAmmo); + // _vehicle setMagazineTurretAmmo [_loadedMag, _currentAmmo, _turret]; + + // setMagazineTurretAmmo is broken on split locality, use setAmmo for now (this may not work for multi turret vehicles) + private _weapon = (_vehicle weaponsTurret _turret) param [0, ""]; + TRACE_3("setAmmo",_vehicle,_weapon, _currentAmmo); + _vehicle setAmmo [_weapon, _currentAmmo]; + private _currentAmmo = _vehicle magazineTurretAmmo [_loadedMag, _turret]; + if ((_weapon == "") || {_currentAmmo != _currentAmmo}) then { ERROR_1("failed to setAmmo - %1", _this); }; + + } else { + if (_loadedMag != "") then { + TRACE_1("Removing emtpy mag",_loadedMag); + _vehicle removeMagazinesTurret [_loadedMag, _turret]; + }; + [_vehicle, _turret, true] call FUNC(proxyWeapon); // Check if we need to add proxy weapon now + private _newMag = [_vehicle, _turret, _carryMag] call FUNC(reload_getVehicleMagazine); + TRACE_2("Adding new mag",_newMag,_ammoUsed); + _vehicle addMagazineTurret [_newMag, _turret, _ammoUsed]; + }; +}; + +if (_ammoRemaining > 0) then { + TRACE_3("Returning ammo",_unit,_carryMag,_ammoRemaining); + [QGVAR(returnAmmo), [_unit, _carryMag, _ammoRemaining], _unit] call CBA_fnc_targetEvent; +}; + diff --git a/addons/csw/functions/fnc_reload_handleRemoveTurretMag.sqf b/addons/csw/functions/fnc_reload_handleRemoveTurretMag.sqf new file mode 100644 index 0000000000..1e64bf82f5 --- /dev/null +++ b/addons/csw/functions/fnc_reload_handleRemoveTurretMag.sqf @@ -0,0 +1,79 @@ +#include "script_component.hpp" +/* + * Author: TCVM + * Handles removing ammo from a turret + * Called from a global event but only runs where turret is local + * + * Arguments: + * 0: Static Weapon + * 1: Turret Path + * 2: Magainze Unit Can Carry + * 3: Magazine To Remove From Static + * 4: Unit to unload to + * + * Return Value: + * None + * + * Example: + * [cursorTarget, [0], "ACE_csw_100Rnd_127x99_mag_red", "500Rnd_127x99_mag_Tracer_Green", player] call ace_csw_fnc_reload_handleRemoveTurretMag + * + * Public: No + */ + +params ["_vehicle", "_turretPath", "_carryMag", "_vehMag", "_unit"]; +TRACE_6("removeTurretMag EH",_vehicle,_turretPath,_carryMag,_vehMag,_unit); + +TRACE_3("",local _vehicle, _vehicle turretLocal _turretPath,local _unit); +if (!(_vehicle turretLocal _turretPath)) exitWith {}; + +private _magsInWeapon = []; // Check how much ammo it has now: +{ + _x params ["_xMag", "_xTurret", "_xAmmo"]; + if ((_xMag == _vehMag) && {_xTurret isEqualTo _turretPath}) then { + _magsInWeapon pushBack _xAmmo; + }; +} forEach (magazinesAllTurrets _vehicle); +TRACE_1("",_magsInWeapon); + +// Remove any empty mags from start: +private _ammoInFirstMag = 0; +while {(!(_magsInWeapon isEqualTo [])) && {_ammoInFirstMag = _magsInWeapon deleteAt 0; (_ammoInFirstMag == 0)}} do { + TRACE_1("Removing empty mag",_ammoInFirstMag); + _vehicle removeMagazineTurret [_vehMag, _turretPath]; +}; +TRACE_2("",_magsInWeapon,_ammoInFirstMag); +if ((_magsInWeapon isEqualTo []) && {_ammoInFirstMag == 0}) exitWith {}; + +private _maxAmmo = getNumber (configFile >> "CfgMagazines" >> _carryMag >> "count"); +private _ammoRemoved = _ammoInFirstMag min _maxAmmo; +private _ammoLeft = _ammoInFirstMag - _ammoRemoved; + +if ((_magsInWeapon isEqualTo []) && {_ammoInFirstMag > _ammoRemoved}) then { + // Only one mag in gun, and we're just taking out a partial ammount (unlinking) + TRACE_2("Setting mag ammo",_ammoRemoved,_ammoLeft); + // _vehicle setMagazineTurretAmmo [_vehMag, _ammoLeft, _turretPath]; + + // setMagazineTurretAmmo is broken on split locality, use setAmmo for now + private _weapon = (_vehicle weaponsTurret _turretPath) param [0, ""]; + TRACE_3("setAmmo",_vehicle,_weapon, _ammoLeft); + _vehicle setAmmo [_weapon, _ammoLeft]; + private _currentAmmo = _vehicle magazineTurretAmmo [_vehMag, _turretPath]; + if ((_weapon == "") || {_currentAmmo != _ammoLeft}) then { ERROR_1("failed to setAmmo - %1", _this); }; + + +} else { + // Because of command limitations, we need to remove mags to change their ammo + // This will cause the gun to need to be reloaded if more than one is loaded (only a problem for non-assembly mode guns) + TRACE_2("Removing magazine",_ammoRemoved,_ammoLeft); + _vehicle removeMagazinesTurret [_vehMag, _turretPath]; + if (_ammoLeft > 0) then { + _magsInWeapon pushBack _ammoLeft; + TRACE_1("Re-adding partial",_ammoLeft); + }; + { + if (_x > 0) then { _vehicle addMagazineTurret [_vehMag, _turretPath, _x]; }; + } forEach _magsInWeapon; +}; + +TRACE_3("Returning ammo",_unit,_carryMag,_ammoRemoved); +[QGVAR(returnAmmo), [_unit, _carryMag, _ammoRemoved], _unit] call CBA_fnc_targetEvent; diff --git a/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf b/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf new file mode 100644 index 0000000000..0cb632bdcb --- /dev/null +++ b/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf @@ -0,0 +1,70 @@ +#include "script_component.hpp" +/* + * Author: TCVM and PabstMirror + * Handles returned ammo (either from unloading or leftovers from linking) + * + * Arguments: + * 0: Man or Vehicle + * 1: Carry Magazine + * 2: Ammo in magazine + * + * Return Value: + * None + * + * Example: + * [player, "ace_csw_100Rnd_127x99_mag", 70] call ace_csw_fnc_reload_handleReturnAmmo + * + * Public: No + */ + +params ["_unloadTo", "_carryMag", "_ammo"]; +TRACE_3("reload_handleReturnAmmo",_unloadTo,_carryMag,_ammo); + +private _carryMaxAmmo = getNumber (configFile >> "CfgMagazines" >> _carryMag >> "count"); +private _fullMagazines = floor (_ammo / _carryMaxAmmo); +private _bulletsRemaining = _ammo % _carryMaxAmmo; + +if (_unloadTo isKindOf "CaManBase") then { + while {(_fullMagazines > 0) && {_unloadTo canAdd _carryMag}} do { + _unloadTo addMagazine [_carryMag, _carryMaxAmmo]; + _fullMagazines = _fullMagazines - 1; + }; + if ((_bulletsRemaining > 0) && {_unloadTo canAdd _carryMag}) then { + _unloadTo addMagazine [_carryMag, _bulletsRemaining]; + _bulletsRemaining = 0; + }; +}; + +if ((_fullMagazines == 0) && {_bulletsRemaining == 0}) exitWith {}; + +// Try to use existing container +private _container = _unloadTo getVariable [QGVAR(container), objNull]; +if ((_container distance _unloadTo) > 4) then { _container = objNull; }; +if (isNull _container) then { + _container = (nearestObjects [_unloadTo, ["groundWeaponHolder"], 4]) param [0, objNull]; +}; + + +if (isNull _container) then { + // Create ground weapon holder container + private _weaponRelPos = _unloadTo getRelPos RELATIVE_DIRECTION(270); + _weaponRelPos set [2, ((getPosATL _unloadTo) select 2) + 0.05]; + _container = createVehicle ["groundWeaponHolder", [0, 0, 0], [], 0, "NONE"]; + // ToDo: Unload to ammo box?? + _unloadTo setVariable [QGVAR(container), container, true]; + _container setDir random [0, 180, 360]; + _container setPosATL _weaponRelPos; + if ((_weaponRelPos select 2) < 0.5) then { + _container setVectorUp (surfaceNormal _weaponRelPos); + }; + TRACE_2("Creating NEW Container",_container,_weaponRelPos); +}; + +TRACE_3("adding to container",_container,_fullMagazines,_bulletsRemaining); + +if (_fullMagazines > 0) then { + _container addMagazineAmmoCargo [_carryMag, _fullMagazines, _carryMaxAmmo]; +}; +if (_bulletsRemaining > 0) then { + _container addMagazineAmmoCargo [_carryMag, 1, _bulletsRemaining]; +}; diff --git a/addons/csw/functions/fnc_reload_loadMagazine.sqf b/addons/csw/functions/fnc_reload_loadMagazine.sqf new file mode 100644 index 0000000000..25032a08f4 --- /dev/null +++ b/addons/csw/functions/fnc_reload_loadMagazine.sqf @@ -0,0 +1,66 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Loads a magazine into a static weapon from a magazine carried by the player. + * + * Arguments: + * 0: Vehicle + * 1: Turret + * 2: Unit Carried Magazine + * 3: Player + * + * Return Value: + * None + * + * Example: + * [cursorTarget, [0], "ACE_csw_100Rnd_127x99_mag_red", player] call ace_csw_fnc_reload_loadMagazine + * + * Public: No + */ + +params ["_vehicle", "_turret", "_carryMag", "_unit"]; +TRACE_4("loadMagazine",_vehicle,_turret,_carryMag,_unit); + +private _timeToLoad = 1; +if (!isNull(configFile >> "CfgVehicles" >> (typeOf _vehicle) >> QUOTE(ADDON) >> "ammoLoadTime")) then { + _timeToLoad = getNumber(configFile >> "CfgVehicles" >> (typeOf _vehicle) >> QUOTE(ADDON) >> "ammoLoadTime"); +}; + +private _displayName = format [localize LSTRING(loadX), getText (configFile >> "CfgMagazines" >> _carryMag >> "displayName")]; + +private _onFinish = { + (_this select 0) params ["_vehicle", "_turret", "_carryMag", "_unit"]; + TRACE_4("load progressBar finish",_vehicle,_turret,_carryMag,_unit); + + ([_vehicle, _turret, _carryMag, _unit] call FUNC(reload_canLoadMagazine)) params ["", "", "_neededAmmo", ""]; + if (_neededAmmo <= 0) exitWith { ERROR_1("Can't load ammo - %1",_this); }; + + // Figure out what we can add from the magazines we have + private _bestAmmoToSend = -1; + { + _x params ["_xMag", "_xAmmo"]; + if (_xMag == _carryMag) then { + if ((_bestAmmoToSend == -1) || {(_xAmmo > _bestAmmoToSend) && {_xAmmo <= _neededAmmo}}) then { + _bestAmmoToSend = _xAmmo; + }; + }; + } forEach (magazinesAmmo _unit); + + if (_bestAmmoToSend == -1) exitWith {ERROR_2("No ammo [%1 - %2]?",_xMag,_bestAmmoToSend);}; + [_unit, _carryMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine); + if (_bestAmmoToSend == 0) exitWith {}; + + TRACE_5("calling addTurretMag event",_vehicle,_turret,_unit,_carryMag,_bestAmmoToSend); + [QGVAR(addTurretMag), [_vehicle, _turret, _unit, _carryMag, _bestAmmoToSend]] call CBA_fnc_globalEvent; +}; + + +[ +TIME_PROGRESSBAR(_timeToLoad), +[_vehicle, _turret, _carryMag, _unit], +_onFinish, +{TRACE_1("load progressBar fail",_this);}, +_displayName, +{((_this select 0) call FUNC(reload_canLoadMagazine)) select 0}, +["isNotInside"] +] call EFUNC(common,progressBar); diff --git a/addons/csw/functions/fnc_staticWeaponInit.sqf b/addons/csw/functions/fnc_staticWeaponInit.sqf new file mode 100644 index 0000000000..2e820ca594 --- /dev/null +++ b/addons/csw/functions/fnc_staticWeaponInit.sqf @@ -0,0 +1,92 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Initializes weapon to disable weapon disassembling + * + * Arguments: + * 0: Weapon + * + * Return Value: + * None + * + * Example: + * [weapon] call ace_csw_fnc_staticWeaponInit + * + * Public: No + */ + +params ["_staticWeapon"]; +private _typeOf = typeOf _staticWeapon; +private _configEnabled = (getNumber (configFile >> "CfgVehicles" >> _typeOf >> "ace_csw" >> "enabled")) == 1; +private _assemblyConfig = _configEnabled && {(getText (configFile >> "CfgVehicles" >> _typeOf >> "ace_csw" >> "disassembleWeapon")) != ""}; +TRACE_4("staticWeaponInit",_staticWeapon,_typeOf,_configEnabled,_assemblyConfig); + +if (_configEnabled && {GVAR(ammoHandling) == 2}) then { + TRACE_1("adding AI fired handler",_staticWeapon); + _staticWeapon addEventHandler ["Fired", LINKFUNC(ai_handleFired)]; +}; + +TRACE_2("",local _staticWeapon,_staticWeapon turretLocal [0]); +if (_configEnabled && {_staticWeapon turretLocal [0]}) then { // if turret is local to us, then handle mags/weapon + [{ + params ["_staticWeapon"]; + if (!alive _staticWeapon) exitWith { TRACE_1("dead/deleted",_staticWeapon); }; + private _assemblyMode = [false, true, GVAR(defaultAssemblyMode)] select (_staticWeapon getVariable [QGVAR(assemblyMode), 2]); + TRACE_2("turretLocal",_staticWeapon,_assemblyMode); + [_staticWeapon, [0], _assemblyMode] call FUNC(proxyWeapon); + [_staticWeapon, _assemblyMode] call FUNC(staticWeaponInit_unloadExtraMags); + }, [_staticWeapon]] call CBA_fnc_execNextFrame; // need to wait a frame to allow setting object vars during assembly +}; + +if (_assemblyConfig) then { + [{ + params ["_staticWeapon"]; + if (!alive _staticWeapon) exitWith { TRACE_1("dead/deleted",_staticWeapon); }; + private _assemblyMode = [false, true, GVAR(defaultAssemblyMode)] select (_staticWeapon getVariable [QGVAR(assemblyMode), 2]); + TRACE_2("assemblyConfig present",_staticWeapon,_assemblyMode); + if (_assemblyMode) then { // Disable vanilla assembly if assemblyMode eanbled + [QGVAR(disableVanillaAssembly), [_staticWeapon]] call CBA_fnc_localEvent; + }; + }, [_staticWeapon]] call CBA_fnc_execNextFrame; // need to wait a frame to allow setting object vars during assembly +}; + +// Add interactions for players +if (hasInterface && {!(_typeOf in GVAR(initializedStaticTypes))}) then { + GVAR(initializedStaticTypes) pushBack _typeOf; + TRACE_1("Adding Actions",_typeOf); + + if (_assemblyConfig) then { + private _disassembleAction = [QGVAR(disassemble), localize LSTRING(DisassembleCSW_displayName), "", {call FUNC(assemble_pickupWeapon)}, {call FUNC(assemble_canPickupWeapon)}] call EFUNC(interact_menu,createAction); + [_typeOf, 0, ["ACE_MainActions"], _disassembleAction] call EFUNC(interact_menu,addActionToClass); + }; + + + private _ammoActionPath = []; + private _magazineLocation = getText (configFile >> "CfgVehicles" >> _typeOf >> QUOTE(ADDON) >> "magazineLocation"); + private _condition = { //IGNORE_PRIVATE_WARNING ["_target", "_player"]; + // If magazine handling is enabled or weapon assembly/disassembly is enabled we enable ammo handling + if ((GVAR(ammoHandling) == 0) && {!([false, true, GVAR(defaultAssemblyMode)] select (_staticWeapon getVariable [QGVAR(assemblyMode), 2]))}) exitWith { false }; + [_player, _target, ["isNotSwimming", "isNotSitting"]] call EFUNC(common,canInteractWith) + }; + private _childenCode = { + BEGIN_COUNTER(getActions); // can remove for final release + private _ret = (call FUNC(reload_actionsLoad)) + (call FUNC(reload_actionsUnload)); + END_COUNTER(getActions); + _ret + }; + if (_configEnabled && {_magazineLocation != ""}) then { + private _positionCode = compile _magazineLocation; + private _ammoAction = [QGVAR(magazine), localize LSTRING(AmmoHandling_displayName), "", {}, _condition, _childenCode, [], _positionCode, 4] call EFUNC(interact_menu,createAction); + _ammoActionPath = [_typeOf, 0, [], _ammoAction] call EFUNC(interact_menu,addActionToClass); + } else { + private _ammoAction = [QGVAR(magazine), localize LSTRING(AmmoHandling_displayName), "", {}, _condition, _childenCode] call EFUNC(interact_menu,createAction); + _ammoActionPath = [_typeOf, 0, ["ACE_MainActions"], _ammoAction] call EFUNC(interact_menu,addActionToClass); + }; + + if (["ACE_reload"] call EFUNC(common,isModLoaded)) then { + // move reload's check ammo action to the ammo handling point (remove and re-add) + [_typeOf, 0, ["ACE_MainActions", QEGVAR(reload,CheckAmmo)]] call EFUNC(interact_menu,removeActionFromClass); + private _checkAmmoAction = [QGVAR(checkAmmo), localize ELSTRING(reload,checkAmmo), "", EFUNC(reload,checkAmmo), EFUNC(reload,canCheckAmmo)] call EFUNC(interact_menu,createAction); + [_typeOf, 0, _ammoActionPath, _checkAmmoAction] call EFUNC(interact_menu,addActionToClass); + }; +}; diff --git a/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf b/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf new file mode 100644 index 0000000000..a5eddfe6a6 --- /dev/null +++ b/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf @@ -0,0 +1,88 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM), PabstMirror + * Dumps ammo to container + * + * Arguments: + * 0: Weapon + * + * Return Value: + * None + * + * Example: + * [weapon] call ace_csw_fnc_staticWeaponInit_unloadExtraMags + * + * Public: No + */ + +params ["_staticWeapon"]; +TRACE_1("staticWeaponInit_unloadExtraMags",_staticWeapon); +if (!alive _staticWeapon) exitWith {TRACE_1("dead/deleted",alive _staticWeapon);}; + +private _assemblyMode = [false, true, GVAR(defaultAssemblyMode)] select (_staticWeapon getVariable [QGVAR(assemblyMode), 2]); +private _emptyWeapon = _staticWeapon getVariable [QGVAR(emptyWeapon), false]; +TRACE_2("",_assemblyMode,_emptyWeapon); + +if (!_assemblyMode) exitWith {}; + +private _desiredAmmo = getNumber (configFile >> "CfgVehicles" >> (typeOf _staticWeapon) >> QUOTE(ADDON) >> "desiredAmmo"); +private _storeExtraMagazines = GVAR(handleExtraMagazines); +if (_emptyWeapon) then { + _desiredAmmo = 0; + _storeExtraMagazines = false; +}; +TRACE_2("settings",_desiredAmmo,_storeExtraMagazines); + +private _magsToRemove = []; +private _loadedMagazineInfo = []; +private _containerMagazineClassnames = []; +private _containerMagazineCount = []; + +{ + _x params ["_xMag", "_xTurret", "_xAmmo"]; + + private _carryMag = GVAR(vehicleMagCache) getVariable _xMag; + if (isNil "_carryMag") then { + private _groups = "getNumber (_x >> _xMag) == 1" configClasses (configFile >> QGVAR(groups)); + _carryMag = configName (_groups param [0, configNull]); + GVAR(vehicleMagCache) setVariable [_xMag, _carryMag]; + TRACE_2("setting cache",_xMag,_carryMag); + }; + if (_carryMag != "") then { + if ((_desiredAmmo > 0) && {_loadedMagazineInfo isEqualTo []}) then { + private _loadedMagAmmo = _desiredAmmo min _xAmmo; + _loadedMagazineInfo = [_xMag, _xTurret, _loadedMagAmmo]; + _xAmmo = _xAmmo - _loadedMagAmmo; + TRACE_1("",_loadedMagAmmo); + }; + if (_xAmmo > 0) then { + _magsToRemove pushBackUnique [_xMag, _xTurret]; + private _index = _containerMagazineClassnames find _carryMag; + if (_index < 0) then { + _index = _containerMagazineClassnames pushBack _carryMag; + _containerMagazineCount pushBack 0; + }; + _containerMagazineCount set [_index, (_containerMagazineCount select _index) + _xAmmo]; + }; + } else { + if ((_xMag select [0,4]) != "fake") then { WARNING_1("Unable to unload [%1] - No matching carry mag",_xMag); }; + }; +} forEach (magazinesAllTurrets _staticWeapon); + + +TRACE_1("Remove all loaded magazines",_magsToRemove); +{ + _staticWeapon removeMagazinesTurret _x; + if ((_loadedMagazineInfo select [0,2]) isEqualTo _x) then { + TRACE_1("Re-add the starting mag",_loadedMagazineInfo); + _staticWeapon addMagazineTurret _loadedMagazineInfo; + }; +} forEach _magsToRemove; + + +if (_storeExtraMagazines) then { + TRACE_1("saving extra mags to container",_containerMagazineCount); + { + [_staticWeapon, _x, _containerMagazineCount select _forEachIndex] call FUNC(reload_handleReturnAmmo); + } forEach _containerMagazineClassnames; +}; diff --git a/addons/csw/functions/script_component.hpp b/addons/csw/functions/script_component.hpp new file mode 100644 index 0000000000..7e8eaa8954 --- /dev/null +++ b/addons/csw/functions/script_component.hpp @@ -0,0 +1 @@ +#include "\z\ace\addons\csw\script_component.hpp" diff --git a/addons/csw/initSettings.sqf b/addons/csw/initSettings.sqf new file mode 100644 index 0000000000..868597f94c --- /dev/null +++ b/addons/csw/initSettings.sqf @@ -0,0 +1,43 @@ +// CBA Settings [ADDON: ace_csw]: + +private _categoryArray = [format ["ACE %1", localize LSTRING(DisplayName)]]; + +[ + QGVAR(defaultAssemblyMode), "CHECKBOX", + [LSTRING(defaultAssemblyMode_displayName), LSTRING(defaultAssemblyMode_description)], + _categoryArray, + false, // default value + true, // isGlobal + {[QGVAR(defaultAssemblyMode), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_settings_fnc_init; + +[ + QGVAR(handleExtraMagazines), "CHECKBOX", + [LSTRING(handleExtraMagazines_displayName), LSTRING(handleExtraMagazines_description)], + _categoryArray, + true, // default value + true, // isGlobal + {[QGVAR(handleExtraMagazines), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_settings_fnc_init; + +[ + QGVAR(ammoHandling), "LIST", + [LSTRING(ammoHandling_displayName), LSTRING(ammoHandling_description)], + _categoryArray, + [[0, 1, 2], [LELSTRING(common,Disabled), LELSTRING(common,playerOnly), LELSTRING(common,playersAndAI)], 2], // [_values, _valueTitles, _defaultIndex] + true, // isGlobal + {[QGVAR(ammoHandling), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_settings_fnc_init; + +[ + QGVAR(progressBarTimeCoefficent), "SLIDER", + [LSTRING(progressBarTimeCoefficent_displayName), LSTRING(progressBarTimeCoefficent_description)], + _categoryArray, + [0,2,1,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)] + true, // isGlobal + {[QGVAR(progressBarTimeCoefficent), _this] call EFUNC(common,cbaSettings_settingChanged)}, + false // Needs mission restart +] call CBA_settings_fnc_init; diff --git a/addons/csw/script_component.hpp b/addons/csw/script_component.hpp new file mode 100644 index 0000000000..ab263d6dec --- /dev/null +++ b/addons/csw/script_component.hpp @@ -0,0 +1,28 @@ +#define COMPONENT csw +#define COMPONENT_BEAUTIFIED Crew-Served Weapons +#include "\z\ace\addons\main\script_mod.hpp" + +#define FAST_PROGRESSBARS +#define DEBUG_MODE_FULL +#define DISABLE_COMPILE_CACHE +#define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_CSW + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_CSW + #define DEBUG_SETTINGS DEBUG_SETTINGS_CSW +#endif + +#include "\z\ace\addons\main\script_macros.hpp" + + +#define DISTANCE_FROM_GUN 1.5 +#define RELATIVE_DIRECTION(direction) [DISTANCE_FROM_GUN, direction] + +#ifdef FAST_PROGRESSBARS + #define TIME_PROGRESSBAR(X) ((X) * 0.075) +#else + #define TIME_PROGRESSBAR(X) ((X) * GVAR(progressBarTimeCoefficent)) +#endif diff --git a/addons/csw/stringtable.xml b/addons/csw/stringtable.xml new file mode 100644 index 0000000000..e71400da6c --- /dev/null +++ b/addons/csw/stringtable.xml @@ -0,0 +1,220 @@ + + + + + Crew Served Weapons + + + CSW Tripod + + + Place Tripod + + + Disassemble + Rozložit + Démonter + %1 demontieren + Disassemblare + Złóż + Desmontar + Разобрать + Desmonta + + + Get In + Nastup + Embarquer + Einsteigen + A bordo + Wsiadać + Entrar + Войти + Entrar + + + Load %1 + Lade %1 + Load %1 + Nabít %1 + Load %1 + Załaduj %1 + Load %1 + Загрузить %1 + Load %1 + + + Unload %1 + Entlade %1 + Unload %1 + Vytáhnout zásobník z %1 + Unload %1 + Rozładuj %1 + Unload %1 + Разгрузить %1 + Unload %1 + + + Link %1 + + + Advanced assembly + + + Use ace for Assemble/Disassemble of supported static weapons. Loaded ammo is reduced to a single magazine. + + + Save extra ammo + + + Store extra magazines next to static weapon + + + Ammo handling + + + Allow loading and unloading magazines + + + AI Reloading + + + AI will attempt to reload static weapons with available ammo + + + Interaction Time Coefficent + + + Scales time required to assemble and reload static weapons + + + Pickup Tripod + + + Move Tripod + + + Mount Weapon + + + Disassembling Gun... + + + Assembling Gun... + + + Loading Ammo... + + + Unloading Ammo... + + + Picking Up Tripod... + + + Placing Tripod... + + + Enable CSW + + + Enables Crew Served ability on this weapon + + + Used to reload crew served weapons + + + [CSW] Deployable Tripod + + + [CSW] Deployable Tripod (Low) + + + [CSW] Mk6 Mortar Baseplate + + + [CSW] Mk6 Mortar Tube + + + [CSW] Mini-Spike Launcher (AT) + + + [CSW] Mini-Spike Launcher (AA) + + + [CSW] XM312 + + + [CSW] XM312A + + + [CSW] XM312 (High) + + + [CSW] XM307 + + + [CSW] XM307A + + + [CSW] XM307 (High) + + + [CSW] Static Mini-Spike Launcher (AT) + + + [CSW] Static Mini-Spike Launcher (AA) + + + [CSW] Static XM312 Gun + + + [CSW] Static XM312 Gun (Autonomous) + + + [CSW] Static XM312 Gun (High) + + + [CSW] Static XM307 Gun + + + [CSW] Static XM307 Gun (Autonomous) + + + [CSW] Static XM307 Gun (High) + + + [CSW] HMG Static + + + [CSW] GMG Static + + + [CSW] AT Static + + + [CSW] AA Static + + + [CSW] 12.7x108mm HMG Belt + + + [CSW] 12.7x99mm HMG Belt + + + [CSW] 12.7x99mm Tracer HMG Belt (Red) + + + [CSW] 12.7x99mm Tracer HMG Belt (Green) + + + [CSW] 12.7x99mm Tracer HMG Belt (Yellow) + + + [CSW] 20mm Grenade GMG Belt + + + [CSW] 12.7 x 108 mm Ammo Belt + + + diff --git a/addons/mk6mortar/CfgVehicles.hpp b/addons/mk6mortar/CfgVehicles.hpp index 4a5d420f5c..41e45abf35 100644 --- a/addons/mk6mortar/CfgVehicles.hpp +++ b/addons/mk6mortar/CfgVehicles.hpp @@ -24,9 +24,12 @@ class CfgVehicles { class Turrets: Turrets { class MainTurret: MainTurret {}; }; - class ACE_Actions; }; class Mortar_01_base_F: StaticMortar { + class ace_csw { + proxyWeapon = QFUNC(csw_getProxyWeapon); + magazineLocation = "_target selectionPosition 'usti hlavne'"; + }; class Turrets: Turrets { class MainTurret: MainTurret { turretInfoType = "ACE_Mk6_RscWeaponRangeArtillery"; @@ -34,54 +37,6 @@ class CfgVehicles { discreteDistanceInitIndex = 0; }; }; - class ACE_Actions: ACE_Actions { - class GVAR(unloadMagazine) { - displayName = CSTRING(unloadMortar); - distance = 2; - condition = QUOTE(_this call FUNC(canUnloadMagazine)); - statement = QUOTE([ARR_3(_target,_player,5)] call FUNC(unloadMagazineTimer)); - icon = ""; - selection = "usti hlavne"; - }; - class GVAR(LoadActions) { - displayName = CSTRING(loadMortar); - distance = 2; - condition = QUOTE([ARR_2(_target,_player)] call FUNC(canLoadMagazine)); - statement = ""; - icon = ""; - selection = "usti hlavne"; - class GVAR(loadMagazine_HE_Guided) { - displayName = CSTRING(loadMagazine_HE_Guided); - condition = QUOTE([ARR_3(_target,_player,'ACE_1Rnd_82mm_Mo_HE_Guided')] call FUNC(canLoadMagazine)); - statement = QUOTE([ARR_4(_target,_player,8,'ACE_1Rnd_82mm_Mo_HE_Guided')] call FUNC(loadMagazineTimer)); - icon = ""; - }; - class GVAR(loadMagazine_HE_LaserGuided) { - displayName = CSTRING(loadMagazine_HE_LaserGuided); - condition = QUOTE([ARR_3(_target,_player,'ACE_1Rnd_82mm_Mo_HE_LaserGuided')] call FUNC(canLoadMagazine)); - statement = QUOTE([ARR_4(_target,_player,8,'ACE_1Rnd_82mm_Mo_HE_LaserGuided')] call FUNC(loadMagazineTimer)); - icon = ""; - }; - class GVAR(loadMagazine_Illum) { - displayName = CSTRING(loadMagazine_Illum); - condition = QUOTE([ARR_3(_target,_player,'ACE_1Rnd_82mm_Mo_Illum')] call FUNC(canLoadMagazine)); - statement = QUOTE([ARR_4(_target,_player,5,'ACE_1Rnd_82mm_Mo_Illum')] call FUNC(loadMagazineTimer)); - icon = ""; - }; - class GVAR(loadMagazine_Smoke) { - displayName = CSTRING(loadMagazine_Smoke); - condition = QUOTE([ARR_3(_target,_player,'ACE_1Rnd_82mm_Mo_Smoke')] call FUNC(canLoadMagazine)); - statement = QUOTE([ARR_4(_target,_player,2.5,'ACE_1Rnd_82mm_Mo_Smoke')] call FUNC(loadMagazineTimer)); - icon = ""; - }; - class GVAR(loadMagazine_HE) { - displayName = CSTRING(loadMagazine_HE); - condition = QUOTE([ARR_3(_target,_player,'ACE_1Rnd_82mm_Mo_HE')] call FUNC(canLoadMagazine)); - statement = QUOTE([ARR_4(_target,_player,2.5,'ACE_1Rnd_82mm_Mo_HE')] call FUNC(loadMagazineTimer)); - icon = ""; - }; - }; - }; class ACE_SelfActions { class GVAR(toggleMils) { displayName = "Toggle MILS"; diff --git a/addons/mk6mortar/XEH_PREP.hpp b/addons/mk6mortar/XEH_PREP.hpp index 600fc0707f..03d6bd6051 100644 --- a/addons/mk6mortar/XEH_PREP.hpp +++ b/addons/mk6mortar/XEH_PREP.hpp @@ -5,19 +5,14 @@ PREP(dev_simulateCalcRangeTableLine); PREP(dev_simulateFindSolution); PREP(dev_simulateShot); -PREP(canLoadMagazine); -PREP(canUnloadMagazine); +PREP(csw_getProxyWeapon); + PREP(handleFired); PREP(handlePlayerVehicleChanged); -PREP(loadMagazine); -PREP(loadMagazineTimer); PREP(moduleInit); -PREP(mortarInit); PREP(rangeTableCanUse); PREP(rangeTableOpen); PREP(rangeTablePageChange); PREP(rangeTablePreCalculatedValues); PREP(toggleMils); PREP(turretDisplayLoaded); -PREP(unloadMagazine); -PREP(unloadMagazineTimer); diff --git a/addons/mk6mortar/XEH_postInit.sqf b/addons/mk6mortar/XEH_postInit.sqf index e3169b6dba..338f859767 100644 --- a/addons/mk6mortar/XEH_postInit.sqf +++ b/addons/mk6mortar/XEH_postInit.sqf @@ -1,22 +1,5 @@ #include "script_component.hpp" -[QGVAR(addMagazine), { - params ["_static", "_magazine"]; - _static addMagazineTurret [_magazine,[0]]; -}] call CBA_fnc_addEventHandler; - -[QGVAR(removeMagazine), { - params ["_static", "_magazine"]; - _static removeMagazineTurret [_magazine,[0]]; -}] call CBA_fnc_addEventHandler; - -[QGVAR(setAmmo), { - params ["_static", "_magazine","_ammoCount"]; - _static setMagazineTurretAmmo [_magazine, _ammoCount, [0]]; -}] call CBA_fnc_addEventHandler; - -["ace_initMortar", {_this call FUNC(mortarInit);}] call CBA_fnc_addEventHandler; - if (hasInterface) then { ["ace_infoDisplayChanged", FUNC(turretDisplayLoaded)] call CBA_fnc_addEventHandler; }; @@ -25,17 +8,4 @@ if (hasInterface) then { TRACE_1("ace_settingsInitialized",GVAR(useAmmoHandling)); ["vehicle", FUNC(handlePlayerVehicleChanged), true] call CBA_fnc_addPlayerEventHandler; - - if (GVAR(useAmmoHandling)) then { - ["Mortar_01_base_F", "init", { - TRACE_2("mortar init",_this,(_this select 0) turretLocal [0]); - - //wait for proper turret locality change - [{ - TRACE_2("after delay",_this,(_this select 0) turretLocal [0]); - ["ace_initMortar", _this] call CBA_fnc_localEvent; - }, _this, 0.5] call CBA_fnc_waitAndExecute; - - }, true, [], true] call CBA_fnc_addClassEventHandler; - }; }] call CBA_fnc_addEventHandler; diff --git a/addons/mk6mortar/config.cpp b/addons/mk6mortar/config.cpp index f387632446..79fd043619 100644 --- a/addons/mk6mortar/config.cpp +++ b/addons/mk6mortar/config.cpp @@ -7,7 +7,7 @@ class CfgPatches { "ACE_Box_82mm_Mo_Illum","ACE_Box_82mm_Mo_Combo"}; weapons[] = {"ACE_RangeTable_82mm","ace_mortar_82mm"}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_interaction"}; + requiredAddons[] = {"ace_csw"}; author = ECSTRING(common,ACETeam); authors[] = {"PabstMirror","Grey","VKing"}; url = ECSTRING(main,URL); diff --git a/addons/mk6mortar/functions/fnc_canLoadMagazine.sqf b/addons/mk6mortar/functions/fnc_canLoadMagazine.sqf deleted file mode 100644 index 67bcf4d522..0000000000 --- a/addons/mk6mortar/functions/fnc_canLoadMagazine.sqf +++ /dev/null @@ -1,52 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * Checks whether magazine can be loaded into static weapon - * - * Arguments: - * 0: static - * 1: unit - * 2: magazine class to check; if not given having any compatible magazine returns true (default: "") - * - * Return Value: - * canLoadMagazine - * - * Example: - * [_target,_player,"ACE_1Rnd_82mm_Mo_HE"] call ace_mk6mortar_fnc_canLoadMagazine - * - * Public: Yes - */ - -params ["_static","_unit",["_magazineClassOptional","",[""]]]; - -if !(alive _static && GVAR(useAmmoHandling)) exitWith {false}; -if (_static getVariable [QGVAR(inUse), false]) exitWith {false}; - -private _canLoadMagazine = false; -private _hasCompatibleMagazine = false; - -private _currentMagazine = (magazinesAllTurrets _static) select 1; -private _weapon = (_static weaponsTurret [0]) select 0; - -private _listOfMagNames = getArray(configFile >> "cfgWeapons" >> _weapon >> "magazines"); -private _count = 0; - -//If function is called with an optional string then check if player has that magzine otherwise check all magazines of the player to see if they are compatible with the static weapon -if (_magazineClassOptional != "") then { - if ([_unit,_magazineClassOptional] call EFUNC(common,hasMagazine)) then { - _hasCompatibleMagazine = true; - }; - } else { - { - if ([_unit,_x] call EFUNC(common,hasMagazine)) exitWith {_hasCompatibleMagazine = true}; - } forEach _listOfMagNames; -}; -//If static weapon has a magazine then find the ammo count -if (count (_static magazinesTurret [0]) > 0) then { - _count = _currentMagazine select 2; -}; -//If the static weapon doesn't have a magzine or a magazine with no bullets, the player has a compatible magazine and the static weapon has a barrel then you can load a magazine -if ((count (_static magazinesTurret [0]) == 0 || _count == 0) && _hasCompatibleMagazine) then { - _canLoadMagazine = true; -}; -_canLoadMagazine diff --git a/addons/mk6mortar/functions/fnc_canUnloadMagazine.sqf b/addons/mk6mortar/functions/fnc_canUnloadMagazine.sqf deleted file mode 100644 index a296d56c32..0000000000 --- a/addons/mk6mortar/functions/fnc_canUnloadMagazine.sqf +++ /dev/null @@ -1,30 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * Checks whether magazine can be unloaded from static weapon - * - * Arguments: - * 0: static - * 1: unit - * - * Return Value: - * canUnloadMagazine - * - * Example: - * [_target,_player] call ace_mk6mortar_fnc_canUnloadMagazine - * - * Public: Yes - */ - -params ["_static","_unit"]; - -if !(alive _static && GVAR(useAmmoHandling) && _static getVariable [QGVAR(initialized),false]) exitWith {false}; -if (_static getVariable [QGVAR(inUse), false]) exitWith {false}; - -private _canUnloadMagazine = false; - -private _ammoCount = ((magazinesAllTurrets _static) select 1) select 2; -if (_ammoCount > 0) then { - _canUnloadMagazine = true; -}; -_canUnloadMagazine diff --git a/addons/mk6mortar/functions/fnc_csw_getProxyWeapon.sqf b/addons/mk6mortar/functions/fnc_csw_getProxyWeapon.sqf new file mode 100644 index 0000000000..04ed2a0014 --- /dev/null +++ b/addons/mk6mortar/functions/fnc_csw_getProxyWeapon.sqf @@ -0,0 +1,68 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror + * Compatibility With ACE_CSW (will be called by ace_csw, no dependency) + * Setting Init has finished, and this runs before csw attempts to unload weapon, should replicate functionality of mk6_fnc_mortarInit + * + * Arguments: + * 0: static + * 1: Turret + * 2: current weapon + * 3: need proxy weapon (either assembly mode is true, or weapon has been emptied and is being reloaded) + * + * Return Value: + * Proxy Weapon + * + * Example: + * [mortar, "mortar_82mm", true] call ace_mk6mortar_fnc_csw_getProxyWeapon + * + * Public: No + */ + +params ["_mortar", "_turret", "_currentWeapon", "_proxyWeaponNeeded"]; +TRACE_4("csw_getProxyWeapon",_mortar,_turret,_currentWeapon,_proxyWeaponNeeded); + +private _newWeapon = ""; + +if (_proxyWeaponNeeded || GVAR(useAmmoHandling)) then { + if (_currentWeapon != "mortar_82mm") exitWith { ERROR_2("unknown weapon [%1 - %2]",typeOf _mortar,_currentWeapon); }; + + // Replace weapon with fast reloading version + _newWeapon = "ace_mortar_82mm"; + TRACE_1("replacing weapon",_newWeapon); + + // need to convert 8rnd mags to 1rnd mags for new weapon (we need to do this so the weapon is loaded with a compatible mag) + private _magsToRemove = []; + private _convertedMags = []; + { + _x params ["_xMag", "_xTurret", "_xAmmo"]; + + if (_xTurret isEqualTo _turret) then { + private _replaceMag = switch (true) do { + case (_xMag == "8Rnd_82mm_Mo_shells"): {"ACE_1Rnd_82mm_Mo_HE"}; + case (_xMag == "8Rnd_82mm_Mo_Smoke_white"): {"ACE_1Rnd_82mm_Mo_Smoke"}; + case (_xMag == "8Rnd_82mm_Mo_Flare_white"): {"ACE_1Rnd_82mm_Mo_Illum"}; + case (_xMag == "8Rnd_82mm_Mo_guided"): {"ACE_1Rnd_82mm_Mo_HE_Guided"}; + case (_xMag == "8Rnd_82mm_Mo_LG"): {"ACE_1Rnd_82mm_Mo_HE_LaserGuided"}; + default {""}; + }; + if (_replaceMag != "") then { + _magsToRemove pushBackUnique [_xMag, _xTurret]; + if (!GVAR(useAmmoHandling)) then { + TRACE_3("replacing",_xMag,_replaceMag,_xAmmo); + for "_i" from 1 to _xAmmo do { + _convertedMags pushBack [_replaceMag, _xTurret, 1]; + }; + }; + } else { + WARNING("unknown mag %1", _xMag); + }; + }; + } forEach (magazinesAllTurrets _mortar); + + // remove orignal mags and add 1rnd versions: + { _staticWeapon removeMagazinesTurret _x; } forEach _magsToRemove; + { _mortar addMagazineTurret _x; } forEach _convertedMags; +}; + +_newWeapon diff --git a/addons/mk6mortar/functions/fnc_handleFired.sqf b/addons/mk6mortar/functions/fnc_handleFired.sqf index 02a8e51ce0..550ae05f8a 100644 --- a/addons/mk6mortar/functions/fnc_handleFired.sqf +++ b/addons/mk6mortar/functions/fnc_handleFired.sqf @@ -23,13 +23,6 @@ params ["_vehicle", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile"]; -if (GVAR(useAmmoHandling) && {_vehicle getVariable [QGVAR(initialized),false] && !(_vehicle getVariable [QGVAR(exclude),false])}) then { - // if !(_vehicle getVariable [QGVAR(exclude),false]) then { - _vehicle removeMagazineGlobal (_vehicle magazinesTurret [0] select 0); - TRACE_1("",_vehicle magazinesTurret [0]); - // }; -}; - if (!GVAR(airResistanceEnabled)) exitWith {}; // Large enough distance to not simulate any wind deflection diff --git a/addons/mk6mortar/functions/fnc_handlePlayerVehicleChanged.sqf b/addons/mk6mortar/functions/fnc_handlePlayerVehicleChanged.sqf index fd53bcf3d4..6e0b9b1794 100644 --- a/addons/mk6mortar/functions/fnc_handlePlayerVehicleChanged.sqf +++ b/addons/mk6mortar/functions/fnc_handlePlayerVehicleChanged.sqf @@ -21,20 +21,6 @@ params ["_player", "_newVehicle"]; if (isNull _newVehicle) exitWith {}; if (!(_newVehicle isKindOf "Mortar_01_base_F")) exitWith {}; -// Run magazine handling initialization if enabled -if (!(_newVehicle getVariable [QGVAR(initialized),false]) && !(_newVehicle getVariable [QGVAR(exclude),false])) then { - // Make sure that mortar init is executed after settings init - [{ - params ["_mortar"]; - if (GVAR(useAmmoHandling) && {!(_mortar getVariable [QGVAR(initialized),false]) && !(_mortar getVariable [QGVAR(exclude),false])}) then { - //wait for proper turret locality change - [{ - ["ace_initMortar", [_this], [_this]] call CBA_fnc_globalEvent; - }, _mortar, 0.05] call CBA_fnc_waitAndExecute; - }; - }, _newVehicle] call EFUNC(common,runAfterSettingsInit); -}; - private _tubeWeaponName = (weapons _newVehicle) select 0; private _fireModes = getArray (configFile >> "CfgWeapons" >> _tubeWeaponName >> "modes"); diff --git a/addons/mk6mortar/functions/fnc_loadMagazine.sqf b/addons/mk6mortar/functions/fnc_loadMagazine.sqf deleted file mode 100644 index 297fb2a969..0000000000 --- a/addons/mk6mortar/functions/fnc_loadMagazine.sqf +++ /dev/null @@ -1,62 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * Loads Magazine into static weapon - * - * Arguments: - * 0: static - * 1: unit - * 2: magazine class to load; if not given the first compatible magazine is loaded (default: "") - * - * Return Value: - * None - * - * Example: - * [_target,_player,"ACE_1Rnd_82mm_Mo_HE"] call ace_mk6mortar_fnc_loadMagazine - * - * Public: Yes - */ - -params ["_static","_unit",["_magazineClassOptional","",[""]]]; - -//If function has been called with an optional classname hten add that magazine to the static weapon. Otherwise add the compatible magazine -if(_magazineClassOptional != "") then { - _unit removeMagazine _magazineClassOptional; - [QGVAR(addMagazine), [_static, _magazineClassOptional]] call CBA_fnc_globalEvent; -} else { - //Get weapon & magazine information of static weapon - private _weapon = (_static weaponsTurret [0]) select 0; - private _currentMagazine = (magazinesAllTurrets _static) select 1; - private _currentMagazineClass = _currentMagazine select 0; - private _count = _currentMagazine select 2; - - //Check all of the players magazines to see if they are compatible with the static weapon. First magazine that is compatible is chosen - //VKing: This section ought to be double checked. - private _magazines = magazines _unit; - private _magazineDetails = magazinesDetail _unit; - private _listOfMagNames = getArray(configFile >> "cfgWeapons" >> _weapon >> "magazines"); - private _magazineClass = ""; - private _magazineClassDetails = ""; - private _roundsLeft = 0; - { - if (_x in _listOfMagNames) exitWith { - _magazineClass = _x; - _magazineClassDetails = _magazineDetails select _forEachIndex; - }; - } forEach _magazines; - //If the static weapon already has an empty magazine then remove it - if (_count == 0) then { - [QGVAR(removeMagazine), [_static, _currentMagazineClass]] call CBA_fnc_globalEvent; - }; - //Find out the ammo count of the compatible magazine found - if (_magazineClassDetails != "") then{ - private _parsed = _magazineClassDetails splitString "([]/: )"; - _parsed params ["_type", "", "", "_roundsLeftText", "_maxRoundsText"]; - _roundsLeft = parseNumber _roundsLeftText; - _magType = _type; - }; - - _unit removeMagazine _magazineClass; - [QGVAR(addMagazine), [_static, _magazineClass]] call CBA_fnc_globalEvent; - [QGVAR(setAmmo), [_static, _magazineClass,_roundsLeft], _static] call CBA_fnc_targetEvent; -}; diff --git a/addons/mk6mortar/functions/fnc_loadMagazineTimer.sqf b/addons/mk6mortar/functions/fnc_loadMagazineTimer.sqf deleted file mode 100644 index cfc6adff08..0000000000 --- a/addons/mk6mortar/functions/fnc_loadMagazineTimer.sqf +++ /dev/null @@ -1,30 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * Loads Magazine into static weapon using a timer. - * - * Arguments: - * 0: Static - * 1: Unit - * 2: Time to load - * 3: Magazine Class (default: "") - * - * Return Value: - * None - * - * Example: - * [_target,_player,"ACE_1Rnd_82mm_Mo_HE"] call ace_mk6mortar_fnc_loadMagazineTimer - * - * Public: Yes - */ - -params ["_static","_unit","_timeToLoad",["_magazineClassOptional","",[""]]]; - -_static setVariable [QGVAR(inUse), true, true]; - -// Move player into animation if player is standing -if ((_unit call CBA_fnc_getUnitAnim) select 0 == "stand") then { - [_unit, "AmovPercMstpSrasWrflDnon_diary", 1] call EFUNC(common,doAnimation); -}; - -[_timeToLoad, [_static,_unit,_magazineClassOptional], {(_this select 0) call FUNC(loadMagazine); ((_this select 0) select 0) setVariable [QGVAR(inUse), nil, true]}, {((_this select 0) select 0) setVariable [QGVAR(inUse), nil, true]}, localize LSTRING(loadingMortar)] call EFUNC(common,progressBar); diff --git a/addons/mk6mortar/functions/fnc_mortarInit.sqf b/addons/mk6mortar/functions/fnc_mortarInit.sqf deleted file mode 100644 index 46c16738bf..0000000000 --- a/addons/mk6mortar/functions/fnc_mortarInit.sqf +++ /dev/null @@ -1,46 +0,0 @@ -#include "script_component.hpp" -/* - * Author: VKing - * Initializes mortar for use with ammunition handling magazines. - * - * Arguments: - * 0: Mortar - * - * Return Value: - * None - * - * Example: - * [mortar1] call ace_mk6mortar_fnc_mortarInit - * - * Public: No - */ - -params ["_mortar"]; - -if (_mortar getVariable [QGVAR(initialized),false] || _mortar getVariable [QGVAR(exclude),false]) exitWith {TRACE_1("Exit",_mortar)}; -if (!(_mortar turretLocal [0])) exitWith {TRACE_1("Exit - turret not local",_mortar)}; - -// Remove all magazines from turret -if (count magazines _mortar > 0) then { - { - _mortar removeMagazineTurret [_x,[0]]; - } forEach magazines _mortar; -}; - -// Replace current turret weapon with ammo handling weapon -private _currentWeapon = _mortar weaponsTurret [0] select 0; -private _newWeapon = ""; - -if (_currentWeapon == "mortar_82mm") then { - _newWeapon = "ace_mortar_82mm"; -} else { - _newWeapon = getText (configFile >> "CfgWeapons" >> _currentWeapon >> QGVAR(replaceWith)); -}; - -if (_newWeapon != "") then { - _mortar removeWeaponTurret [_currentWeapon,[0]]; - _mortar addWeaponTurret [_newWeapon,[0]]; -}; - -_mortar setVariable [QGVAR(initialized),true,true]; -TRACE_1("Init complete",_mortar); diff --git a/addons/mk6mortar/functions/fnc_unloadMagazine.sqf b/addons/mk6mortar/functions/fnc_unloadMagazine.sqf deleted file mode 100644 index 4da21b3e8f..0000000000 --- a/addons/mk6mortar/functions/fnc_unloadMagazine.sqf +++ /dev/null @@ -1,38 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * - * Unload current magazine from static weapon - * - * Arguments: - * 0: static - * 1: unit - * - * Return Value: - * None - * - * Example: - * [_target, _player] call ace_mk6mortar_fnc_unloadMagazine - * - * Public: Yes - */ - -params ["_static","_unit"]; - -//Get weapon & magazine information about static weapon -private _currentMagazine = (magazinesAllTurrets _static) select 1; -private _currentMagazineClass = _currentMagazine select 0; -private _ammoCount = _currentMagazine select 2; - -// Try to add the round to player inventory, otherwise place it on the ground near the player -if (_ammoCount > 0) then { - if (_unit canAdd _currentMagazineClass) then { - _unit addMagazineGlobal _currentMagazineClass; - } else { - _pos = _unit modelToWorldVisual [0.5,0.5,0]; // Front right of player - _unit = createVehicle ["WeaponHolder_Single_F",_pos,[],0,"NONE"]; - _unit addMagazineAmmoCargo [_currentMagazineClass, 1, _ammoCount]; - _unit setPosATL _pos; - }; - [QGVAR(removeMagazine), [_static, _currentMagazineClass]] call CBA_fnc_globalEvent; -}; diff --git a/addons/mk6mortar/functions/fnc_unloadMagazineTimer.sqf b/addons/mk6mortar/functions/fnc_unloadMagazineTimer.sqf deleted file mode 100644 index 4c152bc7d1..0000000000 --- a/addons/mk6mortar/functions/fnc_unloadMagazineTimer.sqf +++ /dev/null @@ -1,30 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Grey - * - * Unload current magazine from static weapon using a timer - * - * Arguments: - * 0: static - * 1: unit - * 2: time to unload - * - * Return Value: - * None - * - * Example: - * [_target, _player, 5] call ace_mk6mortar_fnc_unloadMagazineTimer - * - * Public: Yes - */ - -params ["_static","_unit","_timeToUnload"]; - -_static setVariable [QGVAR(inUse), true, true]; - -//Move player into animation if player is standing -if ((_unit call CBA_fnc_getUnitAnim) select 0 == "stand") then { - [_unit, "AmovPercMstpSrasWrflDnon_diary", 1] call EFUNC(common,doAnimation); -}; - -[_timeToUnload, [_static,_unit], {(_this select 0) call FUNC(unloadMagazine); ((_this select 0) select 0) setVariable [QGVAR(inUse), nil, true]}, {((_this select 0) select 0) setVariable [QGVAR(inUse), nil, true]}, localize LSTRING(unloadingMortar)] call EFUNC(common,progressBar); diff --git a/addons/reload/CfgVehicles.hpp b/addons/reload/CfgVehicles.hpp index 7a1d483bd9..fe1e9672e6 100644 --- a/addons/reload/CfgVehicles.hpp +++ b/addons/reload/CfgVehicles.hpp @@ -13,8 +13,8 @@ class CfgVehicles { class GVAR(CheckAmmo) { displayName = CSTRING(checkAmmo); distance = 2.0; - condition = QUOTE([ARR_2(_player, _target)] call FUNC(canCheckAmmo)); - statement = QUOTE([ARR_2(_player, _target)] call FUNC(checkAmmo)); + condition = QUOTE(call FUNC(canCheckAmmo)); + statement = QUOTE(call FUNC(checkAmmo)); exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"}; }; }; @@ -28,8 +28,8 @@ class CfgVehicles { class GVAR(CheckAmmo) { displayName = CSTRING(checkAmmo); distance = 2.0; - condition = QUOTE([ARR_2(_player, _target)] call FUNC(canCheckAmmo)); - statement = QUOTE([ARR_2(_player, _target)] call FUNC(checkAmmo)); + condition = QUOTE(call FUNC(canCheckAmmo)); + statement = QUOTE(call FUNC(checkAmmo)); exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"}; }; }; diff --git a/addons/reload/XEH_postInit.sqf b/addons/reload/XEH_postInit.sqf index eda5c61faa..3e1b95f9bf 100644 --- a/addons/reload/XEH_postInit.sqf +++ b/addons/reload/XEH_postInit.sqf @@ -13,7 +13,7 @@ if (!hasInterface) exitWith {}; if (!isNull (ACE_controlledUAV param [0, objNull])) exitWith {false}; // Statement - [ACE_player] call FUNC(checkAmmo); + [ACE_player, ACE_player] call FUNC(checkAmmo); true }, {false}, [19, [false, true, false]], false] call CBA_fnc_addKeybind; diff --git a/addons/reload/functions/fnc_canCheckAmmo.sqf b/addons/reload/functions/fnc_canCheckAmmo.sqf index a0aa0c5c70..9632d0b4b1 100644 --- a/addons/reload/functions/fnc_canCheckAmmo.sqf +++ b/addons/reload/functions/fnc_canCheckAmmo.sqf @@ -4,19 +4,18 @@ * Check if the player can check the ammo of the target. * * Arguments: - * 0: Unit - * 1: Target + * 0: Target * * Return Value: - * Can link belt + * Can link belt * * Example: - * [player, bob] call ace_reload_fnc_canCheckAmmo + * [cursorObject] call ace_reload_fnc_canCheckAmmo * * Public: No */ -params ["", "_target"]; +params ["_target"]; // Return true for static weapons if they have been fired once, @todo 1.40 this work-around doesn't work anymore if (_target isKindOf "StaticWeapon") exitWith { diff --git a/addons/reload/functions/fnc_checkAmmo.sqf b/addons/reload/functions/fnc_checkAmmo.sqf index 156ca30a32..8239dfcde7 100644 --- a/addons/reload/functions/fnc_checkAmmo.sqf +++ b/addons/reload/functions/fnc_checkAmmo.sqf @@ -4,39 +4,25 @@ * Count the ammo of the currently loaded magazine or count rifle grenades. Play animation and display message. * * Arguments: - * 0: Player - * 1: Target. Optional, if not suplied the player counts his personal or static weapon ammo + * 0: Target. + * 1: Player * * Return Value: * None * * Example: - * [bob, kevin] call ace_reload_fnc_checkAmmo + * [cursorObject, player] call ace_reload_fnc_checkAmmo * * Public: No */ -#define COUNT_BARS 12 +params ["_target", "_player"]; -params ["_unit"]; - -private _target = vehicle _unit; - -if (count _this > 1) then { - _target = _this select 1; -} else { - - // If the unit is on foot, count it's own ammo - if (_unit == _target) exitWith {}; - - // If it's mounted on a movile weapon, count it's own ammo - if !(_target isKindOf "StaticWeapon") then { - _target = _unit; +if (_player == _target) then { + if ((vehicle _target) isKindOf "StaticWeapon") then { + _target = vehicle _target; }; -}; - -if (_unit == _target) then { [_unit, "Gear", 1] call EFUNC(common,doGesture); }; -[FUNC(displayAmmo), [_target], 1, 0.1] call CBA_fnc_waitAndExecute; +[FUNC(displayAmmo), [_target], 1] call CBA_fnc_waitAndExecute; diff --git a/docs/wiki/feature/crew-served-weapons.md b/docs/wiki/feature/crew-served-weapons.md new file mode 100644 index 0000000000..7175eb6c3d --- /dev/null +++ b/docs/wiki/feature/crew-served-weapons.md @@ -0,0 +1,78 @@ +--- +layout: wiki +title: Crew Served Weapons +description: Static weapons that require multiple people to crew +group: feature +category: equipment +parent: wiki +mod: ace +version: + major: 3 + minor: ? + patch: 0 +--- + +## 1. Overview + +Crew Served Weapons are static weapons that require multiple people to crew them. + +### 1.1 Loading/Unloading of ammo into static weapons + +Static weapons need to be manually loaded with ammo when placed down. The user can also unload ammo from static weapons, and place the ammo into their inventory for transport + +### 1.2 Assembling/Disassembling of static weapons + +Static weapons are assembled when a tripod is placed down, and the weapon mounted ontop. The user can then disassemble the weapon back into the tripod and weapon-bag and carry it around for the next deployment. + +## 2. Usage + +### 2.1 Loading Ammo + +- Apporach the static weapon with the relavent ammo in your inventory +- Interact with the weapon using ⊞ Win (ACE3 default) and navigate to the `CSW` menu. +- Select `Handle Ammo` +- Select `Load X` where X is the ammo you want loaded and wait for the timer to complete + +### 2.2 Unloading ammo + +- Apporach the static weapon and interact ⊞ Win (ACE3 default) +- Navigate to the `CSW` menu +- Select `Unload Ammo` and wait for the timer to complete +- The ammo will be placed to the left of the gun + +### 2.3 Assembling Weapon + +- Have the tripod and the relavent weapon in your launcher slot +- Place down tripod in the self-interact menu Ctrl + ⊞ Win (ACE3 default) +- Approach the tripod with the wanted weapon, and interact ⊞ Win (ACE3 default) +- Navigate to the `CSW` menu, and select `Assemble Weapon` +- Wait for the timer to complete, and the weapon will be assembled in the direction the tripod is facing + +### 2.4 Disassembling Weapon + +- Approach the static weapon and interact ⊞ Win (ACE3 default) +- Navigate to the `CSW` menu +- Select `Disassemble Weapon` +- Wait for the timer to complete +- The tripod, ammo, and weapon will spawn where the static weapon was + +## 3. Addon Options + +### 3.1 defaultAssemblyMode + +- Enables/Disables the ability to assemble the CSW through the addon (Non-Vanilla assembly) +- Default: Off + +### 3.2 handleExtraMagazines + +- Enables/Disables the magazines in the CSW will appear next to the gun on weapon initialization when using defaultAssemblyMode and you have a pre-placed static weapon +- Default: On + +### 3.3 ammoHandling + +- Whether or not you want to handle ammo using the CSW way. Does nothing if using defaultAssemblyMode +- Default: On + +## 4. Dependencies + +{% include dependencies_list.md component="csw" %} diff --git a/docs/wiki/framework/crew-served-weapons-framework.md b/docs/wiki/framework/crew-served-weapons-framework.md new file mode 100644 index 0000000000..a83aa02c6f --- /dev/null +++ b/docs/wiki/framework/crew-served-weapons-framework.md @@ -0,0 +1,142 @@ +--- +layout: wiki +title: Crew Served Weapons Framework +description: Explains how to add new Crew Served Weapons to ACE3 +group: framework +order: 5 +parent: wiki +mod: ace +version: + major: 3 + minor: 13 + patch: 0 +--- + +## 1. Making a new Crew Served Weapon + +### 1.1 CfgVehicles + +```cpp +class CfgVehicles { + class LandVehicle; + class StaticWeapon: LandVehicle { + class ACE_Actions; + }; + class StaticMGWeapon: StaticWeapon { + class Turrets { + class MainTurret; + }; + class ACE_Actions: ACE_Actions { + class ACE_MainActions; + }; + }; + class banana_csw: StaticMGWeapon { + class ace_csw { + enabled = 1; // whether or not the weapon is affected by CSW + proxyWeapon = QGVAR(HMG_Static); // The weapon that will be added to the CSW on initialization. Used to ensure lower ammo-reload time when using Ammo Handling + magazineLocation = "_target selectionPosition 'magazine'"; // The location of the magazine. Where the action for ammo-handling will appear on the weapon + disassembleWeapon = QGVAR(staticHMGCarry); // What the weapon will disassemble to + disassembleTurret = QGVAR(m3TripodLow); // Which tripod will appear when weapon has been disassembled + ammoLoadTime = 7; // How long it takes in seconds to load ammo into the weapon + ammoUnloadTime = 5; // How long it takes in seconds to unload ammo from the weapon + disassembleFunc = "myCoolFunction.sqf"; // A callback function for when the CSW gets disassembled. Arguments: [tripod, staticWeapon] + }; + }; +}; +``` + +### 1.2 CfgMagazines + +```cpp +class CfgMagazines { + class 100Rnd_127x99_mag; // Example magazine used - does not have to be this + class banana_ammo: 100Rnd_127x99_mag { + scope=2; // Needs to be 2 to make sure it shows up in Arsenal + type=256; // Must be 256 to show up in Arsenal + count = 100; // How much ammo gets added per "Load Ammo" selection + model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d"; // default ammo box model + }; +}; +``` + +### 1.3 CfgWeapons + +```cpp +class CfgWeapons { + class ace_csw_base_carry; + class banana_carry_weapon: ace_csw_base_carry { + class ace_csw_options { + assembleTo = "banana_csw"; // What the weapon will assemble into + baseTripod = "banana_tripod"; // The tripod which the weapon can be assembled onto (Default is "ace_csw_m3Tripod") + type = "weapon"; // What type of carry it is. Must always be "weapon" for the carry weapon + }; + }; + + class HMG_Static; + class banana_weapon: HMG_Static { + class ace_csw_options { + deployTime = 10; // Time in seconds it takes to mount the weapon on the tripod + pickupTime = 12; // Time in seconds it takes to dismount the weapon from the tripod + }; + magazines[] = { banana_ammo }; // You must have both the dummy and real ammunition + }; +}; +``` + +### 1.4 CfgMagazineGroups + +```cpp + class ace_csw_groups { // Ammo that can be loaded into this CSW + class banana_ammo { // The magazine which will be loaded into the weapon + banana_dummy_ammo = 1; // Ammo that is loaded into the weapon as per CfgWeapons >> weapon >> magazines + }; + + // Optional + class ace_csw_100Rnd_127x99_mag { // default magazine that CSW already implements + banana_dummy_ammo = 1; + }; + + /* + Ammo types already defined by CSW: + - ace_csw_100Rnd_127x99_mag + - ace_csw_50Rnd_127x108_mag + - ace_csw_20Rnd_20mm_G_belt + - ACE_1Rnd_82mm_Mo_HE + - ACE_1Rnd_82mm_Mo_Smoke + - ACE_1Rnd_82mm_Mo_Illum + - ACE_1Rnd_82mm_Mo_HE_Guided + - ACE_1Rnd_82mm_Mo_HE_LaserGuided + - Titan_AT + - Titan_AA + */ + }; +``` + +## 2. Making a new Tripod + +### 2.1 CfgVehicles + +```cpp +class CfgVehicles { + class ace_csw_baseTripod; + class banana_tripod: ace_csw_baseTripod { + class ace_csw { disassembleTo = "banana_carry_tripod"; }; // What will be spawned when "Pickup Tripod" is selected + }; +}; +``` + +### 2.2 CfgWeapons + +```cpp +class CfgWeapons { + class ace_csw_base_carry; + class banana_carry_tripod: ace_csw_base_carry { + class GVAR(options) { + deployTime = 166; // How much time in seconds it takes to deploy the tripod + pickupTime = 12; // How much time in seconds it takes to pickup the tripod + type = "mount"; // What type of carry it is. Must always be "mount" for the carry tripod + deploy = "banana_tripod"; // What will be deployed when "Deploy Tripod" is selected + }; + }; +}; +``` \ No newline at end of file