readd javelin

This commit is contained in:
Bailey Danyluk 2024-05-27 17:41:53 -06:00
parent 074fc362a7
commit 909a028737
26 changed files with 1191 additions and 0 deletions

View File

@ -0,0 +1 @@
z\ace\addons\javelin

View File

@ -0,0 +1,18 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
clientInit = QUOTE(call COMPILE_SCRIPT(XEH_clientInit));
};
};

View File

@ -0,0 +1,18 @@
class CfgMagazines {
//Static Titan Magazine
class 5Rnd_GAT_missiles;
class 1Rnd_GAT_missiles: 5Rnd_GAT_missiles {
ammo = "ACE_Javelin_FGM148_static"; //from misssileGuidance, was "M_Titan_AT_static"
};
//Handheld Titan "AT" Magazine (Locking - "Anti-Tank")
class Titan_AA;
class Titan_AT: Titan_AA {
ammo = "ACE_Javelin_FGM148"; //from misssileGuidance, was "M_Titan_AT"
};
//Handheld Titan "AP" Magazine (SACLOS? "Anti-personal")
// class Titan_AP: Titan_AA {
//???
// };
};

View File

@ -0,0 +1,13 @@
class CfgSounds {
class ACE_Javelin_Locking {
name = "ACE_Javelin_Locking";
sound[] = {QPATHTOF(data\sounds\javelin_locking.ogg), "db+0", 1.0};
titles[] = {};
};
class ACE_Javelin_Locked {
name = "ACE_Javelin_Locked";
sound[] = {QPATHTOF(data\sounds\javelin_locked.ogg), "db+0", 1.0};
titles[] = {};
};
};

View File

@ -0,0 +1,86 @@
class CfgVehicles {
class LandVehicle;
class StaticWeapon: LandVehicle {
class Turrets;
};
class StaticMGWeapon: StaticWeapon {
class Turrets: Turrets {
class MainTurret;
};
};
class AT_01_base_F: StaticMGWeapon {};
class B_static_AT_F: AT_01_base_F {
class Turrets: Turrets {
class MainTurret: MainTurret {
weapons[] = { QGVAR(Titan_Static) };
magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"};
turretInfoType = "ACE_RscOptics_javelin";
gunnerOpticsModel = QPATHTOF(data\reticle_titan.p3d);
opticsZoomMin = 0.08333;
opticsZoomMax = 0.04167;
opticsZoomInit = 0.08333;
opticsPPEffects[] = {"OpticsCHAbera1","OpticsBlur1"};
opticsFlare = 0;
discretefov[] = {0.08333,0.04167};
discreteInitIndex = 0;
};
};
};
class O_static_AT_F: AT_01_base_F {
class Turrets: Turrets {
class MainTurret: MainTurret {
weapons[] = { QGVAR(Titan_Static) };
magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"};
turretInfoType = "ACE_RscOptics_javelin";
gunnerOpticsModel = QPATHTOF(data\reticle_titan.p3d);
opticsZoomMin = 0.08333;
opticsZoomMax = 0.04167;
opticsZoomInit = 0.08333;
opticsPPEffects[] = {"OpticsCHAbera1","OpticsBlur1"};
opticsFlare = 0;
discretefov[] = {0.08333,0.04167};
discreteInitIndex = 0;
};
};
};
class I_static_AT_F: AT_01_base_F {
class Turrets: Turrets {
class MainTurret: MainTurret {
weapons[] = { QGVAR(Titan_Static) };
magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"};
turretInfoType = "ACE_RscOptics_javelin";
gunnerOpticsModel = QPATHTOF(data\reticle_titan.p3d);
opticsZoomMin = 0.08333;
opticsZoomMax = 0.04167;
opticsZoomInit = 0.08333;
opticsPPEffects[] = {"OpticsCHAbera1","OpticsBlur1"};
opticsFlare = 0;
discretefov[] = {0.08333,0.04167};
discreteInitIndex = 0;
};
};
};
class Car;
class Car_F: Car {
class Turrets {
class MainTurret;
};
};
class LSV_01_base_F: Car_F {
class Turrets: Turrets {};
};
class LSV_01_AT_base_F: LSV_01_base_F { // Prowler / Polaris DAGOR
class Turrets: Turrets {
class TopTurret: MainTurret {
weapons[] = { QGVAR(Titan_Static) };
turretInfoType = "ACE_RscOptics_javelin";
gunnerOpticsModel = QPATHTOF(data\reticle_titan.p3d);
};
};
};
};

View File

@ -0,0 +1,80 @@
class Mode_SemiAuto;
class CfgWeapons {
class MissileLauncher;
class missiles_titan: MissileLauncher {
class Player: MissileLauncher {
EGVAR(missileGuidance,attackProfile) = "JAV_DIR";
};
class TopDown: Player {
EGVAR(missileGuidance,attackProfile) = "JAV_TOP";
};
};
class missiles_titan_static: missiles_titan {};
class GVAR(Titan_Static): missiles_titan_static {
GVAR(enabled) = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
magazines[] = {"1Rnd_GAT_missiles"};
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
class Launcher_Base_F;
class launch_Titan_base: Launcher_Base_F {
class Single: Mode_SemiAuto {
EGVAR(missileGuidance,attackProfile) = "JAV_DIR";
};
class TopDown: Single {
EGVAR(missileGuidance,attackProfile) = "JAV_TOP";
};
};
class launch_Titan_short_base: launch_Titan_base {};
class launch_B_Titan_short_F: launch_Titan_short_base {
GVAR(enabled) = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
class launch_B_Titan_short_tna_F: launch_B_Titan_short_F {
GVAR(enabled) = 1;
};
class launch_I_Titan_short_F: launch_Titan_short_base {
GVAR(enabled) = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
class launch_O_Titan_short_F: launch_Titan_short_base {
GVAR(enabled) = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
class launch_O_Titan_short_ghex_F: launch_O_Titan_short_F {
GVAR(enabled) = 1;
};
class launch_Titan_short_F: launch_Titan_short_base {
GVAR(enabled) = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
};

4
addons/javelin/README.md Normal file
View File

@ -0,0 +1,4 @@
ace_javelin
===============
Adds the Javelin AT launcher.

View File

@ -0,0 +1,423 @@
class RscOpticsValue;
class RscControlsGroupNoScrollbars;
class RscPicture;
class RscLine;
class RscMapControl;
// Taken from AGM for optics management.
class RscInGameUI {
class ACE_RscOptics_javelin {
idd = 300;
controls[] = { QGVAR(elements_group), "ACE_Targeting", QGVAR(mapHelper) };
onLoad = QUOTE(with uiNamespace do {ACE_RscOptics_javelin = _this select 0;};);
class GVAR(mapHelper): RscMapControl {
onDraw = QUOTE(_this call FUNC(mapHelperDraw));
x = -10;
y = -10;
w = 0;
h = 0;
};
class GVAR(elements_group): RscControlsGroupNoScrollbars {
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW";
h = "safeZoneH";
idc = 170;
class Controls {
class CA_Distance: RscOpticsValue {
idc = 151;
sizeEx = "0";
colorText[] = {0,0,0,0};
x = 0;
y = 0;
w = 0;
h = 0;
};
class GVAR(Day_mode_off): RscPicture {
idc = 1001;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (0.03/4)*3*safeZoneH - safeZoneX";
y = "safeZoneY+safeZoneH*0.031 - safeZoneY";
w = "0.1045752* (((safeZoneW*3)/4)/safeZoneW)/(1/safeZoneH)";
h = "safeZoneH*0.1045752";
colorText[] = {0.2941,0.2941,0.2941,1};
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\day_co.paa";
};
class GVAR(Day_mode): GVAR(Day_mode_off) {
idc = 160;
colorText[] = {0.2941,0.8745,0.2157,1};
};
class GVAR(WFOV_mode_off): GVAR(Day_mode_off) {
idc = 1004;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (0.307/4)*3*safeZoneH - safeZoneX";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\wfov_co.paa";
};
class GVAR(WFOV_mode_group): RscControlsGroupNoScrollbars {
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW";
h = "safeZoneH";
idc = 163;
class Controls {
class GVAR(WFOV_mode_on): GVAR(WFOV_mode_off) {
idc = -1;
y = "0.031*SafeZoneH - SafezoneY";
x = "((SafezoneW -SafezoneH*3/4)/2)+ (0.307/4)*3*SafezoneH - SafezoneX";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class StadiaL: RscLine {
x = "0.4899*safeZoneW - safeZoneX";
y = "0.171*safeZoneH - safeZoneY";
w = 0;
h = "0.049*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class StadiaR: RscLine {
x = "0.5109*safeZoneW- safeZoneX";
y = "0.171*safeZoneH - safeZoneY";
w = 0;
h = "0.049*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class BracketL: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.293/4)*3*safeZoneH - safeZoneX";
y = "0.4677*safeZoneH - safeZoneY";
w = 0;
h = "0.0646*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class BracketR: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.70/4)*3*safeZoneH - safeZoneX";
y = "0.4677*safeZoneH - safeZoneY";
w = 0;
h = "0.0646*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class BracketT: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.467/4)*3*safeZoneH - safeZoneX";
y = "0.3535*safeZoneH - safeZoneY";
w = "0.065* (((safeZoneW*3)/4)/safeZoneW)/(1/safeZoneH)";
h = 0;
colorText[] = {0.2941,0.8745,0.2157,1};
};
class BracketB: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.467/4)*3*safeZoneH - safeZoneX";
y = "0.6465*safeZoneH - safeZoneY";
w = "0.065* (((safeZoneW*3)/4)/safeZoneW)/(1/safeZoneH)";
h = 0;
colorText[] = {0.2941,0.8745,0.2157,1};
};
};
};
class GVAR(NFOV_mode_off): GVAR(Day_mode_off) {
idc = 1003;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (0.586/4)*3*safeZoneH - safeZoneX";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\nfov_co.paa";
};
class GVAR(NFOV_mode_group): RscControlsGroupNoScrollbars {
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW-safeZoneX";
h = "safeZoneH-safeZoneY";
idc = 162;
class Controls {
class GVAR(NFOV_mode_on): GVAR(NFOV_mode_off) {
idc = -1;
x = "((SafezoneW -SafezoneH*3/4)/2)+ (0.586/4)*3*SafezoneH - SafezoneX";
y = "0.031*SafeZoneH - SafezoneY";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class StadiaL: RscLine {
x = "0.4788*safeZoneW - safeZoneX";
y = "0.171*safeZoneH - safeZoneY";
w = 0;
h = "0.049*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class StadiaR: RscLine {
x = "0.5212*safeZoneW - safeZoneX";
y = "0.171*safeZoneH - safeZoneY";
w = 0;
h = "0.049*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class LineHL: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.01/4)*3*safeZoneH - safeZoneX";
y = "safeZoneH*0.5 - safeZoneY";
w = "0.29* (((safeZoneW*3)/4)/safeZoneW)/(1/safeZoneH)";
h = "safeZoneH*0.0";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class LineHR: RscLine {
x = "((safeZoneW -safeZoneH*3/4)/2)+ (0.695/4)*3*safeZoneH - safeZoneX";
y = "safeZoneH*0.5 - safeZoneY";
w = "0.29* (((safeZoneW*3)/4)/safeZoneW)/(1/safeZoneH)";
h = "safeZoneH*0.0";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class LineVT: RscLine {
x = "0.5*safeZoneW - safeZoneX";
y = "0.171*safeZoneH - safeZoneY";
w = 0;
h = "0.1825*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class LineVB: RscLine {
x = "0.5*safeZoneW - safeZoneX";
y = "0.6465*safeZoneH - safeZoneY";
w = 0;
h = "0.1895*safeZoneH";
colorText[] = {0.2941,0.8745,0.2157,1};
};
};
};
class GVAR(SEEK_off): GVAR(Day_mode_off) {
idc = 699000;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (0.863/4)*3*safeZoneH - safeZoneX";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\seek_co.paa";
};
class GVAR(SEEK): GVAR(SEEK_off) {
idc = 166;
colorText[] = {0.2941,0.8745,0.2157,0};
};
class GVAR(Missle_off): GVAR(Day_mode_off) {
idc = 1032;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (-0.134/4)*3*safeZoneH - safeZoneX";
y = "(safeZoneY + 0.208*safeZoneH) - safeZoneY";
colorText[] = {0.2941,0.2941,0.2941,1};
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\missle_co.paa";
};
class GVAR(Missle): GVAR(Missle_off) {
idc = 167;
colorText[] = {0.9255,0.5216,0.1216,0};
};
class GVAR(CLU_off): GVAR(Missle_off) {
idc = 1027;
y = "(safeZoneY + 0.436*safeZoneH) - safeZoneY";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\clu_co.paa";
};
class GVAR(HangFire_off): GVAR(Missle_off) {
idc = 1028;
y = "(safeZoneY + 0.669*safeZoneH) - safeZoneY";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\hangfire_co.paa";
};
class GVAR(TOP_off): GVAR(Day_mode_off) {
idc = 699001;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (1.023/4)*3*safeZoneH - safeZoneX";
y = "(safeZoneY + 0.208*safeZoneH) - safeZoneY";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\top_co.paa";
colorText[] = {0.2941,0.8745,0.2157,1};
};
class GVAR(DIR): GVAR(Day_mode) {
idc = 699002;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (1.023/4)*3*safeZoneH - safeZoneX";
y = "(safeZoneY + 0.436*safeZoneH) - safeZoneY";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\dir_co.paa";
colorText[] = {0.2941,0.2941,0.2941,1};
};
class GVAR(FLTR_mode_off): GVAR(Day_mode_off) {
idc = 1002;
x = "(safeZoneX+(safeZoneW -safeZoneH*3/4)/2)+ (1.023/4)*3*safeZoneH - safeZoneX";
y = "(safeZoneY + 0.669*safeZoneH) - safeZoneY";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\fltr_co.paa";
};
class GVAR(FLTR_mode): GVAR(FLTR_mode_off) {
idc = 161;
colorText[] = {0.2941,0.8745,0.2157,1};
};
};
};
class ACE_Targeting: RscControlsGroupNoScrollbars {
idc = 6999;
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW";
h = "safeZoneH";
enabled = 0;
show = 0;
class Controls {
class ACE_TargetingConstrains: RscControlsGroupNoScrollbars {
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW-safeZoneX";
h = "safeZoneH-safeZoneY";
enabled = 0;
class Controls {
class Top: RscPicture {
idc = 699101;
text = "#(argb,8,8,3)color(1,1,1,1)";
colorText[] = {0.2941,0.2941,0.2941,1};
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX";
y = "0.15*safeZoneH-safeZoneY";
w = "(3/4)*safeZoneH";
h = "0.21*safeZoneH";
};
class Bottom: Top {
idc = 699102;
y = "0.64*safeZoneH-safeZoneY";
};
class Left: Top {
idc = 699103;
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX";
y = "0.36*safeZoneH-safeZoneY";
w = "0.31*(3/4)*safeZoneH";
h = "0.28*safeZoneH";
};
class Right: Left {
idc = 699104;
x = "((safeZoneW -(3/4)*safeZoneH)/2)+ 0.69*(3/4)*safeZoneH - safeZoneX";
};
class OpticsBorders: RscPicture {
idc = 699105;
text = QPATHTOF(data\javelin_ui_border_ca.paa);
colorText[] = {0,0,0,1};
x = "((safeZoneW -(3.1/4)*safeZoneH)/2) - safeZoneX";
y = "0.15*safeZoneH-safeZoneY";
w = "(3.1/4)*safeZoneH";
h = "0.7*safeZoneH";
};
};
};
class ACE_TargetingGate: ACE_TargetingConstrains {
idc = 699200;
class Controls {
class TargetingGateTL: ACE_TargetingConstrains {
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX";
y = "0.15*safeZoneH - safeZoneY";
idc = 699201;
class Controls {
class LineH: RscLine {
idc = 699210;
x = "0";
y = "0";
w = "0.025*(3/4)*safeZoneH";
h = "0";
colorText[] = {0.8745,0.8745,0.8745,1};
};
class LineV: LineH {
idc = 699211;
w = "0";
h = "0.025*safeZoneH";
};
};
};
class TargetingGateTR: TargetingGateTL {
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX + 0.975*(3/4)*safeZoneH";
y = "0.15*safeZoneH - safeZoneY";
idc = 699202;
class Controls {
class LineH: RscLine {
idc = 699220;
x = "0";
y = "0";
w = "0.025*(3/4)*safeZoneH";
h = "0";
colorText[] = {0.8745,0.8745,0.8745,1};
};
class LineV: LineH {
idc = 699221;
x = "0.025*(3/4)*safeZoneH";
w = "0";
h = "0.025*safeZoneH";
};
};
};
class TargetingGateBL: TargetingGateTL {
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX";
y = "0.825*safeZoneH - safeZoneY";
idc = 699203;
class Controls {
class LineH: RscLine {
x = "0";
y = "0.025*safeZoneH";
w = "0.025*(3/4)*safeZoneH";
h = "0";
colorText[] = {0.8745,0.8745,0.8745,1};
};
class LineV: LineH {
y = "0";
w = "0";
h = "0.025*safeZoneH";
};
};
};
class TargetingGateBR: TargetingGateBL {
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX + 0.975*(3/4)*safeZoneH";
y = "0.825*safeZoneH - safeZoneY";
idc = 699204;
class Controls {
class LineH: RscLine {
x = "0";
y = "0.025*safeZoneH";
w = "0.025*(3/4)*safeZoneH";
h = "0";
colorText[] = {0.8745,0.8745,0.8745,1};
};
class LineV: LineH {
x = "0.025*(3/4)*safeZoneH";
y = "0";
w = "0";
h = "0.025*safeZoneH";
};
};
};
};
};
class ACE_TargetingLines: ACE_TargetingConstrains {
idc = 699300;
class Controls {
class LineH: RscLine {
idc = 699301;
x = "((safeZoneW -(3/4)*safeZoneH)/2) - safeZoneX";
y = "0.5*safeZoneH - safeZoneY";
w = "(3/4)*safeZoneH";
h = "0";
colorText[] = {0.8745,0.8745,0.8745,1};
};
class LineV: RscLine {
idc = 699302;
x = "0.5*safeZoneW - safeZoneX";
y = "0.15*safeZoneH - safeZoneY";
w = "0";
h = "0.7*safeZoneH";
colorText[] = {0.8745,0.8745,0.8745,1};
};
};
};
};
};
};
};
// on colorText[] = {0.2941, 0.8745, 0.2157, 1.0};
// off colorText[] = {0.2941, 0.2941, 0.2941, 1.0};
// orange colorText[] = {0.9255, 0.5216, 0.1216, 1.0};
/*
ACE_Titan_elements_group: 170
ACE_Titan_Day_mode_off: 1001
ACE_Titan_Day_mode: 160
ACE_Titan_WFOV_mode_off: 1004
ACE_Titan_WFOV_mode_group: 163
ACE_Titan_NFOV_mode_off: 1003
ACE_Titan_NFOV_mode_group: 162
ACE_Titan_SEEK_off: 1005 //1001
ACE_Titan_SEEK: 166
ACE_Titan_Missle_off: 1032
ACE_Titan_Missle: 167
ACE_Titan_CLU_off: 1027
ACE_Titan_HangFire_off: 1028
ACE_Titan_TOP_off: 1006
ACE_Titan_DIR: 1007
ACE_Titan_FLTR_mode_off: 1002
ACE_Titan_FLTR_mode: 161
*/

View File

@ -0,0 +1,5 @@
PREP(getTarget);
PREP(mapHelperDraw);
PREP(onOpticDraw);
PREP(showFireMode);

View File

@ -0,0 +1,6 @@
// #define DEBUG_MODE_FULL
#include "script_component.hpp"
if (!hasInterface) exitWith {};
#include "initKeybinds.inc.sqf"

View File

@ -0,0 +1,36 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
GVAR(isLockKeyDown) = false;
GVAR(pfehID) = -1;
DFUNC(disableFire) = {
params ["_firedEH"];
if (_firedEH < 0 && {difficulty > 0}) then {
_firedEH = [ACE_player, "DefaultAction", {true}, {
private _canFire = (_this select 1) getVariable ["ace_missileguidance_target", nil];
if (!isNil "_canFire") exitWith { false };
true
}] call EFUNC(common,addActionEventHandler);
TRACE_1("Locking Fire Button",_firedEH);
};
_firedEH
};
DFUNC(enableFire) = {
params ["_firedEH"];
if (_firedEH >= 0 && {difficulty > 0}) then {
TRACE_1("Unlocking Fire Button",_firedEH);
[ACE_player, "DefaultAction", _firedEH] call EFUNC(common,removeActionEventHandler);
};
-1
};
ADDON = true;

View File

@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

21
addons/javelin/config.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_main", "ace_common", "ace_missileguidance"};
author = ECSTRING(common,ACETeam);
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgEventhandlers.hpp"
#include "RscInGameUI.hpp"
#include "CfgSounds.hpp"
#include "CfgWeapons.hpp"
#include "CfgVehicles.hpp"
#include "CfgMagazines.hpp"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,80 @@
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Find a target within the optic range
*
* Arguments:
* 0: Last Target (seeds the scan) <OBJECT>
* 1: Max Range (meters) <NUMBER>
*
* Return Value:
* Target <OBJECT>
*
* Example:
* [bob, 5] call ace_javelin_fnc_getTarget
*
* Public: No
*/
params ["_lastTarget", "_maxRange"];
scopeName "main";
private _viewASL = AGLtoASL positionCameraToWorld [0,0,0];
private _viewDir = _viewASL vectorFromTo (AGLtoASL positionCameraToWorld [0,0,1]);
// Attempt to lock onto current target if it is still valid
if (!isNull _lastTarget) then {
private _aimASL = aimPos _lastTarget;
if ((_viewASL vectorDistance _aimASL) > _maxRange) exitWith {};
if ((acos ((_viewASL vectorFromTo _aimASL) vectorDotProduct _viewDir)) > 0.6) exitWith {};
private _relAngle = (_lastTarget getRelDir _viewASL);
for "_xOffset" from -2.5 to 2.5 step 0.5 do {
for "_yOffset" from -2 to 1 step 0.5 do {
// Find test points in the model based on the angle that we are viewing it from (not true 3d projection, but not bad)
private _testPosASL = _lastTarget modelToWorldWorld [_xOffset * - cos _relAngle, _xOffset * sin _relAngle, _yOffset];
private _intersectionsToCursorTarget = lineIntersectsSurfaces [_viewASL, _testPosASL, ace_player, vehicle ace_player, true, 1];
// drawIcon3D ["\A3\ui_f\data\map\markers\military\dot_CA.paa", [[0,1,1,1], [1,0,1,1]] select (count _intersectionsToCursorTarget), (ASLtoAGL _testPosASL), 0.25, 0.25, 0, "", 0.5, 0.025, "TahomaB"];
if (_intersectionsToCursorTarget isNotEqualTo []) then {
(_intersectionsToCursorTarget select 0) params ["", "", "_intersectedObject"];
if (_intersectedObject isKindOf "AllVehicles") then {
_intersectedObject breakOut "main";
};
};
};
};
};
// Try cursorObject/Target as they are very fast
if ((cursorObject isKindOf "AllVehicles") && {(cursorObject distance ace_player) < _maxRange}) then {
private _intersectionsToCursorTarget = lineIntersectsSurfaces [_viewASL, aimPos cursorObject, ace_player, cursorObject, true, 1];
if (_intersectionsToCursorTarget isEqualTo []) then {
cursorObject breakOut "main";
};
};
if ((cursorTarget isKindOf "AllVehicles") && {(cursorObject distance ace_player) < _maxRange}) then {
private _intersectionsToCursorTarget = lineIntersectsSurfaces [_viewASL, aimPos cursorTarget, ace_player, cursorTarget, true, 1];
if (_intersectionsToCursorTarget isEqualTo []) then {
cursorTarget breakOut "main";
};
};
// Attempt to scan using multiple rayscasts - This is expensive (n^2) and care should be given to balance accuracy vs speed
for "_xOffset" from -14 to 14 step 2 do {
for "_yOffset" from -12 to 12 step 4 do {
private _testPosASL = AGLtoASL (positionCameraToWorld [_xOffset, _yOffset, _maxRange]);
private _intersectionsToCursorTarget = lineIntersectsSurfaces [_viewASL, _testPosASL, ace_player, vehicle ace_player, true, 1];
// drawIcon3D ["\A3\ui_f\data\map\markers\military\dot_CA.paa", [[0,1,0,1], [1,0,0,1]] select (count _intersectionsToCursorTarget), (ASLtoAGL _testPosASL), 0.25, 0.25, 0, "", 0.5, 0.025, "TahomaB"];
if (_intersectionsToCursorTarget isNotEqualTo []) then {
(_intersectionsToCursorTarget select 0) params ["", "", "_intersectedObject"];
if (_intersectedObject isKindOf "AllVehicles") then {
_intersectedObject breakOut "main";
};
};
};
};
objNull

View File

@ -0,0 +1,51 @@
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Handles the map helper's draw event
* Resets arguments if not run recently
* And starts a watchdog to detect when weapon display unloaded
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_javelin_fnc_mapHelperDraw
*
* Public: No
*/
if (isNil QGVAR(arguments)) then {
TRACE_1("Starting optic draw",_this);
// reset shooter var:
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
GVAR(arguments) = [
diag_frameno, // Last run frame
objNull, // currentTargetObject
0, // Lock Start Time
0, // Next Sound timer
-1, // _fireDisabledEH
0 // _nextTargetScan
];
// Start up a watchdog for when the display is no longer shown (but might not be unloaded or null)
[{
if (isNull (uiNamespace getVariable ["ACE_RscOptics_javelin", displayNull])) exitWith {true};
GVAR(arguments) params ["_lastRunFrame"];
(diag_frameno < _lastRunFrame) || {diag_frameno > (_lastRunFrame + 1)}
}, {
TRACE_1("old/null display - ending optic draw",_this);
private _fireDisabledEH = GVAR(arguments) param [4, -1];
[_fireDisabledEH] call FUNC(enableFire);
GVAR(arguments) = nil;
}, []] call CBA_fnc_waitUntilAndExecute;
};
BEGIN_COUNTER(onOpticDraw);
GVAR(arguments) call FUNC(onOpticDraw);
END_COUNTER(onOpticDraw);

View File

@ -0,0 +1,202 @@
#include "..\script_component.hpp"
/*
* Author: jaynus, PabstMirror
* Main loop, handles scaning for targets and drawing the javelin optic
*
* Arguments:
* 0: Last run frame <NUMBER>
* 0: Current target (what we locked last run) <OBJECT>
* 0: Lock start time (cba mission time) <NUMBER>
* 0: Next sound play time (ticktime) <NUMBER>
* 0: Next target scan (ticktime) <NUMBER>
*
* Return Value:
* None
*
* Example:
* [] call ace_javelin_fnc_onOpticDraw
*
* Public: No
*/
// TRACE_1("onOpticDraw",diag_frameno);
#define __TRACKINTERVAL 0 // how frequent the ui update should be.
#define __SCANNTERVAL 0.05 // how frequent the target scan check should be.
#define __LOCKONTIME 3 // Lock on won't occur sooner
// Pull the arguments
params ["_lastRunFrame", "_currentTarget", "_lockStartTime", "_soundNextPlayTime", "_fireDisabledEH", "_nextTargetScan"];
// Get shooter info
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
private _currentWeapon = currentWeapon _currentShooter;
private _currentMagazine = currentMagazine _currentShooter;
// Get weapon / ammo configs
private _ammoCount = _currentShooter ammo _currentWeapon;
private _weaponConfig = configProperties [configFile >> "CfgWeapons" >> _currentWeapon, QUOTE(configName _x == QUOTE(QGVAR(enabled))), false];
private _ammoConfig = if (_currentMagazine != "") then {
private _ammoType = getText (configFile >> "CfgMagazines" >> _currentMagazine >> "ammo");
configProperties [(configFile >> "CfgAmmo" >> _ammoType), "(configName _x) == 'ace_missileguidance'", false];
} else {
[]
};
// Check if loaded and javelin enabled for wepaon and missile guidance enabled for loaded ammo
if ((_ammoCount == 0) || // No ammo loaded
{(count _weaponConfig) < 1} || {(getNumber (_weaponConfig select 0)) != 1} || // Not enabled for weapon
{(count _ammoConfig) < 1} || {(getNumber ((_ammoConfig select 0) >> "enabled")) != 1} // Not enabled for ammo
) exitWith {
__JavelinIGUITargeting ctrlShow false;
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
_fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);
_this set [0, diag_frameno];
_this set [4, _fireDisabledEH];
// Fix weapon being in top-attack when loading AP magazine (https://feedback.bistudio.com/T171012)
if ((_currentShooter == ACE_player) && {_currentMagazine == "Titan_AP"} && {currentWeaponMode ACE_player == "TopDown"}) then {
{
_x params ["_xIndex", "", "", "", "_xMode"];
if (_xMode == "Single") exitWith {
ACE_player action ["SwitchWeapon", _currentShooter, ACE_player, _xIndex];
__JavelinIGUITop ctrlSetTextColor __ColorGray;
__JavelinIGUIDir ctrlSetTextColor __ColorGreen;
TRACE_2("fix top-attack for AP",weaponState _currentShooter,_x);
};
} forEach (ACE_player weaponsInfo [_currentWeapon, true]);
};
};
// Bail on fast movement (keep it steady)
if ((velocity ACE_player) distance [0,0,0] > 0.75 && {cameraView == "GUNNER"} && {cameraOn == ACE_player}) exitWith {
TRACE_1("exiting gunner because movement",velocity ACE_player);
ACE_player switchCamera "INTERNAL";
if (player != ACE_player) then {
TRACE_2("Zeus, manually reseting RC after switchCamera",player,ACE_player);
player remoteControl ACE_player;
};
};
// Refresh the firemode (top/dir)
[] call FUNC(showFireMode);
// Get UI constants
private _offsetX = 0.5 * safeZoneW - safeZoneX - 0.5;
private _offsetY = 0.5 * safeZoneH - safeZoneY - 0.5;
private _newTarget = objNull;
if (GVAR(isLockKeyDown) && {cameraView == "GUNNER"} && {((currentVisionMode ACE_player) == 2) || {missionNamespace getVariable [QGVAR(ignoreVisionMode), false]}}) then {
// Attempting to lock; getTarget can be expensive so it's rate is limited
if (diag_tickTime > _nextTargetScan) then {
BEGIN_COUNTER(getTarget);
_newTarget = [_currentTarget, 2500, 0.6] call FUNC(getTarget);
END_COUNTER(getTarget);
_nextTargetScan = diag_tickTime + __SCANNTERVAL;
} else {
_newTarget = _currentTarget;
};
// Show gate box
private _boundsInput = if (_currentTarget isKindOf "CAManBase") then {
[_currentTarget,[-0.5,-0.5,-0.25],[0,0,0]];
} else {
[_currentTarget,[-1,-1,-1],_currentTarget selectionPosition "zamerny"];
};
private _bpos = _boundsInput call EFUNC(common,worldToScreenBounds);
private _lockTime = if (isNull _currentTarget) then {0} else {CBA_missionTime - _lockStartTime};
private _minX = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneW, (_bpos select 0), true]) + _offsetX) max __ConstraintLeft;
private _minY = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneH, (_bpos select 1), true]) + _offsetY) max __ConstraintTop;
private _maxX = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneW, (_bpos select 2), true]) + _offsetX) min __ConstraintRight) - (0.025 * (3 / 4) * safeZoneH);
private _maxY = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneH, (_bpos select 3), true]) + _offsetY) min __ConstraintBottom) - (0.025 * safeZoneH);
// TRACE_3("",_boundsInput,_bpos,_lockTime);
// TRACE_4("",_minX,_maxX,_minY,_maxY);
__JavelinIGUITargetingGateTL ctrlSetPosition [_minX, _minY];
__JavelinIGUITargetingGateTR ctrlSetPosition [_maxX, _minY];
__JavelinIGUITargetingGateBL ctrlSetPosition [_minX, _maxY];
__JavelinIGUITargetingGateBR ctrlSetPosition [_maxX, _maxY];
{_x ctrlCommit __TRACKINTERVAL} forEach [__JavelinIGUITargetingGateTL, __JavelinIGUITargetingGateTR, __JavelinIGUITargetingGateBL, __JavelinIGUITargetingGateBR];
__JavelinIGUITargeting ctrlShow true;
__JavelinIGUITargetingGate ctrlShow true;
} else {
// Not trying to lock
__JavelinIGUITargeting ctrlShow false;
__JavelinIGUITargetingGate ctrlShow false;
__JavelinIGUITargetingLines ctrlShow false;
};
if (isNull _newTarget) then {
// No target found
_currentTarget = objNull;
_lockStartTime = 0;
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
__JavelinIGUITargetingLines ctrlShow false;
// Disallow fire
_fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
} else {
if ((!isNull _newTarget) && {_currentTarget != _newTarget}) then {
TRACE_1("New Target, reseting locking",_newTarget);
_lockStartTime = CBA_missionTime;
_currentTarget = _newTarget;
};
if ((CBA_missionTime - _lockStartTime) > __LOCKONTIME) then { // Lock on after 3 seconds
TRACE_2("LOCKED!",_currentTarget,_lockStartTime);
__JavelinIGUISeek ctrlSetTextColor __ColorGreen;
__JavelinIGUITargetingLines ctrlShow true;
// Move target marker (the crosshair) to aimpoint on the target
private _aimPointOnTarget = _currentTarget selectionPosition (["zamerny", "body"] select (_currentTarget isKindOf "CAManBase"));
(worldToScreen (_currentTarget modelToWorld _aimPointOnTarget)) params [["_aposX", 0.5], ["_aposY", 0.5]];
private _ctrlPos = ctrlPosition __JavelinIGUITargetingLineV;
_ctrlPos set [0, _aposX + _offsetX];
__JavelinIGUITargetingLineV ctrlSetPosition _ctrlPos;
__JavelinIGUITargetingLineV ctrlCommit __TRACKINTERVAL;
_ctrlPos = ctrlPosition __JavelinIGUITargetingLineH;
_ctrlPos set [1, _aposY + _offsetY];
__JavelinIGUITargetingLineH ctrlSetPosition _ctrlPos;
__JavelinIGUITargetingLineH ctrlCommit __TRACKINTERVAL;
_currentShooter setVariable ["ace_missileguidance_target", _currentTarget, false];
// Allow fire
_fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);
if (diag_tickTime > _soundNextPlayTime) then {
playSound "ACE_Javelin_Locked";
_soundNextPlayTime = diag_tickTime + 0.25;
};
} else {
// Lock in progress
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
__JavelinIGUITargetingLines ctrlShow false;
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
if (diag_tickTime > _soundNextPlayTime) then {
playSound "ACE_Javelin_Locking";
_soundNextPlayTime = diag_tickTime + 0.25;
};
// Disallow fire
_fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
};
};
// Save arguments for next run
_this set [0, diag_frameno];
_this set [1, _currentTarget];
_this set [2, _lockStartTime];
_this set [3, _soundNextPlayTime];
_this set [4, _fireDisabledEH];
_this set [5, _nextTargetScan];

View File

@ -0,0 +1,41 @@
#include "..\script_component.hpp"
/*
* Author: jaynus
* Updates fire mode on javelin display (top/dir)
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_javelin_fnc_showFireMode
*
* Public: No
*/
(if (((vehicle ACE_player) == ACE_player) || {ACE_player call CBA_fnc_canUseWeapon}) then {
weaponState ACE_player
} else {
_turretPath = if (ACE_player == (driver _currentShooter)) then {[-1]} else {ACE_player call CBA_fnc_turretPath};
weaponState [vehicle ACE_player, _turretPath]
}) params ["_weapon", "", "_mode"];
private _currentFireMode = getText (configFile >> "CfgWeapons" >> _weapon >> _mode >> QEGVAR(missileGuidance,attackProfile));
TRACE_3("showFireMode",_weapon,_mode,_currentFireMode);
if (_currentFireMode == "") then { // backwards compatiblity for addons using ace_javelin (CUP)
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
_currentFireMode = _currentShooter getVariable ["ace_missileguidance_attackProfile", "JAV_TOP"];
TRACE_1("using getVar",_currentFireMode);
};
if (_currentFireMode == "JAV_TOP") then {
__JavelinIGUITop ctrlSetTextColor __ColorGreen;
__JavelinIGUIDir ctrlSetTextColor __ColorGray;
} else {
__JavelinIGUITop ctrlSetTextColor __ColorGray;
__JavelinIGUIDir ctrlSetTextColor __ColorGreen;
};

View File

@ -0,0 +1,20 @@
// by commy2
["ACE3 Weapons", QGVAR(lockTarget), localize LSTRING(LockTarget),
{
if (GETGVAR(isLockKeyDown,false)) exitWith {false};
GVAR(isLockKeyDown) = true;
TRACE_1("lock key down",GVAR(isLockKeyDown));
// Return false so it doesn't block the rest weapon action
false
},
{
// prevent holding down
GVAR(isLockKeyDown) = false;
TRACE_1("lock key up",GVAR(isLockKeyDown));
false
},
[15, [false, false, false]], false] call CBA_fnc_addKeybind; //Tab Key

View File

@ -0,0 +1,61 @@
#define COMPONENT javelin
#define COMPONENT_BEAUTIFIED Javelin
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_JAVELIN
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_JAVELIN
#define DEBUG_SETTINGS DEBUG_SETTINGS_JAVELIN
#endif
#include "\z\ace\addons\main\script_macros.hpp"
// Javelin IGUI defines
#define __JavelinIGUI (uinamespace getVariable "ACE_RscOptics_javelin")
// Custom controls
#define __JavelinIGUITargeting (__JavelinIGUI displayCtrl 6999)
#define __JavelinIGUISeek (__JavelinIGUI displayCtrl 699000)
#define __JavelinIGUITop (__JavelinIGUI displayCtrl 699001)
#define __JavelinIGUIDir (__JavelinIGUI displayCtrl 699002)
// Constrains
#define __JavelinIGUITargetingConstrains (__JavelinIGUI displayCtrl 699100)
#define __JavelinIGUITargetingConstrainTop (__JavelinIGUI displayCtrl 699101)
#define __JavelinIGUITargetingConstrainBottom (__JavelinIGUI displayCtrl 699102)
#define __JavelinIGUITargetingConstrainLeft (__JavelinIGUI displayCtrl 699103)
#define __JavelinIGUITargetingConstrainRight (__JavelinIGUI displayCtrl 699104)
// Targeting gate
#define __JavelinIGUITargetingGate (__JavelinIGUI displayCtrl 699200)
#define __JavelinIGUITargetingGateTL (__JavelinIGUI displayCtrl 699201)
#define __JavelinIGUITargetingGateTR (__JavelinIGUI displayCtrl 699202)
#define __JavelinIGUITargetingGateBL (__JavelinIGUI displayCtrl 699203)
#define __JavelinIGUITargetingGateBR (__JavelinIGUI displayCtrl 699204)
// Rangefinder
#define __JavelinIGUIRangefinder (__JavelinIGUI displayCtrl 151)
// Targeting lines
#define __JavelinIGUITargetingLines (__JavelinIGUI displayCtrl 699300)
#define __JavelinIGUITargetingLineH (__JavelinIGUI displayCtrl 699301)
#define __JavelinIGUITargetingLineV (__JavelinIGUI displayCtrl 699302)
#define __ConstraintTop (((ctrlPosition __JavelinIGUITargetingConstrainTop) select 1) + ((ctrlPosition (__JavelinIGUITargetingConstrainTop)) select 3))
#define __ConstraintBottom ((ctrlPosition __JavelinIGUITargetingConstrainBottom) select 1)
#define __ConstraintLeft (((ctrlPosition __JavelinIGUITargetingConstrainLeft) select 0) + ((ctrlPosition (__JavelinIGUITargetingConstrainLeft)) select 2))
#define __ConstraintRight ((ctrlPosition __JavelinIGUITargetingConstrainRight) select 0)
// Colors for controls
#define __ColorOrange [0.9255,0.5216,0.1216,1]
#define __ColorGreen [0.2941,0.8745,0.2157,1]
#define __ColorGray [0.2941,0.2941,0.2941,1]
#define __ColorNull [0,0,0,0]

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="Javelin">
<Key ID="STR_ACE_Javelin_LockTarget">
<English>Lock Target (Hold)</English>
<German>Ziel aufschalten (Halten)</German>
<Russian>Захватить цель (удерживать)</Russian>
<Czech>Zamknout cíl (držet)</Czech>
<Polish>Namierz cel (przytrzymaj)</Polish>
<French>Javelin - Verrouiller la cible (maintenir)</French>
<Hungarian>Célpontra állás (Lenyomva tartott)</Hungarian>
<Italian>Aggangia il bersaglio</Italian>
<Spanish>Fijar objetivo (Mantener)</Spanish>
<Portuguese>Travar Alvo (Segurar)</Portuguese>
<Japanese>目標を捕捉 (長押し)</Japanese>
<Korean>표적 획득 (누르기)</Korean>
<Chinesesimp>锁定目标(按住)</Chinesesimp>
<Chinese>鎖定目標 (按住)</Chinese>
<Turkish>Hedefe Kilitlen(Basılı Tut)</Turkish>
</Key>
</Package>
</Project>