diff --git a/A3A/addons/Garage/Public/fn_addVehicle.sqf b/A3A/addons/Garage/Public/fn_addVehicle.sqf index 96f56ce7bc..5261446bf9 100644 --- a/A3A/addons/Garage/Public/fn_addVehicle.sqf +++ b/A3A/addons/Garage/Public/fn_addVehicle.sqf @@ -105,11 +105,9 @@ if ( //here to allow adaption of external antistasi system without needing to addapt code under APL-ND private _broadcastReportedVehsAndStaticsToSave = { publicVariable "staticsToSave"; - publicVariable "reportedVehs"; }; //_this is vehicle private _deleteFromReportedVehsAndStaticsToSave = { - reportedVehs deleteAt (reportedVehs find _this); staticsToSave deleteAt (staticsToSave find _this); }; //_this is vehicle diff --git a/A3A/addons/core/CfgFunctions.hpp b/A3A/addons/core/CfgFunctions.hpp index 0dae2abff2..9124698477 100644 --- a/A3A/addons/core/CfgFunctions.hpp +++ b/A3A/addons/core/CfgFunctions.hpp @@ -7,11 +7,11 @@ class CfgFunctions file = QPATHTOFOLDER(functions\AI); class airbomb {}; class AIreactOnKill {}; - class artillery {}; class artySupport {}; class askHelp {}; class assaultBuilding {}; class attackDrillAI {}; + class attackHeli {}; class autoHealFnc {}; class autoLoot {}; class autoRearm {}; @@ -20,12 +20,13 @@ class CfgFunctions class canFight {}; class captureX {}; class chargeWithSmoke {}; - class chooseSupport {}; class combatLanding {}; class coverage {}; class destroyBuilding {}; class doFlank {}; class enemyList {}; + class enemyGarrison {}; + class enemyReturnToBase {}; class entriesLand {}; class fastrope {}; class findSafeRoadToUnload {}; @@ -47,7 +48,6 @@ class CfgFunctions class napalmDamage {}; class napalmParticles {}; class nearEnemy {}; - class occupantInvaderUnitKilledEH {}; class paradrop {}; class rearmCall {}; class recallGroup {}; @@ -100,17 +100,18 @@ class CfgFunctions file = QPATHTOFOLDER(functions\Base); class addActionBreachVehicle {}; class addAggression {}; + class addEnemyResources {}; class addHC {}; + class addRecentDamage {}; class addTimeForIdle {}; class aggressionUpdateLoop {}; class AILoadInfo {}; class airspaceControl {}; - class rebelAttack {}; class blackout {}; class buildHQ {}; class calculateAggression {}; class canMoveHQ {}; - class chooseAttackType {}; + class chooseAttack {}; class citiesToCivPatrol {}; class citySupportChange {}; class commsMP {}; @@ -122,9 +123,8 @@ class CfgFunctions class destroyCity {}; class distance {}; class distanceUnits {}; - class economicsAI {}; class FIAradio {}; - class findBaseForQRF {}; + class findAttackTargets {} class findBasesForConvoy {}; class findNearestGoodRoad {}; class flagaction {}; @@ -132,9 +132,10 @@ class CfgFunctions class garbageCleaner {}; class garrisonInfo {}; class getAggroLevelString {}; - class getPlayerScale {}; - class getVehiclePoolForAttacks {}; - class getVehiclePoolForQRFs {}; + class getRecentDamage {}; + class getVehiclesAirSupport {}; + class getVehiclesGroundSupport {}; + class getVehiclesGroundTransport {}; class vehicleBoxHeal {}; class initPetros {}; class isFrontline {}; @@ -161,7 +162,6 @@ class CfgFunctions class rebuildAssets {}; class rebuildRadioTower {}; class relocateHQObjects {}; - class remUnitCount {}; class repairRuinedBuilding {}; class resourceCheckSkipTime {}; class resourcesFIA {}; @@ -217,6 +217,9 @@ class CfgFunctions class airportCanAttack {}; class AIVEHinit {}; class ambientCivs {}; + class attackHQ {}; + class availableBasesAir {}; + class availableBasesLand {}; class calculateMarkerArea {}; class cargoSeats {}; class CIVinit {}; @@ -228,6 +231,9 @@ class CfgFunctions class createAIOutposts {}; class createAIResources {}; class createAISite {}; + class createAttackForceAir {}; + class createAttackForceLand {}; + class createAttackForceMixed {}; class createAttackVehicle {}; class createCIV {}; class createFIAOutposts2 {}; @@ -254,7 +260,6 @@ class CfgFunctions class reinforcementsAI {}; class registerUnitType {}; class remoteBattle {}; - class removeVehFromPool {}; class safeVehicleSpawn {}; class singleAttack {}; class spawnGroup {}; @@ -265,7 +270,7 @@ class CfgFunctions class vehAvailable {}; class VEHdespawner {}; class vehKilledOrCaptured {}; - class wavedCA {}; + class wavedAttack {}; class WPCreate {}; }; @@ -299,8 +304,10 @@ class CfgFunctions class EventHandler { file = QPATHTOFOLDER(functions\EventHandler); - class addArtilleryDetectionEH {}; class addArtilleryTrailEH {}; + class enemyUnitDeletedEH {}; + class enemyUnitKilledEH {}; + class vehicleDeletedEH {}; }; class Garrison { @@ -339,6 +346,7 @@ class CfgFunctions //Other initialisation functions (generally called by the above) class briefing {}; class cityinfo {}; + class clientIdleChecker {}; class credits {}; class initACEUnconsciousHandler {}; class initFuncs {}; @@ -423,7 +431,6 @@ class CfgFunctions class AS_Official {}; class AS_specOP {}; class AS_Traitor {}; - class attackHQ {}; class CON_Outpost {}; class convoy {}; class DES_Antenna {}; @@ -477,17 +484,20 @@ class CfgFunctions class Pathfinding { file = QPATHTOFOLDER(functions\Pathfinding); + class addToNavCells {}; + class addNodesNearMarkers {}; class areNodesConnected {}; class calculateH {}; class convoyTest {}; class drawGrid {}; class drawLine {}; class drawPath {}; + class findLandSupportMarkers {}; + class findNavDistance {}; class findNodesInDistance {}; class findPath {}; class findPathPrecheck {}; class findPosOnRoute {}; - class getMainPositions {}; class getMarkerNavPoint {}; class getNearestNavPoint {}; class listInsert {}; @@ -495,7 +505,6 @@ class CfgFunctions class markNode {}; class roadAStar {}; class roadConnPoint {}; - class setNavData {}; class trimPath {}; }; @@ -612,7 +621,7 @@ class CfgFunctions class shortID_create {}; class shortID_format {}; class shortID_init {}; - }; + }; class Supports { file = QPATHTOFOLDER(functions\Supports); @@ -620,14 +629,19 @@ class CfgFunctions class calculateSupportCallReveal {}; class clearTargetArea {}; class createSupport {}; - class endSupport {}; - class initSupportCooldowns {}; - class sendSupport {}; + class getArtilleryRanges {}; + class initSupports {}; + class maxDefenceSpend {}; + class requestArtillery {}; + class requestSupport {}; class showInterceptedSetupCall {}; class showInterceptedSupportCall {}; + class useRadioKey {}; class SUP_airstrike {}; class SUP_airstrikeAvailable {}; class SUP_airstrikeRoutine {}; + class SUP_artillery {}; + class SUP_artilleryAvailable {}; class SUP_ASF {}; class SUP_ASFAvailable {}; class SUP_ASFRoutine {}; @@ -654,13 +668,16 @@ class CfgFunctions class SUP_orbitalStrikeImpactEffects {}; class SUP_orbitalStrikeBeamEffects {}; class SUP_orbitalStrikeRoutine {}; - class SUP_QRF {}; - class SUP_QRFAvailable {}; + class SUP_QRFAir {}; + class SUP_QRFAirAvailable {}; + class SUP_QRFLand {}; + class SUP_QRFLandAvailable {}; class SUP_QRFRoutine {}; class SUP_SAM {}; class SUP_SAMAvailable {}; class SUP_SAMRoutine {}; - class supportAvailable {}; + class SUP_UAV {}; + class SUP_UAVRoutine {}; }; class FunctionsTemplates { diff --git a/A3A/addons/core/Templates/Templates.hpp b/A3A/addons/core/Templates/Templates.hpp index 6e631e4210..4df006ef5f 100644 --- a/A3A/addons/core/Templates/Templates.hpp +++ b/A3A/addons/core/Templates/Templates.hpp @@ -267,6 +267,11 @@ class Templates { Occ = "LDF"; }; + class vt7 + { + Occ = "LDF"; + Inv = "HIDF"; + }; class tem_anizay : kunduz {}; class altis { diff --git a/A3A/addons/core/Templates/Templates/#Examples/FactionExample.sqf b/A3A/addons/core/Templates/Templates/#Examples/FactionExample.sqf index f07f86ffb1..6796bac98e 100644 --- a/A3A/addons/core/Templates/Templates/#Examples/FactionExample.sqf +++ b/A3A/addons/core/Templates/Templates/#Examples/FactionExample.sqf @@ -17,33 +17,36 @@ ["surrenderCrate", "Box_IND_Wps_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type +// vehicles can be placed in more than one category if they fit between both. Cost will be derived by the higher category ["vehiclesBasic", []] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", []] call _fnc_saveToTemplate; -["vehiclesLightArmed",[]] call _fnc_saveToTemplate; +["vehiclesLightArmed", []] call _fnc_saveToTemplate; // Should be armed, unarmoured to lightly armoured, with 0-4 passengers ["vehiclesTrucks", []] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", []] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", []] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", []] call _fnc_saveToTemplate; ["vehiclesMedical", []] call _fnc_saveToTemplate; -["vehiclesAPCs", []] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; // armed, lightly armoured, with 6-8 passengers +["vehiclesAPCs", []] call _fnc_saveToTemplate; // armed with enclosed turret, armoured, with 6-8 passengers +["vehiclesIFVs", []] call _fnc_saveToTemplate; // capable of surviving multiple rockets, cannon armed, with 6-8 passengers ["vehiclesTanks", []] call _fnc_saveToTemplate; -["vehiclesAA", []] call _fnc_saveToTemplate; -["vehiclesLightAPCs", []] call _fnc_saveToTemplate; //this line determines light APCs -["vehiclesIFVs", []] call _fnc_saveToTemplate; //this line determines IFVs +["vehiclesAA", []] call _fnc_saveToTemplate; // ideally heavily armed with anti-ground capability and enclosed turret. Passengers will be ignored ["vehiclesTransportBoats", []] call _fnc_saveToTemplate; ["vehiclesGunBoats", []] call _fnc_saveToTemplate; ["vehiclesAmphibious", []] call _fnc_saveToTemplate; -["vehiclesPlanesCAS", []] call _fnc_saveToTemplate; -["vehiclesPlanesAA", []] call _fnc_saveToTemplate; +["vehiclesPlanesCAS", []] call _fnc_saveToTemplate; // Will be used with CAS script, must be defined in setPlaneLoadout. Needs fixed gun and either rockets or missiles +["vehiclesPlanesAA", []] call _fnc_saveToTemplate; // ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; -["vehiclesHelisLight", []] call _fnc_saveToTemplate; +["vehiclesHelisLight", []] call _fnc_saveToTemplate; // ideally fragile & unarmed helis seating 4+ ["vehiclesHelisTransport", []] call _fnc_saveToTemplate; -["vehiclesHelisAttack", []] call _fnc_saveToTemplate; +// Should be capable of dealing damage to ground targets without additional scripting +["vehiclesHelisLightAttack", []] call _fnc_saveToTemplate; // Utility helis with fixed or door guns + rocket pods +["vehiclesHelisAttack", []] call _fnc_saveToTemplate; // Proper attack helis: Apache, Hind etc ["vehiclesArtillery", []] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray []] call _fnc_saveToTemplate; //element format: [Vehicle class, [Magazines]] diff --git a/A3A/addons/core/Templates/Templates/3CB/3CBBAF_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/3CB/3CBBAF_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..2685b87e66 --- /dev/null +++ b/A3A/addons/core/Templates/Templates/3CB/3CBBAF_Vehicle_Attributes.sqf @@ -0,0 +1,11 @@ +["attributesVehicles", [ + + // Apaches stronk + ["UK3CB_BAF_Apache_AH1_CAS_DDPM_RM", ["cost", 350]], + ["UK3CB_BAF_Apache_AH1_DDPM_RM", ["cost", 350]], + ["UK3CB_BAF_Apache_AH1_CAS_DPMT_RM", ["cost", 350]], + ["UK3CB_BAF_Apache_AH1_DPMT_RM", ["cost", 350]], + ["UK3CB_BAF_Apache_AH1_CAS_DPMW_RM", ["cost", 350]], + ["UK3CB_BAF_Apache_AH1_DPMW_RM", ["cost", 350]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/3CB/3CBFactions_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/3CB/3CBFactions_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..cf9291ac16 --- /dev/null +++ b/A3A/addons/core/Templates/Templates/3CB/3CBFactions_Vehicle_Attributes.sqf @@ -0,0 +1,39 @@ +["attributesVehicles", [ + +/* + ["UK3CB_ADA_I_BMP2", ["cost", 120], ["threat", 150]], + ["UK3CB_ANA_B_BMP2", ["cost", 120], ["threat", 150]], + ["UK3CB_TKA_O_BMP2", ["cost", 120], ["threat", 150]], + ["UK3CB_TKA_O_BMP2K", ["cost", 120], ["threat", 150]], + ["UK3CB_TKA_B_BMP2", ["cost", 120], ["threat", 150]], + ["UK3CB_CW_SOV_O_LATE_BMP2", ["cost", 120], ["threat", 150]], + ["UK3CB_CW_SOV_O_LATE_BMP2K", ["cost", 120], ["threat", 150]], +*/ + + // Strong by light-armed standards + ["UK3CB_AAF_B_M1117", ["cost", 80], ["threat", 100]], + ["UK3CB_ANA_B_M1117", ["cost", 80], ["threat", 100]], + ["UK3CB_TKA_O_GAZ_Vodnik_Cannon", ["cost", 80], ["threat", 100]], + + // Trash planes + ["UK3CB_AAF_B_L39_PYLON", ["cost", 150]], + ["UK3CB_ANA_B_L39_PYLON", ["cost", 150]], + ["UK3CB_KRG_B_L39_PYLON", ["cost", 150]], + ["UK3CB_LDF_B_L39_PYLON", ["cost", 150]], + ["rhs_l159_cdf_b_CDF_CAP", ["cost", 150]], + ["RHSGREF_A29B_HIDF", ["cost", 120]], + ["UK3CB_B_Mystere_HIDF_CAS1", ["cost", 200]], // not many missiles. Gun is actually good though + ["UK3CB_B_Mystere_HIDF_AA1", ["cost", 200]], // no mid-range AA missiles + ["UK3CB_MDF_B_Mystere_AA1", ["cost", 200]] + + // American attack helis with hellfires & chaingun, better than Russian stuff +/* ["UK3CB_AAF_B_AH1Z", ["cost", 300]], + ["UK3CB_CW_US_B_LATE_AH1Z", ["cost", 300]], + ["UK3CB_CW_US_B_LATE_AH1Z_CS", ["cost", 300]], + ["UK3CB_MDF_B_AH1Z_NAVY", ["cost", 300]], + ["UK3CB_MDF_B_AH1Z_CS_NAVY", ["cost", 300]], + ["RHS_AH1Z", ["cost", 300]], + ["RHS_AH1Z_CS", ["cost", 300]] +*/ + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_AAF.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_AAF.sqf index b073893fbe..f8496a3d50 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_AAF.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_AAF.sqf @@ -20,16 +20,18 @@ ["vehiclesBasic", ["UK3CB_AAF_B_M1030"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_AAF_B_M1151", "UK3CB_AAF_B_M998_4DR", "UK3CB_AAF_B_M998_2DR", "UK3CB_AAF_B_LR_Closed", "UK3CB_AAF_B_LR_Open"]] call _fnc_saveToTemplate; ["vehiclesLightArmed", ["UK3CB_AAF_B_M1151_GPK_M2", "UK3CB_AAF_B_M1151_GPK_M240", "UK3CB_AAF_B_M1151_OGPK_M2", "UK3CB_AAF_B_M1151_OGPK_M240", "UK3CB_AAF_B_SUV_Armed", -"UK3CB_AAF_I_LR_SF_M2", "UK3CB_AAF_B_LR_M2"]] call _fnc_saveToTemplate; +"UK3CB_AAF_I_LR_SF_M2", "UK3CB_AAF_B_LR_M2", "UK3CB_AAF_I_GAZ_Vodnik_Cannon"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_AAF_B_M939_Open", "UK3CB_AAF_B_M939", "UK3CB_AAF_B_MTVR_Closed", "UK3CB_AAF_B_MTVR_Open"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_AAF_I_M939_Recovery", "UK3CB_AAF_B_MTVR_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_AAF_B_MTVR_Reammo", "UK3CB_AAF_B_M939_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_AAF_B_M939_Repair", "UK3CB_AAF_B_MTVR_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_AAF_B_MTVR_Refuel", "UK3CB_AAF_B_M939_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_AAF_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_AAF_B_LAV25", "UK3CB_AAF_B_LAV25", "UK3CB_AAF_B_AAV", "UK3CB_AAF_B_LAV25_HQ", "UK3CB_AAF_B_M113_M2", "UK3CB_AAF_B_AAV"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_AAF_B_LAV25_HQ", "UK3CB_AAF_B_M113_M2", "UK3CB_AAF_B_M113_MK19", "UK3CB_AAF_I_GAZ_Vodnik_PKT", "UK3CB_AAF_I_GAZ_Vodnik_KVPT", "UK3CB_AAF_B_M1117"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_AAF_B_LAV25", "UK3CB_AAF_B_LAV25", "UK3CB_AAF_B_AAV","UK3CB_AAF_B_AAV", "UK3CB_AAF_O_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_AAF_B_M60A3", "UK3CB_AAF_I_T72BC", "UK3CB_AAF_B_FV4201", "UK3CB_AAF_B_M1A1"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_AAF_O_ZsuTank", "UK3CB_AAF_O_MTLB_ZU23"]] call _fnc_saveToTemplate; //UK3CB_AAF_O_2S6M_Tunguska +["vehiclesAA", ["UK3CB_AAF_O_ZsuTank"]] call _fnc_saveToTemplate; //UK3CB_AAF_O_2S6M_Tunguska ["vehiclesTransportBoats", ["UK3CB_AAF_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_AAF_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -41,7 +43,8 @@ ["vehiclesHelisLight", ["UK3CB_AAF_B_UH1H", "UK3CB_AAF_B_Benches_MH9", "UK3CB_AAF_B_Bell412_Utility"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_AAF_B_UH60M2", "UK3CB_AAF_B_UH60M", "UK3CB_AAF_O_Mi8AMT", "UK3CB_AAF_O_Mi8", "UK3CB_AAF_I_UH1H_M240"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_AAF_B_AH1Z_GS", "UK3CB_AAF_B_AH1Z", "UK3CB_AAF_B_UH1H_GUNSHIP", "UK3CB_AAF_I_Mi_24V", "UK3CB_AAF_I_Mi8AMTSh", "UK3CB_AAF_B_Bell412_Armed", "UK3CB_AAF_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_AAF_B_UH1H_GUNSHIP", "UK3CB_AAF_I_Mi8AMTSh", "UK3CB_AAF_B_Bell412_Armed", "UK3CB_AAF_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_AAF_B_AH1Z_GS", "UK3CB_AAF_B_AH1Z", "UK3CB_AAF_I_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_AAF_B_M109", "UK3CB_AAF_B_M270_MLRS_HE", "UK3CB_AAF_B_M270_MLRS_CLUSTER"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -72,6 +75,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ADA.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ADA.sqf index 541bb43990..acf702bb43 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ADA.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ADA.sqf @@ -21,17 +21,18 @@ ["vehiclesLightUnarmed", ["UK3CB_ADA_I_SUV_Armoured", "UK3CB_ADA_I_Van_Transport", "UK3CB_ADA_I_Offroad", "UK3CB_ADA_I_LR_Open", "UK3CB_ADA_I_LR_Closed", "UK3CB_ADA_I_Hilux_Open", "UK3CB_ADA_I_Hilux_Closed", "UK3CB_ADA_I_Datsun_Pickup", "UK3CB_ADA_I_BTR40"]] call _fnc_saveToTemplate; ["vehiclesLightArmed", ["UK3CB_ADA_I_LR_SF_M2", "UK3CB_ADA_I_LR_SF_AGS30", "UK3CB_ADA_I_LR_M2", "UK3CB_ADA_I_Hilux_Pkm", -"UK3CB_ADA_I_Hilux_Dshkm", "UK3CB_ADA_I_Datsun_Pickup_PKM", "UK3CB_ADA_I_BRDM2_HQ", "UK3CB_ADA_I_BTR40_MG"]] call _fnc_saveToTemplate; +"UK3CB_ADA_I_Hilux_Dshkm", "UK3CB_ADA_I_Datsun_Pickup_PKM", "UK3CB_ADA_I_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_ADA_I_Ural_Open", "UK3CB_ADA_I_Ural"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_ADA_I_Ural_Recovery", "UK3CB_ADA_I_V3S_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_ADA_I_Ural_Ammo", "UK3CB_ADA_I_V3S_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_ADA_I_Ural_Repair", "UK3CB_ADA_I_V3S_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_ADA_I_Ural_Fuel", "UK3CB_ADA_I_Van_Fuel", "UK3CB_ADA_I_V3S_Refuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_ADA_I_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_ADA_I_BMP1", "UK3CB_ADA_I_BMP2", "UK3CB_ADA_I_BTR60", "UK3CB_ADA_I_BTR70", "UK3CB_ADA_I_BTR80", "UK3CB_ADA_I_BTR80a", -"UK3CB_ADA_I_M113_M2", "UK3CB_ADA_I_M113_MK19"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_ADA_I_M113_M2", "UK3CB_ADA_I_M113_MK19", "UK3CB_ADA_I_BRDM2_HQ", "UK3CB_ADA_O_BRDM2", "UK3CB_ADA_I_BTR40_MG", "UK3CB_ADA_O_MTLB_PKT"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_ADA_I_BMP1", "UK3CB_ADA_I_BMP2", "UK3CB_ADA_I_BTR60", "UK3CB_ADA_I_BTR70", "UK3CB_ADA_I_BTR80", "UK3CB_ADA_I_BTR80a"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_ADA_I_BMP2"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_ADA_I_T72A", "UK3CB_ADA_I_T72B", "UK3CB_ADA_I_T72BM", "UK3CB_ADA_I_T55"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_ADA_I_ZsuTank", "UK3CB_ADA_I_Ural_Zu23"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_ADA_I_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_TKA_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -41,9 +42,10 @@ ["vehiclesPlanesAA", ["UK3CB_ADA_I_L39_PYLON"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_ADA_I_C130J"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_ADA_I_UH1H", "UK3CB_ADA_I_UH1H_M240"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_ADA_I_UH1H", "UK3CB_ADA_I_UH1H_M240", "UK3CB_ADA_I_Mi8AMT", "UK3CB_ADA_I_Mi8"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_ADA_I_UH1H_GUNSHIP", "UK3CB_ADA_I_Mi8AMTSh", "UK3CB_ADA_I_Mi_24P", "UK3CB_ADA_I_Mi_24V"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_ADA_I_UH1H"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_ADA_I_UH1H_M240", "UK3CB_ADA_I_Mi8AMT", "UK3CB_ADA_I_Mi8"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_ADA_I_UH1H_GUNSHIP", "UK3CB_ADA_I_Mi8AMTSh"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_ADA_I_Mi_24P", "UK3CB_ADA_I_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_ADA_I_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +73,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ANA.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ANA.sqf index d9d0ed30c9..fb39d40da4 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ANA.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_ANA.sqf @@ -20,17 +20,18 @@ ["vehiclesBasic", ["UK3CB_ADA_I_Quadbike"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_ANA_B_M1152", "UK3CB_ANA_B_M998_2DR", "UK3CB_ANA_B_M998_4DR", "UK3CB_ANA_B_Offroad", "UK3CB_ANA_B_Hilux_Open", "UK3CB_ANA_B_Hilux_Closed"]] call _fnc_saveToTemplate; ["vehiclesLightArmed", ["UK3CB_ANA_B_Hilux_Dshkm", "UK3CB_ANA_B_Hilux_Pkm", "UK3CB_ANA_B_Hilux_Spg9", "UK3CB_ANA_B_M1025_M2", "UK3CB_ANA_B_M1025_MK19", "UK3CB_ANA_B_M1151_GPK_M2", -"UK3CB_ANA_B_M1151_GPK_M240", "UK3CB_ANA_B_M1151_OGPK_M2", "UK3CB_ANA_B_M1151_OGPK_M240"]] call _fnc_saveToTemplate; +"UK3CB_ANA_B_M1151_GPK_M240", "UK3CB_ANA_B_M1151_OGPK_M2", "UK3CB_ANA_B_M1151_OGPK_M240", "UK3CB_ANA_B_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_ANA_B_Ural", "UK3CB_ANA_B_Ural_Open"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_ANA_B_Ural_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_ANA_B_Ural_Ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_ANA_B_Ural_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_ANA_B_Ural_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_ANA_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_ANA_B_BMP1", "UK3CB_ANA_B_BMP2", "UK3CB_ANA_B_M1117", -"UK3CB_ANA_B_M113_M2", "UK3CB_ANA_B_M113_MK19"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_ANA_B_M113_M2", "UK3CB_ANA_B_M113_MK19", "UK3CB_ANA_B_M113_M240", "UK3CB_ANA_B_MaxxPro_MK19", "UK3CB_ANA_B_MaxxPro_M2", "UK3CB_ANA_B_M1117"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_ANA_B_BMP1", "UK3CB_ANA_B_BMP2"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_ANA_B_BMP2"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_ANA_B_T72BM", "UK3CB_ANA_B_T72B", "UK3CB_ANA_B_T72A", "UK3CB_ANA_B_T55", "UK3CB_ANA_B_T72A"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_ANA_B_ZsuTank", "UK3CB_ANA_B_Ural_Zu23"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_ANA_B_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_TKA_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -42,7 +43,8 @@ ["vehiclesHelisLight", ["UK3CB_ANA_B_UH1H", "UK3CB_ANA_B_Benches_MH9"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_ANA_B_B_UH60M2", "UK3CB_ANA_B_B_UH60M", "UK3CB_ANA_B_Mi8AMT", "UK3CB_ANA_B_Mi8", "UK3CB_ANA_B_UH1H_M240"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_ANA_B_Mi_24P","UK3CB_ANA_B_Mi_24V","UK3CB_ANA_B_Mi8AMTSh","UK3CB_ANA_B_UH1H_GUNSHIP"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_ANA_B_Mi8AMTSh", "UK3CB_ANA_B_UH1H_GUNSHIP"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_ANA_B_Mi_24P", "UK3CB_ANA_B_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_ANA_B_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -70,6 +72,8 @@ ["minefieldAT", ["rhs_mine_tm62m"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhs_mine_pmn2"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arctic.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arctic.sqf index 69b086c315..c7ff41ce7f 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arctic.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arctic.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["UK3CB_BAF_MAN_HX60_Repair_Green_DPMT", "UK3CB_BAF_MAN_HX58_Repair_Green_DPMT"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_BAF_MAN_HX60_Fuel_Green_DPMT", "UK3CB_BAF_MAN_HX58_Fuel_Green_DPMT"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_BAF_LandRover_Amb_FFR_Green_A_DPMT"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMT", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMT", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_BAF_Coyote_Passenger_L134A1_W_DPMT", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMT", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMT"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMT", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMT", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_wd","rhsusf_m1a1aimwd_usarmy","rhsusf_m1a1aim_tuski_wd","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -38,9 +40,10 @@ ["vehiclesPlanesAA", ["rhsusf_f22"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_BAF_Hercules_C3_DDPM", "UK3CB_BAF_Hercules_C4_DDPM"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_BAF_Merlin_HC3_CSAR_DDPM_RM"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DDPM_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DDPM_RM", "UK3CB_BAF_Chinook_HC1_DDPM"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DDPM_RM", "UK3CB_BAF_Apache_AH1_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_6A_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DDPM_RM"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_BAF_Merlin_HC3_CSAR_DDPM_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DDPM_RM", "UK3CB_BAF_Chinook_HC1_DDPM"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_BAF_Wildcat_AH1_CAS_6A_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DDPM_RM", "UK3CB_BAF_Apache_AH1_DDPM_RM"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -69,6 +72,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBBAF_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arid.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arid.sqf index 40bd0d29d8..0dcc11a472 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Arid.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["UK3CB_BAF_MAN_HX60_Repair_Sand_DDPM", "UK3CB_BAF_MAN_HX58_Repair_Sand_DDPM"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_BAF_MAN_HX60_Fuel_Sand_DDPM", "UK3CB_BAF_MAN_HX58_Fuel_Sand_DDPM"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_BAF_LandRover_Amb_FFR_Sand_A_DDPM"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Sand_DDPM", "UK3CB_BAF_FV432_Mk3_RWS_Sand_DDPM", "UK3CB_BAF_Warrior_A3_D_MTP", "UK3CB_BAF_Warrior_A3_D_Camo_MTP", "UK3CB_BAF_Warrior_A3_D_Cage_MTP", "UK3CB_BAF_Warrior_A3_D_Cage_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_BAF_Coyote_Passenger_L134A1_D_DDPM", "UK3CB_BAF_Coyote_Passenger_L111A1_D_DDPM", "UK3CB_BAF_Coyote_Passenger_L111A1_D_DDPM"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Sand_DDPM", "UK3CB_BAF_FV432_Mk3_RWS_Sand_DDPM", "UK3CB_BAF_Warrior_A3_D_MTP", "UK3CB_BAF_Warrior_A3_D_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_BAF_Warrior_A3_D_MTP", "UK3CB_BAF_Warrior_A3_D_Camo_MTP", "UK3CB_BAF_Warrior_A3_D_Cage_MTP", "UK3CB_BAF_Warrior_A3_D_Cage_Camo_MTP"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_d","rhsusf_m1a1aimd_usarmy","rhsusf_m1a1aim_tuski_d","rhsusf_m1a2sep1d_usarmy","rhsusf_m1a2sep1tuskiid_usarmy","rhsusf_m1a2sep2d_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6"]] call _fnc_saveToTemplate; @@ -38,9 +40,10 @@ ["vehiclesPlanesAA", ["rhsusf_f22"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_BAF_Hercules_C3_DDPM", "UK3CB_BAF_Hercules_C4_DDPM"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_BAF_Merlin_HC3_CSAR_DDPM_RM"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DDPM_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DDPM_RM", "UK3CB_BAF_Chinook_HC1_DDPM"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DDPM_RM", "UK3CB_BAF_Apache_AH1_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_6A_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DDPM_RM"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_BAF_Merlin_HC3_CSAR_DDPM_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DDPM_RM", "UK3CB_BAF_Chinook_HC1_DDPM"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_BAF_Wildcat_AH1_CAS_6A_DDPM_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DDPM_RM", "UK3CB_BAF_Apache_AH1_DDPM_RM"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109d_usarmy"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -69,6 +72,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBBAF_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Temperate.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Temperate.sqf index 7a5afe9d16..fc21f179b3 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Temperate.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["UK3CB_BAF_MAN_HX60_Repair_Green_DPMT", "UK3CB_BAF_MAN_HX58_Repair_Green_DPMT"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_BAF_MAN_HX60_Fuel_Green_DPMT", "UK3CB_BAF_MAN_HX58_Fuel_Green_DPMT"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_BAF_LandRover_Amb_FFR_Green_A_DPMT"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMT", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMT", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_BAF_Coyote_Passenger_L134A1_W_DPMT", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMT", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMT"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMT", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMT", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_wd","rhsusf_m1a1aimwd_usarmy","rhsusf_m1a1aim_tuski_wd","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -38,9 +40,10 @@ ["vehiclesPlanesAA", ["rhsusf_f22"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_BAF_Hercules_C3_DPMT", "UK3CB_BAF_Hercules_C4_DPMT"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_BAF_Merlin_HC3_CSAR_DPMT_RM"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DPMT_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DPMT_RM", "UK3CB_BAF_Chinook_HC1_DPMT"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DPMT_RM", "UK3CB_BAF_Apache_AH1_DPMT_RM", "UK3CB_BAF_Wildcat_AH1_CAS_6A_DPMT_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DPMT_RM"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_BAF_Merlin_HC3_CSAR_DPMT_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DPMT_RM", "UK3CB_BAF_Chinook_HC1_DPMT"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_BAF_Wildcat_AH1_CAS_6A_DPMT_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DPMT_RM", "UK3CB_BAF_Apache_AH1_DPMT_RM"]] call _fnc_saveToTemplate; ["vehiclesArtillery", [ "rhsusf_m109_usarmy"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -69,6 +72,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBBAF_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Tropical.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Tropical.sqf index 739a5781df..fb9d926436 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Tropical.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_BAF_Tropical.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["UK3CB_BAF_MAN_HX60_Repair_Green_DPMW", "UK3CB_BAF_MAN_HX58_Repair_Green_DPMW"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_BAF_MAN_HX60_Fuel_Green_DPMW", "UK3CB_BAF_MAN_HX58_Fuel_Green_DPMW"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_BAF_LandRover_Amb_FFR_Green_A_DPMW"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMW", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMW", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_BAF_Coyote_Passenger_L134A1_W_DPMW", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMW", "UK3CB_BAF_Coyote_Passenger_L111A1_W_DPMW"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_BAF_FV432_Mk3_GPMG_Green_DPMW", "UK3CB_BAF_FV432_Mk3_RWS_Green_DPMW", "UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_BAF_Warrior_A3_W_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_MTP", "UK3CB_BAF_Warrior_A3_W_Cage_Camo_MTP", "UK3CB_BAF_Warrior_A3_W_Camo_MTP"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_wd","rhsusf_m1a1aimwd_usarmy","rhsusf_m1a1aim_tuski_wd","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -38,9 +40,10 @@ ["vehiclesPlanesAA", ["rhsusf_f22"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_BAF_Hercules_C3_DPMW", "UK3CB_BAF_Hercules_C4_DPMW"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_BAF_Merlin_HC3_CSAR_DPMW_RM"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DPMW_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DPMW_RM", "UK3CB_BAF_Chinook_HC1_DPMW"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DPMW_RM", "UK3CB_BAF_Apache_AH1_DPMW_RM", "UK3CB_BAF_Wildcat_AH1_CAS_6A_DPMW_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_BAF_Wildcat_AH1_TRN_8A_DPMW_RM"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_BAF_Merlin_HC3_CSAR_DPMW_RM", "UK3CB_BAF_Merlin_HC3_18_GPMG_DPMW_RM", "UK3CB_BAF_Chinook_HC1_DPMW"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_BAF_Wildcat_AH1_CAS_6A_DPMW_RM", "UK3CB_BAF_Wildcat_AH1_CAS_8A"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_BAF_Apache_AH1_CAS_DPMW_RM", "UK3CB_BAF_Apache_AH1_DPMW_RM"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -69,6 +72,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBBAF_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_SOV.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_SOV.sqf index 1512414b08..8c2b097349 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_SOV.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_SOV.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_CW_SOV_O_LATE_BTR40", "UK3CB_CW_SOV_O_LATE_BRDM2_UM", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_Open", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_Closed"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["UK3CB_CW_SOV_O_LATE_BTR40_MG", "UK3CB_CW_SOV_O_LATE_BRDM2", "UK3CB_CW_SOV_O_LATE_BRDM2_ATGM", "UK3CB_CW_SOV_O_LATE_BRDM2_HQ", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_SPG9", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_MG", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_AGS30"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["UK3CB_CW_SOV_O_LATE_VDV_UAZ_SPG9", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_MG", "UK3CB_CW_SOV_O_LATE_VDV_UAZ_AGS30", "UK3CB_CW_SOV_O_LATE_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_CW_SOV_O_LATE_Zil131_Open", "UK3CB_CW_SOV_O_LATE_VDV_Ural_Open", "UK3CB_CW_SOV_O_LATE_VDV_Ural", "UK3CB_CW_SOV_O_LATE_VDV_Kraz255_Open", "UK3CB_CW_SOV_O_LATE_VDV_Gaz66_Open_Flatbed", "UK3CB_CW_SOV_O_LATE_VDV_Gaz66_Covered_Flatbed"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_CW_SOV_O_LATE_Zil131_Flatbed", "UK3CB_CW_SOV_O_LATE_VDV_Ural_Recovery", "UK3CB_CW_SOV_O_LATE_VDV_Kraz255_Flatbed"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_CW_SOV_O_LATE_Ural_Ammo", "UK3CB_CW_SOV_O_LATE_Gaz66_Ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_CW_SOV_O_LATE_Gaz66_Repair", "UK3CB_CW_SOV_O_LATE_Ural_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_CW_SOV_O_LATE_Kraz255_Fuel", "UK3CB_CW_SOV_O_LATE_Ural_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_CW_SOV_O_LATE_Gaz66_Med"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_CW_SOV_O_LATE_BMD1", "UK3CB_CW_SOV_O_LATE_BMD1K", "UK3CB_CW_SOV_O_LATE_BMD1P", "UK3CB_CW_SOV_O_LATE_BMD1PK", "UK3CB_CW_SOV_O_LATE_BMD2", "UK3CB_CW_SOV_O_LATE_BMP1", "UK3CB_CW_SOV_O_LATE_BMP2", "UK3CB_CW_SOV_O_LATE_BMP2K", "UK3CB_CW_SOV_O_LATE_BRM1K", "UK3CB_CW_SOV_O_LATE_BTR60", "UK3CB_CW_SOV_O_LATE_BTR70", "UK3CB_CW_SOV_O_LATE_BTR80", "UK3CB_CW_SOV_O_LATE_BTR80a"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_CW_SOV_O_LATE_BRDM2", "UK3CB_CW_SOV_O_LATE_BRDM2_ATGM", "UK3CB_CW_SOV_O_LATE_BRDM2_HQ", "UK3CB_CW_SOV_O_LATE_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_CW_SOV_O_LATE_BMD1", "UK3CB_CW_SOV_O_LATE_BMD1K", "UK3CB_CW_SOV_O_LATE_BMD1P", "UK3CB_CW_SOV_O_LATE_BMD1PK", "UK3CB_CW_SOV_O_LATE_BMD2", "UK3CB_CW_SOV_O_LATE_BMP1", "UK3CB_CW_SOV_O_LATE_BMP2", "UK3CB_CW_SOV_O_LATE_BMP2K", "UK3CB_CW_SOV_O_LATE_BRM1K", "UK3CB_CW_SOV_O_LATE_BTR60", "UK3CB_CW_SOV_O_LATE_BTR70", "UK3CB_CW_SOV_O_LATE_BTR80", "UK3CB_CW_SOV_O_LATE_BTR80a", "UK3CB_CW_SOV_O_LATE_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_CW_SOV_O_LATE_BMP2", "UK3CB_CW_SOV_O_LATE_BMP2K"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_CW_SOV_O_LATE_T80A", "UK3CB_CW_SOV_O_LATE_T80", "UK3CB_CW_SOV_O_LATE_T80U", "UK3CB_CW_SOV_O_LATE_T80BVK", "UK3CB_CW_SOV_O_LATE_T72BE", "UK3CB_CW_SOV_O_LATE_T72BC", "UK3CB_CW_SOV_O_LATE_T72BB", "UK3CB_CW_SOV_O_LATE_T72A", "UK3CB_CW_SOV_O_LATE_T72B", "UK3CB_CW_SOV_O_LATE_T55"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_CW_SOV_O_LATE_ZsuTank", "UK3CB_CW_SOV_O_LATE_MTLB_ZU23", "UK3CB_CW_SOV_O_LATE_Ural_Zu23"]] call _fnc_saveToTemplate; //UK3CB_CW_SOV_O_LATE_2S6M_Tunguska +["vehiclesAA", ["UK3CB_CW_SOV_O_LATE_ZsuTank"]] call _fnc_saveToTemplate; //UK3CB_CW_SOV_O_LATE_2S6M_Tunguska ["vehiclesTransportBoats", ["O_G_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_CHD_O_Fishing_Boat_DSHKM"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["UK3CB_CW_SOV_O_LATE_Mi8AMT"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_CW_SOV_O_LATE_Mi8"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_CW_SOV_O_LATE_Mi8AMTSh", "UK3CB_CW_SOV_O_LATE_Mi_24V", "UK3CB_CW_SOV_O_LATE_Mi_24P"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_CW_SOV_O_LATE_Mi8AMTSh"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_CW_SOV_O_LATE_Mi_24V", "UK3CB_CW_SOV_O_LATE_Mi_24P"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_CW_SOV_O_LATE_2S1", "UK3CB_CW_SOV_O_LATE_2S3", "UK3CB_CW_SOV_O_LATE_BM21"]] call _fnc_saveToTemplate; //this line determines artillery vehicles -- Example: ["vehiclesArtillery", ["B_MBT_01_arty_F"]] -- Array, can contain multiple assets ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhs_mine_tm62m"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhs_mine_pmn2"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_US.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_US.sqf index f4af3b8ea3..07b351c5ad 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_US.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_CW_US.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_CW_US_B_LATE_M151_Jeep_Closed", "UK3CB_CW_US_B_LATE_M151_Jeep_Open", "UK3CB_CW_US_B_LATE_M1025_Unarmed", "UK3CB_CW_US_B_LATE_M998_4DR", "UK3CB_CW_US_B_LATE_M998_2DR"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["UK3CB_CW_US_B_LATE_M1025_M2", "UK3CB_CW_US_B_LATE_M1025_MK19", "UK3CB_CW_US_B_LATE_M1025_TOW", "UK3CB_CW_US_B_LATE_M151_Jeep_TOW"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["UK3CB_CW_US_B_LATE_M1025_M2", "UK3CB_CW_US_B_LATE_M1025_M2", "UK3CB_CW_US_B_LATE_M1025_MK19", "UK3CB_CW_US_B_LATE_M1025_TOW", "UK3CB_CW_US_B_LATE_M151_Jeep_HMG"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_CW_US_B_LATE_M939", "UK3CB_CW_US_B_LATE_M939_Guntruck", "UK3CB_CW_US_B_LATE_M939_Open"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_CW_US_B_LATE_M939_Recovery", "UK3CB_CW_US_B_LATE_M977A4_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_CW_US_B_LATE_M939_Reammo", "UK3CB_CW_US_B_LATE_M977A4_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_CW_US_B_LATE_M939_Repair", "UK3CB_CW_US_B_LATE_M977A4_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_CW_US_B_LATE_M939_Fuel", "UK3CB_CW_US_B_LATE_M978A4_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_CW_US_B_LATE_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_CW_US_B_LATE_M2A2", "UK3CB_CW_US_B_LATE_M113_MK19", "UK3CB_CW_US_B_LATE_M113_M240", "UK3CB_CW_US_B_LATE_M113_M2", "UK3CB_CW_US_B_LATE_LAV25_HQ", "UK3CB_CW_US_B_LATE_LAV25", "UK3CB_CW_US_B_LATE_AAV"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_CW_US_B_LATE_M113_MK19", "UK3CB_CW_US_B_LATE_M113_M240", "UK3CB_CW_US_B_LATE_M113_M2", "UK3CB_CW_US_B_LATE_LAV25_HQ"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_CW_US_B_LATE_M2A2", "UK3CB_CW_US_B_LATE_LAV25", "UK3CB_CW_US_B_LATE_AAV"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_CW_US_B_LATE_M2A2"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_CW_US_B_EARLY_M1A1", "UK3CB_CW_US_B_EARLY_M60a3", "UK3CB_CW_US_B_EARLY_M60a1"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ ["vehiclesPlanesTransport", ["UK3CB_CW_US_B_EARLY_C130J"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["UK3CB_CW_US_B_EARLY_UH1H"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_CW_US_B_EARLY_CH47", "UK3CB_CW_US_B_EARLY_UH1H_M240", "UK3CB_CW_US_B_LATE_UH60M2", "UK3CB_CW_US_B_LATE_UH60M", "UK3CB_CW_US_B_LATE_UH1H"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_CW_US_B_EARLY_UH1H_GUNSHIP", "UK3CB_CW_US_B_EARLY_AH1Z", "UK3CB_CW_US_B_EARLY_AH1Z_CS", "UK3CB_CW_US_B_EARLY_AH1Z_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_CW_US_B_EARLY_CH47", "UK3CB_CW_US_B_EARLY_UH1H_M240", "UK3CB_CW_US_B_LATE_UH60M2", "UK3CB_CW_US_B_LATE_UH60M"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_CW_US_B_EARLY_UH1H_GUNSHIP"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_CW_US_B_EARLY_AH1Z", "UK3CB_CW_US_B_EARLY_AH1Z_CS", "UK3CB_CW_US_B_EARLY_AH1Z_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_CW_US_B_EARLY_M109", "RHS_M119_WD", "UK3CB_CW_US_B_LATE_M270_MLRS_HE", "UK3CB_CW_US_B_LATE_M270_MLRS_CLUSTER"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -72,6 +75,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_HIDF.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_HIDF.sqf index 80fb1d1928..e2eacc9fe3 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_HIDF.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_HIDF.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["UK3CB_B_M939_Repair_HIDF", "UK3CB_B_MTVR_Repair_HIDF"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_B_MTVR_Refuel_HIDF", "UK3CB_B_M939_Refuel_HIDF"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_CW_US_B_EARLY_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsgref_hidf_m113a3_m2", "rhsgref_hidf_m113a3_m2", "rhsgref_hidf_m113a3_mk19", "UK3CB_B_LAV25_HIDF", "UK3CB_B_LAV25_HIDF", "UK3CB_B_LAV25_HQ_HIDF", "UK3CB_B_AAV_HIDF", "UK3CB_B_AAV_HIDF"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsgref_hidf_m113a3_m2", "rhsgref_hidf_m113a3_m2", "rhsgref_hidf_m113a3_mk19", "UK3CB_B_MaxxPro_M2_US_W", "UK3CB_B_MaxxPro_MK19_US_W", "UK3CB_B_LAV25_HQ_HIDF"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_B_LAV25_HIDF", "UK3CB_B_LAV25_HIDF", "UK3CB_B_AAV_HIDF", "UK3CB_B_AAV_HIDF"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_B_M60A3_HIDF", "UK3CB_B_M60A1_HIDF", "UK3CB_CW_US_B_EARLY_M1A1"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -34,13 +36,14 @@ ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; ["vehiclesAmphibious", ["UK3CB_B_LAV25_HIDF", "UK3CB_B_AAV_HIDF"]] call _fnc_saveToTemplate; -["vehiclesPlanesCAS", ["RHSGREF_A29B_HIDF"]] call _fnc_saveToTemplate; +["vehiclesPlanesCAS", ["UK3CB_B_Mystere_HIDF_CAS1"]] call _fnc_saveToTemplate; // "RHSGREF_A29B_HIDF" -> needs laser activation ["vehiclesPlanesAA", ["UK3CB_B_Mystere_HIDF_AA1"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["RHS_C130J"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["rhs_uh1h_hidf_unarmed", "UK3CB_B_Bell412_Utility_HIDF"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["rhs_uh1h_hidf", "UK3CB_B_Bell412_Utility_HIDF"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["rhs_uh1h_hidf_gunship", "UK3CB_B_Bell412_Armed_HIDF", "UK3CB_B_Bell412_Armed_AT_HIDF"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["rhs_uh1h_hidf_gunship", "UK3CB_B_Bell412_Armed_HIDF", "UK3CB_B_Bell412_Armed_AT_HIDF"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_CW_US_B_EARLY_AH1Z", "UK3CB_CW_US_B_EARLY_AH1Z_CS", "UK3CB_CW_US_B_EARLY_AH1Z_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_CW_US_B_EARLY_M109"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -70,6 +73,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_KRG.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_KRG.sqf index 9654dfae58..8418fb98e0 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_KRG.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_KRG.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["UK3CB_KRG_B_Quadbike"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_KRG_B_M270_Transport", "UK3CB_KRG_B_BTR40", "UK3CB_KRG_B_M1025_Unarmed", "UK3CB_KRG_B_M998_2DR", "UK3CB_KRG_B_M998_4DR", "UK3CB_KRG_B_Pickup"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["UK3CB_KRG_B_Pickup_M2", "UK3CB_KRG_B_Pickup_DSHKM", "UK3CB_KRG_B_M1025_TOW", "UK3CB_KRG_B_M1025_M2", "UK3CB_KRG_B_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["UK3CB_KRG_B_Pickup_M2", "UK3CB_KRG_B_Pickup_DSHKM", "UK3CB_KRG_B_M1025_TOW", "UK3CB_KRG_B_M1025_M2", "UK3CB_KRG_B_M939_ZU23", "UK3CB_KRG_B_MTVR_ZU23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_KRG_B_M939_Closed", "UK3CB_KRG_B_M939_Guntruck", "UK3CB_KRG_B_M939_Open", "UK3CB_KRG_B_MTVR_Closed"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_KRG_B_M939_Recovery", "UK3CB_KRG_B_MTVR_Recovery", "UK3CB_KRG_B_M270_Carrier"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_KRG_B_M939_Reammo", "UK3CB_KRG_B_MTVR_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_KRG_B_M939_Repair", "UK3CB_KRG_B_MTVR_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_KRG_B_MTVR_Refuel", "UK3CB_KRG_B_M939_Refuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_LDF_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_KRG_B_M2A2", "UK3CB_KRG_B_BTR60", "UK3CB_KRG_B_M113tank_M2_90"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_KRG_B_M113tank_M2_90", "UK3CB_KRG_B_M113tank_M2_90", "UK3CB_KRG_B_MTLB_PKT", "UK3CB_KRG_B_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_KRG_B_M2A2", "UK3CB_KRG_B_BTR60", "UK3CB_KRG_B_BTR60", "UK3CB_KRG_B_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_KRG_B_M2A2"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_KRG_B_FV4201", "UK3CB_KRG_B_M60A3", "UK3CB_KRG_B_M60A1"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_KRG_B_M939_ZU23", "UK3CB_KRG_B_MTLB_ZU23", "UK3CB_KRG_B_MTVR_ZU23", "UK3CB_KRG_B_M270_Avenger", "UK3CB_KRG_B_ZsuTank"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_KRG_B_M270_Avenger", "UK3CB_KRG_B_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_MDF_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_MDF_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["UK3CB_KRG_B_Bell412_Utility", "UK3CB_KRG_B_UH1H"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_KRG_B_UH1H_M240"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_KRG_B_Bell412_Armed", "UK3CB_KRG_B_Bell412_Armed_AT", "UK3CB_KRG_B_UH1H_GUNSHIP"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_KRG_B_Bell412_Armed", "UK3CB_KRG_B_Bell412_Armed_AT", "UK3CB_KRG_B_UH1H_GUNSHIP"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", []] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_KRG_B_M109", "UK3CB_KRG_B_M270_MLRS_Cluster", "UK3CB_KRG_B_M270_MLRS_HE", "UK3CB_KRG_B_M939_MLRS", "UK3CB_KRG_B_MTVR_MLRS", "UK3CB_KRG_B_M119"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -75,6 +78,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_LDF.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_LDF.sqf index 6b2237878d..a29da2e448 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_LDF.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_LDF.sqf @@ -18,17 +18,19 @@ ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; ["vehiclesBasic", ["UK3CB_LDF_B_Quadbike"]] call _fnc_saveToTemplate; -["vehiclesLightUnarmed", ["UK3CB_LDF_B_BRDM2_UM", "UK3CB_LDF_B_M1025", "UK3CB_LDF_B_M1152", "UK3CB_LDF_B_M998_2DR", "UK3CB_LDF_B_M998_4DR", "UK3CB_LDF_B_Offroad", "UK3CB_LDF_B_SUV_Armoured"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["UK3CB_LDF_B_BRDM2", "UK3CB_LDF_B_BRDM2_ATGM", "UK3CB_LDF_B_BRDM2_HQ", "UK3CB_LDF_B_Tigr_STS", "UK3CB_LDF_B_Tigr", "UK3CB_LDF_B_M1025_M2", "UK3CB_LDF_B_M1025_TOW", "UK3CB_LDF_B_M1151_GPK_M2", "UK3CB_LDF_B_M1151_GPK_PKM", "UK3CB_LDF_B_M1151_OGPK_M2", "UK3CB_LDF_B_Offroad_M2", "UK3CB_LDF_B_SUV_Armed"]] call _fnc_saveToTemplate; +["vehiclesLightUnarmed", ["UK3CB_LDF_B_BRDM2_UM", "UK3CB_LDF_B_M1025", "UK3CB_LDF_B_M1152", "UK3CB_LDF_B_M998_2DR", "UK3CB_LDF_B_M998_4DR", "UK3CB_LDF_B_Offroad", "UK3CB_LDF_B_SUV_Armoured", "UK3CB_LDF_B_Tigr"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["UK3CB_LDF_B_Tigr_STS", "UK3CB_LDF_B_M1025_M2", "UK3CB_LDF_B_M1025_TOW", "UK3CB_LDF_B_M1151_GPK_M2", "UK3CB_LDF_B_M1151_GPK_PKM", "UK3CB_LDF_B_M1151_OGPK_M2", "UK3CB_LDF_B_Offroad_M2", "UK3CB_LDF_B_SUV_Armed", "UK3CB_LDF_B_T810_ZU23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_LDF_B_T810_Closed", "UK3CB_LDF_B_T810_Open", "UK3CB_LDF_B_T810_Closed_PKM", "UK3CB_LDF_B_T810_Open_PKM"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_LDF_B_T810_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_LDF_B_T810_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_LDF_B_T810_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_LDF_B_T810_Refuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_LDF_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_LDF_B_BMP1", "UK3CB_LDF_B_BMP2", "UK3CB_LDF_B_BMP2K", "UK3CB_LDF_B_Marshall", "UK3CB_LDF_B_Marshall_Cage"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_LDF_B_BRDM2", "UK3CB_LDF_B_BRDM2_ATGM", "UK3CB_LDF_B_BRDM2_HQ", "UK3CB_B_MaxxPro_M2_US_W", "UK3CB_B_MaxxPro_MK19_US_W", "UK3CB_LDF_B_MTLB_PKT"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_LDF_B_BMP1", "UK3CB_LDF_B_BMP2", "UK3CB_LDF_B_BMP2K", "UK3CB_LDF_B_Marshall", "UK3CB_LDF_B_Marshall_Camo", "UK3CB_LDF_B_Marshall_Cage", "UK3CB_LDF_B_Marshall_Cage_Camo", "UK3CB_LDF_B_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_LDF_B_BMP2", "UK3CB_LDF_B_BMP2K"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_LDF_B_Leopard", "UK3CB_LDF_B_Leopard_Cage", "UK3CB_LDF_B_T72BB", "UK3CB_LDF_B_T72A"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_LDF_B_T810_ZU23", "UK3CB_LDF_B_MTLB_ZU23", "UK3CB_LDF_B_ZsuTank"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_LDF_B_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_MDF_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_MDF_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["UK3CB_LDF_B_Mi8", "UK3CB_LFR_B_Bell412_FLIR"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_LDF_B_Mi8AMT"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_LDF_B_Mi_24P", "UK3CB_LDF_B_Mi_24V", "UK3CB_LDF_B_Mi8AMTSh"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_LDF_B_Mi8AMTSh"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_LDF_B_Mi_24P", "UK3CB_LDF_B_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_LDF_B_2S1", "UK3CB_LDF_B_RM70", "UK3CB_LDF_B_RM70_MG", "UK3CB_LDF_B_T810_MLRS"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -73,6 +76,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_MDF.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_MDF.sqf index 7972fa0d13..203411bd65 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_MDF.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_MDF.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["UK3CB_MDF_B_Quadbike"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_MDF_B_M1151", "UK3CB_MDF_B_M998_2DR", "UK3CB_MDF_B_M998_4DR"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["UK3CB_MDF_B_M1025_M2", "UK3CB_MDF_B_M1025_TOW", "UK3CB_MDF_B_M1151_GPK_M2", "UK3CB_MDF_B_M1151_GPK_M240", "UK3CB_MDF_B_M1151_GPK_MK19", "UK3CB_MDF_B_M1151_OGPK_M2", "UK3CB_MDF_B_M1151_OGPK_M240", "UK3CB_MDF_B_Offroad_HMG"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["UK3CB_MDF_B_M1025_M2", "UK3CB_MDF_B_M1025_TOW", "UK3CB_MDF_B_M1151_GPK_M2", "UK3CB_MDF_B_M1151_GPK_M240", "UK3CB_MDF_B_M1151_GPK_MK19", "UK3CB_MDF_B_M1151_OGPK_M2", "UK3CB_MDF_B_M1151_OGPK_M240", "UK3CB_MDF_B_Offroad_HMG", "UK3CB_MDF_B_LSV_02_Armed"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_MDF_B_MTVR_Closed", "UK3CB_MDF_B_MTVR_Open"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_MDF_B_MTVR_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_MDF_B_MTVR_Reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_MDF_B_MTVR_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_MDF_B_MTVR_Refuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_MDF_B_M113_Medical"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_MDF_B_Warrior", "UK3CB_MDF_B_Warrior_Cage", "UK3CB_MDF_B_Warrior_Cage_Camo", "UK3CB_MDF_B_Warrior_Camo", "UK3CB_MDF_B_M113_M2", "UK3CB_MDF_B_M113_M240", "UK3CB_MDF_B_M113_MK19"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_MDF_B_M113_M2", "UK3CB_MDF_B_M113_M240", "UK3CB_MDF_B_M113_MK19"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_MDF_B_Warrior", "UK3CB_MDF_B_Warrior_Cage", "UK3CB_MDF_B_Warrior_Camo"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_MDF_B_Warrior_Cage"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_MDF_B_M60A3"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["UK3CB_MDF_B_UH1H", "UK3CB_MDF_B_Bell412_Utility"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_MDF_B_UH1H_M240", "UK3CB_MDF_B_Bell412_Utility"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_MDF_B_AH1Z_NAVY", "UK3CB_MDF_B_AH1Z_CS_NAVY", "UK3CB_MDF_B_AH1Z_GS_NAVY", "UK3CB_MDF_B_UH1H_GUNSHIP", "UK3CB_MDF_B_UH1H_GUNSHIP_NAVY", "UK3CB_MDF_B_UH1H_GUNSHIP_NAVY", "UK3CB_MDF_B_Bell412_Armed_NAVY", "UK3CB_MDF_B_Bell412_Armed_AT_NAVY"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_MDF_B_UH1H_GUNSHIP", "UK3CB_MDF_B_UH1H_GUNSHIP_NAVY", "UK3CB_MDF_B_Bell412_Armed_NAVY", "UK3CB_MDF_B_Bell412_Armed_AT_NAVY"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_MDF_B_AH1Z_NAVY", "UK3CB_MDF_B_AH1Z_CS_NAVY", "UK3CB_MDF_B_AH1Z_GS_NAVY"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_CW_US_B_EARLY_M109"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -70,6 +73,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_East.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_East.sqf index 363fe4535b..aa4f0a94a9 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_East.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_East.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_TKA_O_SUV_Armoured", "UK3CB_TKA_O_Tigr_FFV", "UK3CB_TKA_O_BRDM2_UM", "UK3CB_TKA_O_UAZ_Closed", "UK3CB_TKA_O_UAZ_Open", "UK3CB_TKA_O_BTR40"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["UK3CB_TKA_O_SUV_Armed", "UK3CB_TKA_O_LR_SF_M2", "UK3CB_TKA_O_Hilux_Dshkm", "UK3CB_TKA_O_Hilux_GMG", "UK3CB_TKA_O_GAZ_Vodnik_PKT", "UK3CB_TKA_O_BTR40_MG", "UK3CB_TKA_O_Tigr_STS", "UK3CB_TKA_O_BRDM2_HQ", "UK3CB_TKA_O_BRDM2"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["UK3CB_TKA_O_Hilux_Dshkm", "UK3CB_TKA_O_Hilux_GMG", "UK3CB_TKA_O_LR_SF_M2", "UK3CB_TKA_O_LR_SF_M2", "UK3CB_TKA_O_GAZ_Vodnik_Cannon", "UK3CB_TKA_O_Tigr_STS", "UK3CB_TKA_B_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_TKA_B_Ural_Open", "UK3CB_TKA_B_Ural"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_TKA_B_Ural_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_TKA_B_Ural_Ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_TKA_B_Ural_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_TKA_B_Ural_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_TKA_O_GAZ_Vodnik_MedEvac"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_TKA_O_BMP1", "UK3CB_TKA_O_BMP2", "UK3CB_TKA_O_BMP2K", "UK3CB_TKA_O_BTR60", "UK3CB_TKA_O_BTR70", "UK3CB_TKA_O_BTR80", "UK3CB_TKA_O_BTR80a"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_TKA_O_BRDM2_HQ", "UK3CB_TKA_O_BRDM2", "UK3CB_TKA_O_GAZ_Vodnik_PKT", "UK3CB_TKA_O_GAZ_Vodnik_KVPT", "UK3CB_TKA_O_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_TKA_O_BMP1", "UK3CB_TKA_O_BMP2", "UK3CB_TKA_O_BMP2K", "UK3CB_TKA_O_BTR60", "UK3CB_TKA_O_BTR70", "UK3CB_TKA_O_BTR80", "UK3CB_TKA_O_BTR80a", "UK3CB_TKA_O_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_TKA_O_BMP2", "UK3CB_TKA_O_BMP2K"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_TKA_B_T72BM", "UK3CB_TKA_B_T72A", "UK3CB_TKA_B_T72B", "UK3CB_TKA_B_T55"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_TKA_B_ZsuTank", "UK3CB_TKA_B_Ural_Zu23", "UK3CB_TKA_O_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_TKA_B_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_TKA_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -38,9 +40,10 @@ ["vehiclesPlanesAA", ["UK3CB_TKA_O_MIG29SM", "UK3CB_TKA_B_MIG21_AA"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_TKA_B_C130J"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_TKA_B_UH1H", "UK3CB_TKA_B_UH1H_M240"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_TKA_B_Mi8AMT", "UK3CB_TKA_B_Mi8"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_TKA_O_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh", "UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_TKA_B_UH1H"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_TKA_B_UH1H_M240", "UK3CB_TKA_B_Mi8AMT", "UK3CB_TKA_B_Mi8"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_TKA_O_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_TKA_B_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -51,7 +54,7 @@ ["uavsPortable", ["B_UAV_01_F"]] call _fnc_saveToTemplate; //Config special vehicles -["vehiclesMilitiaLightArmed", ["UK3CB_TKA_O_UAZ_MG", "UK3CB_TKA_O_Hilux_Dshkm", "UK3CB_TKA_O_UAZ_SPG9"]] call _fnc_saveToTemplate; +["vehiclesMilitiaLightArmed", ["UK3CB_TKA_O_Hilux_Dshkm", "UK3CB_TKA_O_Hilux_Dshkm", "UK3CB_TKA_O_SUV_Armed"]] call _fnc_saveToTemplate; // Armed UAZs have bridge problems ["vehiclesMilitiaTrucks", ["UK3CB_TKM_O_V3S_Open", "UK3CB_TKM_O_V3S_Closed"]] call _fnc_saveToTemplate; ["vehiclesMilitiaCars", ["UK3CB_TKM_O_Hilux_Open", "UK3CB_TKM_O_UAZ_Open", "UK3CB_TKM_O_UAZ_Closed", "UK3CB_TKM_O_LR_Open"]] call _fnc_saveToTemplate; @@ -70,6 +73,8 @@ ["minefieldAT", ["rhs_mine_tm62m"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhs_mine_pmn2"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_Mix.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_Mix.sqf index f0d2f20294..d103123130 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_Mix.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_Mix.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_TKA_B_Hilux_Closed", "UK3CB_TKA_O_SUV_Armoured", "UK3CB_TKA_B_Hilux_Open", "UK3CB_TKA_B_M1025", "UK3CB_TKA_B_M998_2DR", "rhsusf_m1151_usarmy_d", "UK3CB_TKA_O_BTR40"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["UK3CB_TKA_B_Hilux_Pkm", "UK3CB_TKA_O_SUV_Armed", "UK3CB_TKA_B_Hilux_Dshkm", "UK3CB_TKA_B_M1025_M2", "UK3CB_TKA_B_M1025_MK19", "UK3CB_TKA_B_Hilux_GMG", "rhsusf_m1151_m2_v1_usarmy_d", "rhsusf_m1151_m240_v1_usarmy_d", "rhsusf_m1151_mk19_v1_usarmy_d", "UK3CB_TKA_B_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["UK3CB_TKA_B_Hilux_Pkm", "UK3CB_TKA_O_SUV_Armed", "UK3CB_TKA_B_Hilux_Dshkm", "UK3CB_TKA_B_M1025_M2", "UK3CB_TKA_B_M1025_MK19", "UK3CB_TKA_B_Hilux_GMG", "rhsusf_m1151_m2_v1_usarmy_d", "rhsusf_m1151_m240_v1_usarmy_d", "rhsusf_m1151_mk19_v1_usarmy_d", "UK3CB_TKA_B_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_TKA_B_Ural_Open", "UK3CB_TKA_B_Ural", "rhsusf_M1078A1P2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_TKA_B_Ural_Recovery", "rhsusf_M977A4_usarmy_d", "rhsusf_M1084A1P2_B_D_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_TKA_B_Ural_Ammo", "rhsusf_M977A4_AMMO_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_TKA_B_Ural_Repair", "rhsusf_M977A4_REPAIR_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_TKA_B_Ural_Fuel", "rhsusf_M978A4_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_TKA_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_TKA_B_M113_M240", "UK3CB_TKA_B_M113_M2", "UK3CB_TKA_B_M113_MK19", "UK3CB_TKA_B_M1117", "UK3CB_TKA_B_BTR60", "UK3CB_TKA_B_BMP1", "UK3CB_TKA_B_BMP2", "UK3CB_TKA_B_MTLB_PKT", "UK3CB_TKA_B_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_TKA_B_M113_M240", "UK3CB_TKA_B_M113_M2", "UK3CB_TKA_B_M113_MK19", "UK3CB_TKA_B_MTLB_PKT", "UK3CB_TKA_B_M1117", "UK3CB_TKA_B_BTR40_MG"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["UK3CB_TKA_B_BTR60", "UK3CB_TKA_B_BTR60", "UK3CB_TKA_B_BMP1", "UK3CB_TKA_B_BMP2", "UK3CB_TKA_B_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["UK3CB_TKA_B_BMP2"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_TKA_B_T72A", "UK3CB_TKA_B_T72B", "UK3CB_TKA_B_T72BM", "UK3CB_TKA_B_T55", "rhsusf_m1a1aimd_usarmy"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_TKA_B_ZsuTank", "RHS_M6", "UK3CB_TKA_B_Ural_Zu23", "UK3CB_TKA_B_MTLB_ZU23"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_TKA_B_ZsuTank", "RHS_M6"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_TKA_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["UK3CB_TKA_B_UH1H", "UK3CB_TKA_B_UH1H_M240", "UK3CB_TKA_B_Bell412_Utility"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["UK3CB_TKA_B_Mi8AMT", "UK3CB_TKA_B_Mi8", "UK3CB_TKA_B_Bell412_Utility"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_TKA_O_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh", "UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V", "RHS_AH1Z", "RHS_AH1Z_CS", "RHS_AH1Z_GS", "UK3CB_TKA_B_Bell412_Armed", "UK3CB_TKA_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_TKA_O_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh", "UK3CB_TKA_B_Bell412_Armed", "UK3CB_TKA_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V", "RHS_AH1Z", "RHS_AH1Z_CS", "RHS_AH1Z_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy", "UK3CB_TKA_B_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_West.sqf b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_West.sqf index a340ab2033..23a03c0b4b 100644 --- a/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_West.sqf +++ b/A3A/addons/core/Templates/Templates/3CB/3CB_AI_TKA_West.sqf @@ -20,16 +20,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["UK3CB_TKA_B_Hilux_Closed", "UK3CB_TKA_B_Hilux_Open", "UK3CB_TKA_B_M1025", "UK3CB_TKA_B_M998_2DR", "UK3CB_TKA_B_SUV_Armoured"]] call _fnc_saveToTemplate; ["vehiclesLightArmed", ["UK3CB_TKA_B_Hilux_Pkm", "UK3CB_TKA_B_Hilux_Dshkm", "UK3CB_TKA_B_M1025_M2", "UK3CB_TKA_B_M1025_MK19", -"UK3CB_TKA_B_MaxxPro_M2", "UK3CB_TKA_B_MaxxPro_MK19", "UK3CB_TKA_B_Hilux_GMG", "UK3CB_TKA_B_SUV_Armed"]] call _fnc_saveToTemplate; +"UK3CB_TKA_B_Hilux_GMG", "UK3CB_TKA_B_SUV_Armed", "UK3CB_TKA_B_Ural_Zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["UK3CB_TKA_B_Ural_Open", "UK3CB_TKA_B_Ural", "UK3CB_TKA_B_Kamaz_Open", "UK3CB_TKA_B_Kamaz_Closed"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["UK3CB_TKA_B_Ural_Recovery"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["UK3CB_TKA_B_Ural_Ammo", "UK3CB_TKA_B_Kamaz_Ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["UK3CB_TKA_B_Ural_Repair", "UK3CB_TKA_B_Kamaz_Repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["UK3CB_TKA_B_Kamaz_Fuel", "UK3CB_TKA_B_Ural_Fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["UK3CB_TKA_B_M113_AMB"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["UK3CB_TKA_B_M113_M240", "UK3CB_TKA_B_M113_M2", "UK3CB_TKA_B_M113_MK19", "UK3CB_TKA_B_M1117"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["UK3CB_TKA_B_M113_M240", "UK3CB_TKA_B_M113_M2", "UK3CB_TKA_B_M113_MK19", "UK3CB_TKA_B_M1117", "UK3CB_TKA_B_MaxxPro_M2", "UK3CB_TKA_B_MaxxPro_MK19"]] call _fnc_saveToTemplate; +["vehiclesAPCs", []] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["UK3CB_TKA_B_T72A", "UK3CB_TKA_B_T72B", "UK3CB_TKA_B_T72BM", "UK3CB_TKA_B_T55"]] call _fnc_saveToTemplate; -["vehiclesAA", ["UK3CB_TKA_B_ZsuTank", "UK3CB_TKA_B_Ural_Zu23"]] call _fnc_saveToTemplate; +["vehiclesAA", ["UK3CB_TKA_B_ZsuTank"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UK3CB_TKA_B_RHIB"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UK3CB_TKA_B_RHIB_Gunboat"]] call _fnc_saveToTemplate; @@ -39,9 +41,10 @@ ["vehiclesPlanesAA", ["UK3CB_TKA_B_L39_PYLON", "UK3CB_TKA_B_MIG21_AA"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["UK3CB_TKA_B_C130J"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["UK3CB_TKA_B_UH1H", "UK3CB_TKA_B_UH1H_M240", "UK3CB_TKA_B_Bell412_Utility"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["UK3CB_TKA_B_UH1H", "UK3CB_TKA_B_UH1H_M240", "UK3CB_TKA_B_Bell412_Utility", "UK3CB_TKA_B_Mi8AMT", "UK3CB_TKA_B_Mi8"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UK3CB_TKA_B_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh", "UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V", "UK3CB_TKA_B_Bell412_Armed", "UK3CB_TKA_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["UK3CB_TKA_B_UH1H", "UK3CB_TKA_B_Bell412_Utility"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["UK3CB_TKA_B_UH1H_M240", "UK3CB_TKA_B_Bell412_Utility", "UK3CB_TKA_B_Mi8AMT", "UK3CB_TKA_B_Mi8"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["UK3CB_TKA_B_UH1H_GUNSHIP", "UK3CB_TKA_B_Mi8AMTSh", "UK3CB_TKA_B_Bell412_Armed", "UK3CB_TKA_B_Bell412_Armed_AT"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["UK3CB_TKA_B_Mi_24P", "UK3CB_TKA_B_Mi_24V"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["UK3CB_TKA_B_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -70,6 +73,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "3CBFactions_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Arid.sqf index 1cad0ba5fd..564007e780 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Arid.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["CUP_B_T810_Repair_CZ_DES"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_T810_Refuel_CZ_DES"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_LR_Ambulance_CZ_D", "CUP_B_BMP2_AMB_CZ_Des"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_BRDM2_CZ_Des", "CUP_B_BRDM2_HQ_CZ_Des", "CUP_B_BMP2_CZ_Des"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_BRDM2_CZ_Des", "CUP_B_BRDM2_CZ_Des", "CUP_B_BRDM2_HQ_CZ_Des"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_BMP2_CZ_Des"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_T72_CZ"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_nM1097_AVENGER_USA_DES"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_B_Mi171Sh_Unarmed_ACR"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_B_Mi171Sh_Unarmed_ACR"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_Mi171Sh_ACR"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_Mi35_Dynamic_CZ", "CUP_B_Mi35_Dynamic_CZ_Des"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_RM70_CZ"]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Temperate.sqf index e96d37fa6c..e047355e44 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ACR_Temperate.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["CUP_B_T810_Repair_CZ_WDL"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_T810_Refuel_CZ_WDL"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_LR_Ambulance_CZ_W", "CUP_B_BMP2_AMB_CZ"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_BRDM2_HQ_CZ", "CUP_B_BRDM2_CZ", "CUP_B_BMP2_CZ"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_BRDM2_HQ_CZ", "CUP_B_BRDM2_CZ", "CUP_B_BRDM2_CZ"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_BMP2_CZ"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_T72_CZ"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_nM1097_AVENGER_USA_WDL"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_B_Mi171Sh_Unarmed_ACR"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_B_Mi171Sh_Unarmed_ACR"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_Mi171Sh_ACR"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_Mi35_Dynamic_CZ", "CUP_B_Mi35_Dynamic_CZ_Dark"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_RM70_CZ"]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arctic.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arctic.sqf index 1a535c20bb..450adbf5d5 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arctic.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arctic.sqf @@ -18,15 +18,17 @@ ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["vehiclesBasic", ["O_Quadbike_01_F"]] call _fnc_saveToTemplate; -["vehiclesLightUnarmed", ["CUP_O_UAZ_Open_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU"]] call _fnc_saveToTemplate; +["vehiclesLightUnarmed", ["CUP_O_UAZ_Open_RU"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_O_Kamaz_Open_RU", "CUP_O_Ural_Open_RU"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_O_Kamaz_Reammo_RU", "CUP_O_Ural_Reammo_RU"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_O_Ural_Repair_RU", "CUP_O_Kamaz_Repair_RU"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_O_Kamaz_Refuel_RU", "CUP_O_Ural_Refuel_RU"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_O_UAZ_AMB_RU", "CUP_O_BMP2_AMB_RU", "CUP_O_GAZ_Vodnik_MedEvac_RU"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_BTR60_Winter_RU", "CUP_O_BTR80_WINTER_RU", "CUP_O_BTR80A_WINTER_RU", "CUP_O_BTR90_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU", "CUP_O_MTLB_pk_Winter_RU"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU", "CUP_O_MTLB_pk_Winter_RU"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BMP2_RU", "CUP_O_BTR60_Winter_RU", "CUP_O_BTR80_WINTER_RU", "CUP_O_BTR80A_WINTER_RU", "CUP_O_BTR90_RU"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_O_T72_RU", "CUP_O_T90_RU"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_O_ZSU23_SLA"]] call _fnc_saveToTemplate; @@ -36,11 +38,12 @@ ["vehiclesPlanesCAS", ["CUP_O_Su25_Dyn_RU"]] call _fnc_saveToTemplate; ["vehiclesPlanesAA", ["CUP_O_SU34_RU"]] call _fnc_saveToTemplate; -["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; +["vehiclesPlanesTransport", ["CUP_O_MI6T_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["CUP_O_Mi8AMT_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["CUP_O_Mi8_medevac_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_O_Mi8AMT_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_DL_RU", "CUP_O_Ka52_RU", "CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_RU", "CUP_O_Ka52_RU"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_O_BM21_RU"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_O_BM21_RU", ["CUP_40Rnd_GRAD_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arid.sqf index e0b04cfe75..8f7a3a2a29 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Arid.sqf @@ -18,15 +18,17 @@ ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["vehiclesBasic", ["O_Quadbike_01_F"]] call _fnc_saveToTemplate; -["vehiclesLightUnarmed", ["CUP_O_UAZ_Open_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU"]] call _fnc_saveToTemplate; +["vehiclesLightUnarmed", ["CUP_O_UAZ_Open_RU"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_O_Kamaz_Open_RU", "CUP_O_Ural_Open_RU"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_O_Kamaz_Reammo_RU", "CUP_O_Ural_Reammo_RU"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_O_Ural_Repair_RU", "CUP_O_Kamaz_Repair_RU"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_O_Kamaz_Refuel_RU", "CUP_O_Ural_Refuel_RU"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_O_UAZ_AMB_RU", "CUP_O_BMP2_AMB_RU", "CUP_O_GAZ_Vodnik_MedEvac_RU"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_BTR60_RU", "CUP_O_BTR80_DESERT_RU", "CUP_O_BTR80A_DESERT_RU", "CUP_O_BTR90_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU", "CUP_O_MTLB_pk_WDL_RU"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU", "CUP_O_MTLB_pk_WDL_RU"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BMP2_RU", "CUP_O_BTR60_RU", "CUP_O_BTR80_DESERT_RU", "CUP_O_BTR80A_DESERT_RU", "CUP_O_BTR90_RU"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_O_T72_RU", "CUP_O_T90_RU"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_O_ZSU23_SLA"]] call _fnc_saveToTemplate; @@ -36,11 +38,12 @@ ["vehiclesPlanesCAS", ["CUP_O_Su25_Dyn_RU"]] call _fnc_saveToTemplate; ["vehiclesPlanesAA", ["CUP_O_SU34_RU"]] call _fnc_saveToTemplate; -["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; +["vehiclesPlanesTransport", ["CUP_O_MI6T_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["CUP_O_Mi8AMT_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["CUP_O_Mi8_medevac_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_O_Mi8AMT_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_DL_RU", "CUP_O_Ka52_RU", "CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_RU", "CUP_O_Ka52_RU"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_O_BM21_RU"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_O_BM21_RU", ["CUP_40Rnd_GRAD_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Temperate.sqf index 640ccf589f..35a9c7008b 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_AFRF_Temperate.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["O_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_O_UAZ_Open_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_RU", "CUP_O_UAZ_MG_RU", "CUP_O_UAZ_METIS_RU", "CUP_O_UAZ_SPG9_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["CUP_O_Kamaz_RU", "CUP_O_Ural_RU", "CUP_O_GAZ_Vodnik_Unarmed_RU"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_O_Kamaz_Open_RU", "CUP_O_Ural_Open_RU"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_O_Kamaz_Reammo_RU", "CUP_O_Ural_Reammo_RU"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_O_Ural_Repair_RU", "CUP_O_Kamaz_Repair_RU"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_O_Kamaz_Refuel_RU", "CUP_O_Ural_Refuel_RU"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_O_UAZ_AMB_RU", "CUP_O_BMP2_AMB_RU", "CUP_O_GAZ_Vodnik_MedEvac_RU"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_BTR60_RU", "CUP_O_BTR80_CAMO_RU", "CUP_O_BTR80A_CAMO_RU", "CUP_O_BTR90_RU", "CUP_O_GAZ_Vodnik_BPPU_RU", "CUP_O_GAZ_Vodnik_KPVT_RU", "CUP_O_MTLB_pk_WDL_RU"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_O_BRDM2_RUS", "CUP_O_BRDM2_ATGM_RUS", "CUP_O_MTLB_pk_WDL_RU", "CUP_O_GAZ_Vodnik_PK_RU", "CUP_O_GAZ_Vodnik_AGS_RU"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU", "CUP_O_BMP2_RU", "CUP_O_BTR60_RU", "CUP_O_BTR80_CAMO_RU", "CUP_O_BTR80A_CAMO_RU", "CUP_O_BTR90_RU"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_O_BMP3_RU", "CUP_O_BMP2_RU"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_O_T72_RU", "CUP_O_T90_RU"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_O_ZSU23_SLA"]] call _fnc_saveToTemplate; @@ -36,11 +38,12 @@ ["vehiclesPlanesCAS", ["CUP_O_Su25_Dyn_RU"]] call _fnc_saveToTemplate; ["vehiclesPlanesAA", ["CUP_O_SU34_RU"]] call _fnc_saveToTemplate; -["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; +["vehiclesPlanesTransport", ["CUP_O_MI6T_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["CUP_O_Mi8AMT_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["CUP_O_Mi8_medevac_RU", "O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_O_Mi8AMT_RU"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_DL_RU", "CUP_O_Ka52_RU", "CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_O_Mi8_RU"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_O_Mi24_V_Dynamic_RU", "CUP_O_Mi24_P_Dynamic_RU", "CUP_O_Ka50_RU", "CUP_O_Ka52_RU"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_O_BM21_RU"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_O_BM21_RU", ["CUP_40Rnd_GRAD_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Arid.sqf index a3a9ed7b0e..3a067392e6 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Arid.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_LR_Transport_GB_D"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_BAF_Coyote_GMG_D", "CUP_B_BAF_Coyote_L2A1_D", "CUP_B_Jackal2_L2A1_GB_D", "CUP_B_LR_Special_M2_GB_D", "CUP_B_LR_MG_GB_D", "CUP_B_Mastiff_HMG_GB_D", "CUP_B_Mastiff_LMG_GB_D", "CUP_B_Ridgback_GMG_GB_D", "CUP_B_Ridgback_HMG_GB_D", "CUP_B_Ridgback_LMG_GB_D", "CUP_B_Wolfhound_GMG_GB_D", "CUP_B_Wolfhound_HMG_GB_D", "CUP_B_Wolfhound_LMG_GB_D"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_BAF_Coyote_GMG_D", "CUP_B_BAF_Coyote_L2A1_D", "CUP_B_Jackal2_L2A1_GB_D", "CUP_B_LR_Special_M2_GB_D", "CUP_B_LR_MG_GB_D", "CUP_B_Ridgback_GMG_GB_D", "CUP_B_Ridgback_HMG_GB_D", "CUP_B_Ridgback_LMG_GB_D", "CUP_B_Wolfhound_GMG_GB_D", "CUP_B_Wolfhound_HMG_GB_D", "CUP_B_Wolfhound_LMG_GB_D"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_BAF_DES"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_MTVR_Ammo_BAF_DES"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_MTVR_Repair_BAF_DES"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_BAF_DES"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_LR_Ambulance_GB_D"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_FV432_Bulldog_GB_D_RWS", "CUP_B_FV432_Bulldog_GB_D", "CUP_B_FV510_GB_D", "CUP_B_FV510_GB_D_SLAT", "CUP_B_MCV80_GB_D", "CUP_B_MCV80_GB_D_SLAT"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_FV432_Bulldog_GB_D", "CUP_B_FV432_Bulldog_GB_D", "CUP_B_Mastiff_HMG_GB_D", "CUP_B_Mastiff_LMG_GB_D", "CUP_B_Mastiff_GMG_GB_D"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_FV432_Bulldog_GB_D_RWS", "CUP_B_FV432_Bulldog_GB_D_RWS", "CUP_B_FV510_GB_D", "CUP_B_MCV80_GB_D"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_FV510_GB_D", "CUP_B_FV510_GB_D_SLAT", "CUP_B_MCV80_GB_D", "CUP_B_MCV80_GB_D_SLAT"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_Challenger2_Desert_BAF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_B_M6LineBacker_USA_D", "CUP_B_nM1097_AVENGER_USA_DES", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_M6LineBacker_USA_D", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_B_AW159_Unarmed_RN_Blackcat", "CUP_B_AW159_Unarmed_GB", "CUP_B_AW159_Unarmed_RN_Grey"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_B_CH47F_GB", "CUP_B_MH47E_GB", "CUP_B_Merlin_HC3_GB", "CUP_B_Merlin_HC3_Armed_GB", "CUP_B_Merlin_HC3A_GB", "CUP_B_Merlin_HC4_GB", "CUP_B_SA330_Puma_HC1_BAF", "CUP_B_SA330_Puma_HC2_BAF"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_AW159_RN_Grey"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_AH1_DL_BAF"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_HE_BAF_DES"]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Temperate.sqf index 9826fa8345..befd366a26 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_BAF_Temperate.sqf @@ -19,18 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_LR_Transport_GB_W"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_BAF_Coyote_GMG_W", "CUP_B_BAF_Coyote_L2A1_W", "CUP_B_Jackal2_L2A1_GB_W", "CUP_B_LR_Special_M2_GB_W", "CUP_B_LR_MG_GB_W", "CUP_B_Mastiff_HMG_GB_W", "CUP_B_Mastiff_LMG_GB_W", "CUP_B_Ridgback_GMG_GB_W", "CUP_B_Ridgback_HMG_GB_W", "CUP_B_Ridgback_LMG_GB_W", "CUP_B_Wolfhound_GMG_GB_W", "CUP_B_Wolfhound_HMG_GB_W", "CUP_B_Wolfhound_LMG_GB_W"]] call _fnc_saveToTemplate; - +["vehiclesLightArmed", ["CUP_B_BAF_Coyote_GMG_W", "CUP_B_BAF_Coyote_L2A1_W", "CUP_B_Jackal2_L2A1_GB_W", "CUP_B_LR_Special_M2_GB_W", "CUP_B_LR_MG_GB_W", "CUP_B_Ridgback_GMG_GB_W", "CUP_B_Ridgback_HMG_GB_W", "CUP_B_Ridgback_LMG_GB_W", "CUP_B_Wolfhound_GMG_GB_W", "CUP_B_Wolfhound_HMG_GB_W", "CUP_B_Wolfhound_LMG_GB_W"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_BAF_WOOD"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; - ["vehiclesAmmoTrucks", ["CUP_B_MTVR_Ammo_BAF_WOOD"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_MTVR_Repair_BAF_WOOD"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_BAF_WOOD"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_LR_Ambulance_GB_W"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_FV432_Bulldog_GB_W_RWS", "CUP_B_FV432_Bulldog_GB_W", "CUP_B_FV510_GB_W_SLAT", "CUP_B_FV510_GB_W", "CUP_B_MCV80_GB_W_SLAT", "CUP_B_MCV80_GB_W"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_Mastiff_HMG_GB_W", "CUP_B_Mastiff_LMG_GB_W", "CUP_B_Mastiff_GMG_GB_W""CUP_B_FV432_Bulldog_GB_W", "CUP_B_FV432_Bulldog_GB_W"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_FV432_Bulldog_GB_W_RWS", "CUP_B_FV432_Bulldog_GB_W_RWS", "CUP_B_FV510_GB_W", "CUP_B_MCV80_GB_W"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_FV510_GB_W", "CUP_B_MCV80_GB_W", "CUP_B_FV510_GB_W_SLAT", "CUP_B_MCV80_GB_W_SLAT"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_Challenger2_Woodland_BAF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_B_M6LineBacker_USA_W", "CUP_B_nM1097_AVENGER_USA_WDL", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_M6LineBacker_USA_W", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -42,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_B_AW159_Unarmed_RN_Blackcat", "CUP_B_AW159_Unarmed_GB", "CUP_B_AW159_Unarmed_RN_Grey"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_B_CH47F_GB", "CUP_B_MH47E_GB", "CUP_B_Merlin_HC3_GB", "CUP_B_Merlin_HC3_Armed_GB", "CUP_B_Merlin_HC3A_GB", "CUP_B_Merlin_HC4_GB", "CUP_B_SA330_Puma_HC1_BAF", "CUP_B_SA330_Puma_HC2_BAF"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_AW159_GB"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_AH1_DL_BAF"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_HE_BAF_WOOD"]] call _fnc_saveToTemplate; @@ -66,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Arctic.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Arctic.sqf index c98236a634..c466d6a97e 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Arctic.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Arctic.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_UAZ_Unarmed_CDF", "CUP_B_UAZ_Open_CDF"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_UAZ_AGS30_CDF", "CUP_B_UAZ_MG_CDF", "CUP_B_UAZ_METIS_CDF", "CUP_B_UAZ_SPG9_CDF", "CUP_B_UAZ_AA_CDF"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_UAZ_AGS30_CDF", "CUP_B_UAZ_MG_CDF", "CUP_B_UAZ_METIS_CDF", "CUP_B_UAZ_SPG9_CDF", "CUP_B_UAZ_AA_CDF", "CUP_B_Ural_ZU23_CDF"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_Kamaz_CDF", "CUP_B_Ural_CDF", "CUP_B_Kamaz_Open_CDF"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_B_Kamaz_Open_CDF"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_Kamaz_Reammo_CDF", "CUP_B_Ural_Reammo_CDF"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_Kamaz_Repair_CDF", "CUP_B_Ural_Repair_CDF"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_Kamaz_Refuel_CDF", "CUP_B_Ural_Refuel_CDF"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_S1203_Ambulance_CDF", "CUP_B_BMP2_AMB_CDF"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_BRDM2_CDF", "CUP_B_BRDM2_ATGM_CDF", "CUP_B_BRDM2_HQ_CDF", "CUP_B_BTR60_CDF", "CUP_B_BTR80_CDF", "CUP_B_BTR80A_CDF", "CUP_B_MTLB_pk_CDF", "CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_BRDM2_CDF", "CUP_B_BRDM2_ATGM_CDF", "CUP_B_BRDM2_HQ_CDF", "CUP_B_MTLB_pk_CDF"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_BTR60_CDF", "CUP_B_BTR80_CDF", "CUP_B_BTR80A_CDF", "CUP_B_BMP2_CDF", "CUP_B_BMP2_CDF", "CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_T72_CDF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_B_ZSU23_CDF", "CUP_B_ZSU23_Afghan_CDF", "CUP_B_Ural_ZU23_CDF"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_ZSU23_CDF", "CUP_B_ZSU23_Afghan_CDF"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -38,8 +40,9 @@ ["vehiclesPlanesAA", ["CUP_B_SU34_CDF"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["CUP_B_Mi17_CDF"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["CUP_B_MI6T_CDF"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["CUP_B_Mi17_medevac_CDF"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["CUP_B_Mi17_CDF"]] call _fnc_saveToTemplate; // CUP_B_MI6A_CDF +["vehiclesHelisLightAttack", ["CUP_B_Mi171Sh_CDF"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_Mi24_D_Dynamic_CDF"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_BM21_CDF", "CUP_B_D30_CDF"]] call _fnc_saveToTemplate; @@ -67,6 +70,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Temperate.sqf index 0f0fc0fcf3..ab009becc8 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_CDF_Temperate.sqf @@ -19,17 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_UAZ_Unarmed_CDF", "CUP_B_UAZ_Open_CDF"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_UAZ_AGS30_CDF", "CUP_B_UAZ_MG_CDF", "CUP_B_UAZ_METIS_CDF", "CUP_B_UAZ_SPG9_CDF", "CUP_B_UAZ_AA_CDF"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_UAZ_AGS30_CDF", "CUP_B_UAZ_MG_CDF", "CUP_B_UAZ_METIS_CDF", "CUP_B_UAZ_SPG9_CDF", "CUP_B_UAZ_AA_CDF", "CUP_B_Ural_ZU23_CDF"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_Kamaz_CDF", "CUP_B_Ural_CDF", "CUP_B_Kamaz_Open_CDF"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_B_Kamaz_Open_CDF"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_Kamaz_Reammo_CDF", "CUP_B_Ural_Reammo_CDF"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_Kamaz_Repair_CDF", "CUP_B_Ural_Repair_CDF"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_Kamaz_Refuel_CDF", "CUP_B_Ural_Refuel_CDF"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_S1203_Ambulance_CDF", "CUP_B_BMP2_AMB_CDF"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_BRDM2_CDF", "CUP_B_BRDM2_ATGM_CDF", "CUP_B_BRDM2_HQ_CDF", "CUP_B_BTR60_CDF", "CUP_B_BTR80_CDF", "CUP_B_BTR80A_CDF", "CUP_B_MTLB_pk_CDF", "CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_BRDM2_CDF", "CUP_B_BRDM2_ATGM_CDF", "CUP_B_BRDM2_HQ_CDF", "CUP_B_MTLB_pk_CDF"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_BTR60_CDF", "CUP_B_BTR80_CDF", "CUP_B_BTR80A_CDF", "CUP_B_BMP2_CDF", "CUP_B_BMP2_CDF", "CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_BMP2_CDF"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_T72_CDF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_B_ZSU23_CDF", "CUP_B_ZSU23_Afghan_CDF", "CUP_B_Ural_ZU23_CDF"]] call _fnc_saveToTemplate; - +["vehiclesAA", ["CUP_B_ZSU23_CDF", "CUP_B_ZSU23_Afghan_CDF"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -39,8 +40,9 @@ ["vehiclesPlanesAA", ["CUP_B_SU34_CDF"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["CUP_B_Mi17_CDF"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["CUP_B_MI6T_CDF"]] call _fnc_saveToTemplate; +["vehiclesHelisLight", ["CUP_B_Mi17_medevac_CDF"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["CUP_B_Mi17_CDF"]] call _fnc_saveToTemplate; // CUP_B_MI6A_CDF +["vehiclesHelisLightAttack", ["CUP_B_Mi171Sh_CDF"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_B_Mi24_D_Dynamic_CDF"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_BM21_CDF", "CUP_B_D30_CDF"]] call _fnc_saveToTemplate; @@ -68,6 +70,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arctic.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arctic.sqf index 5a8643c551..459a572e09 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arctic.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arctic.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["CUP_I_4WD_unarmed_ION"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_I_LSV_02_unarmed_ION", "CUP_I_nM1025_Unarmed_ION_WIN", "CUP_I_nM1038_4s_ION_WIN"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["CUP_B_nM1025_SOV_Mk19_ION_WIN", "CUP_B_nM1025_SOV_M2_ION_WIN", "CUP_I_SUV_Armored_ION", "CUP_I_nM1025_M240_DF_ION_WIN"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["CUP_B_nM1025_SOV_Mk19_ION_WIN", "CUP_B_nM1025_SOV_M2_ION_WIN", "CUP_I_SUV_Armored_ION", "CUP_I_nM1025_M240_DF_ION_WIN", "CUP_I_nM1036_TOW_ION_WIN"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_I_Van_Transport_ION"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_I_Van_Cargo_ION"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_I_nM1038_Ammo_ION_WIN"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_I_nM1038_Repair_ION_WIN"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_I_nM1035_amb_ION_WIN"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_I_BTR80A_ION", "CUP_I_BTR80_ION"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_I_RG31_Mk19_W_ION", "CUP_I_RG31E_M2_W_ION", "CUP_I_RG31_M2_W_ION", "CUP_I_RG31_M2_W_GC_ION"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_I_BTR80A_ION", "CUP_I_BTR80_ION", "CUP_B_FV432_Bulldog_GB_W_RWS"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_FV510_GB_W_SLAT"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_Challenger2_Snow_BAF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_I_Hilux_zu23_TK"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["CUP_B_Zodiac_USMC"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB_USMC", "CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_I_MH6M_ION", "CUP_I_412_Mil_Utility_PMC"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_I_Merlin_HC3_PMC_Lux_black", "CUP_I_Merlin_HC3_PMC_Transport_black"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_I_412_dynamicLoadout_PMC", "CUP_I_412_Military_Armed_AT_PMC"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_I_Mi24_Mk3_ION"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_DPICM_BAF_DES"]] call _fnc_saveToTemplate; @@ -68,6 +71,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arid.sqf index 4383c504ab..b7fe4638da 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_ION_Arid.sqf @@ -18,17 +18,19 @@ ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["vehiclesBasic", ["CUP_I_4WD_unarmed_ION"]] call _fnc_saveToTemplate; -["vehiclesLightUnarmed", ["CUP_I_LSV_02_unarmed_ION", "CUP_I_nM1025_Unarmed_ION", "CUP_I_MATV_ION"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["CUP_B_nM1025_SOV_Mk19_ION", "CUP_B_nM1025_SOV_M2_ION", "CUP_I_SUV_Armored_ION", "CUP_I_4WD_LMG_ION"]] call _fnc_saveToTemplate; +["vehiclesLightUnarmed", ["CUP_I_LSV_02_unarmed_ION", "CUP_I_nM1025_Unarmed_ION", "CUP_I_MATV_ION", "CUP_I_FENNEK_ION"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["CUP_B_nM1025_SOV_Mk19_ION", "CUP_B_nM1025_SOV_M2_ION", "CUP_I_SUV_Armored_ION", "CUP_I_4WD_LMG_ION", "CUP_I_FENNEK_HMG_ION", "CUP_I_LSV_02_Minigun_ION", "CUP_I_FENNEK_GMG_ION", "CUP_I_MATV_HMG_ION", "CUP_I_MATV_GMG_ION"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_I_Van_Transport_ION"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_I_Van_Cargo_ION"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_I_nM1038_Ammo_ION"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_I_nM1038_Repair_ION"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_I_nM1035_amb_ION"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_I_BTR80A_ION", "CUP_I_BTR80_ION"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_I_RG31_Mk19_ION", "CUP_I_RG31E_M2_ION", "CUP_I_RG31_M2_ION", "CUP_I_RG31_M2_GC_ION"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_I_BTR80A_ION", "CUP_I_BTR80_ION", "CUP_B_FV432_Bulldog_GB_D_RWS"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_FV510_GB_D_SLAT"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_Challenger2_Desert_BAF"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_I_Hilux_zu23_TK"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_I_M163_Vulcan_RACS"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["CUP_B_Zodiac_USMC"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB_USMC", "CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_I_MH6M_ION", "CUP_I_412_Mil_Utility_PMC"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_I_Merlin_HC3_PMC_Lux_black", "CUP_I_Merlin_HC3_PMC_Transport_black"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_I_412_dynamicLoadout_PMC", "CUP_I_412_Military_Armed_AT_PMC"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_I_Mi24_Mk3_ION"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_DPICM_BAF_DES"]] call _fnc_saveToTemplate; @@ -68,6 +71,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Arid.sqf index 57386c6a46..0740367e90 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Arid.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_nM1025_Unarmed_DF_USA_DES", "CUP_B_nM1025_Unarmed_USA_DES", "CUP_B_nM1025_Unarmed_DF_USA_DES", "CUP_B_nM1038_DF_USA_DES", "CUP_B_nM1038_USA_DES", "CUP_B_nM1038_4s_DF_USA_DES", "CUP_B_nM1038_4s_USA_DES", "CUP_B_M1151_USA"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_nM1025_M2_USA_DES", "CUP_B_nM1025_M2_DF_USA_DES", "CUP_B_nM1025_M240_USA_DES", "CUP_B_nM1025_M240_DF_USA_DES", "CUP_B_nM1025_Mk19_USA_DES", "CUP_B_nM1025_Mk19_DF_USA_DES", "CUP_B_nM1025_SOV_M2_USA_DES", "CUP_B_nM1025_SOV_Mk19_USA_DES", "CUP_B_nM1036_TOW_USA_DES", "CUP_B_nM1036_TOW_DF_USA_DES", "CUP_B_M1151_M2_USA", "CUP_B_M1151_Deploy_USA", "CUP_B_M1151_Mk19_USA", "CUP_B_M1165_GMV_USA", "CUP_B_M1167_USA", "CUP_B_RG31_Mk19_USA", "CUP_B_RG31E_M2_USA", "CUP_B_RG31_M2_USA", "CUP_B_RG31_M2_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_nM1025_M2_USA_DES", "CUP_B_nM1025_M2_DF_USA_DES", "CUP_B_nM1025_M240_USA_DES", "CUP_B_nM1025_M240_DF_USA_DES", "CUP_B_nM1025_Mk19_USA_DES", "CUP_B_nM1025_Mk19_DF_USA_DES", "CUP_B_nM1025_SOV_M2_USA_DES", "CUP_B_nM1025_SOV_Mk19_USA_DES", "CUP_B_nM1036_TOW_USA_DES", "CUP_B_nM1036_TOW_DF_USA_DES", "CUP_B_M1151_M2_USA", "CUP_B_M1151_Deploy_USA", "CUP_B_M1151_Mk19_USA", "CUP_B_M1165_GMV_USA", "CUP_B_M1167_USA", "CUP_I_LR_AA_RACS", "CUP_B_M1135_ATGMV_Desert"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_I_MTVR_RACS"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_I_MTVR_Ammo_RACS", "CUP_I_M113A3_Reammo_RACS"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_I_MTVR_Repair_RACS", "CUP_I_M113A3_Repair_RACS"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_I_MTVR_Refuel_RACS"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_I_LR_Ambulance_RACS", "CUP_I_M113A1_Med_RACS"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_M2Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D", "CUP_B_M7Bradley_USA_D", "CUP_B_M6LineBacker_USA_D", "CUP_B_M1126_ICV_M2_Desert", "CUP_B_M1126_ICV_MK19_Desert", "CUP_B_M1135_ATGMV_Desert", "CUP_B_M1129_MC_MK19_Desert", "CUP_I_LAV25_RACS", "CUP_I_M113A1_RACS", "CUP_I_M113A1_RACS_URB"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_I_M113A1_RACS", "CUP_I_M113A1_RACS_URB", "CUP_B_RG31_Mk19_USA", "CUP_B_RG31E_M2_USA", "CUP_B_RG31_M2_USA", "CUP_B_RG31_M2_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_M1126_ICV_M2_Desert", "CUP_B_M1126_ICV_MK19_Desert", "CUP_I_LAV25_RACS", "CUP_I_LAV25M240_RACS", "CUP_I_AAV_RACS"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_M2Bradley_USA_D", "CUP_B_M7Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_M1A2C_Desert_US_Army", "CUP_B_M1A2C_TUSK_II_Desert_US_Army", "CUP_B_M1A2C_TUSK_Desert_US_Army", "CUP_I_M60A3_RACS", "CUP_I_M60A3_TTS_RACS", "CUP_B_M1A2SEP_RACS", "CUP_B_M1A2SEP_TUSK_RACS", "CUP_I_T72_RACS"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_I_M163_Vulcan_RACS", "CUP_I_LR_AA_RACS"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_M6LineBacker_USA_D", "CUP_I_M163_Vulcan_RACS"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -36,11 +38,12 @@ ["vehiclesPlanesCAS", ["CUP_B_A10_DYN_USA"]] call _fnc_saveToTemplate; ["vehiclesPlanesAA", ["CUP_I_JAS39_RACS"]] call _fnc_saveToTemplate; -["vehiclesPlanesTransport", ["CUP_B_MV22_USMC_RAMPGUN"]] call _fnc_saveToTemplate; +["vehiclesPlanesTransport", ["CUP_I_C130J_RACS"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["CUP_I_MH6J_RACS", "CUP_I_UH1H_RACS"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_I_SA330_Puma_HC1_RACS", "CUP_I_SA330_Puma_HC2_RACS", "CUP_I_CH47F_RACS", "CUP_I_UH60L_RACS", "CUP_I_UH60L_FFV_RACS", "CUP_I_UH60L_Unarmed_RACS", "CUP_I_UH60L_Unarmed_FFV_Racs"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_I_AH6J_AT_RACS", "CUP_I_AH6J_RACS", "CUP_B_AH64D_DL_USA", "CUP_I_UH1H_gunship_RACS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_I_AH6J_AT_RACS", "CUP_I_AH6J_RACS", "CUP_I_UH1H_gunship_RACS"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_I_M270_HE_RACS"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_I_M270_HE_RACS", ["CUP_12Rnd_MLRS_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Tropical.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Tropical.sqf index dbd73d4831..52dd2bb0c9 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Tropical.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_RACS_Tropical.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_nM1025_Unarmed_DF_USA_WDL", "CUP_B_nM1025_Unarmed_USA_WDL", "CUP_B_nM1038_DF_USA_WDL", "CUP_B_nM1038_USA_WDL", "CUP_B_nM1038_4s_DF_USA_WDL", "CUP_B_nM1038_4s_USA_WDL", "CUP_B_M1151_WDL_USA"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_nM1025_M2_USA_WDL", "CUP_B_nM1025_M2_DF_USA_WDL", "CUP_B_nM1025_M240_USA_WDL", "CUP_B_nM1025_M240_DF_USA_WDL", "CUP_B_nM1025_Mk19_USA_WDL", "CUP_B_nM1025_Mk19_DF_USA_WDL", "CUP_B_nM1025_SOV_M2_USA_WDL", "CUP_B_nM1025_SOV_Mk19_USA_WDL", "CUP_B_nM1036_TOW_USA_WDL", "CUP_B_nM1036_TOW_DF_USA_WDL", "CUP_B_M1151_M2_WDL_USA", "CUP_B_M1151_Deploy_WDL_USA", "CUP_B_M1151_Mk19_WDL_USA", "CUP_B_M1165_GMV_WDL_USA", "CUP_B_M1167_WDL_USA", "CUP_B_RG31_Mk19_OD_USA", "CUP_B_RG31E_M2_OD_USA", "CUP_B_RG31_M2_OD_USA", "CUP_B_RG31_M2_OD_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_nM1025_M2_USA_WDL", "CUP_B_nM1025_M2_DF_USA_WDL", "CUP_B_nM1025_M240_USA_WDL", "CUP_B_nM1025_M240_DF_USA_WDL", "CUP_B_nM1025_Mk19_USA_WDL", "CUP_B_nM1025_Mk19_DF_USA_WDL", "CUP_B_nM1025_SOV_M2_USA_WDL", "CUP_B_nM1025_SOV_Mk19_USA_WDL", "CUP_B_nM1036_TOW_USA_WDL", "CUP_B_nM1036_TOW_DF_USA_WDL", "CUP_B_M1151_M2_WDL_USA", "CUP_B_M1151_Deploy_WDL_USA", "CUP_B_M1151_Mk19_WDL_USA", "CUP_B_M1165_GMV_WDL_USA", "CUP_B_M1167_WDL_USA", "CUP_I_LR_AA_RACS", "CUP_B_M1135_ATGMV_Woodland"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_I_MTVR_RACS"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_I_MTVR_Ammo_RACS", "CUP_I_M113A3_Reammo_RACS"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_I_MTVR_Repair_RACS", "CUP_I_M113A3_Repair_RACS"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_I_MTVR_Refuel_RACS"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_I_LR_Ambulance_RACS", "CUP_I_M113A1_Med_RACS"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_M2Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W", "CUP_B_M7Bradley_USA_W", "CUP_B_M6LineBacker_USA_W", "CUP_B_M1126_ICV_M2_Woodland", "CUP_B_M1126_ICV_MK19_Woodland", "CUP_B_M1135_ATGMV_Woodland", "CUP_I_LAV25_RACS", "CUP_I_M113A1_RACS", "CUP_I_M113A1_RACS_URB"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_I_M113A1_RACS", "CUP_I_M113A1_RACS_URB", "CUP_B_RG31_Mk19_OD_USA", "CUP_B_RG31E_M2_OD_USA", "CUP_B_RG31_M2_OD_USA", "CUP_B_RG31_M2_OD_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_I_AAV_RACS", "CUP_B_M1126_ICV_M2_Woodland", "CUP_B_M1126_ICV_MK19_Woodland", "CUP_I_LAV25_RACS", "CUP_I_LAV25M240_RACS"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_B_M2Bradley_USA_W", "CUP_B_M7Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_M1A2C_OD_US_Army", "CUP_B_M1A2SEP_TUSK_II_OD_US_Army", "CUP_B_M1A1SA_TUSK_OD_US_Army", "CUP_I_M60A3_RACS", "CUP_I_M60A3_TTS_RACS", "CUP_B_M1A2SEP_RACS", "CUP_B_M1A2SEP_TUSK_RACS", "CUP_I_T72_RACS"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_I_M163_Vulcan_RACS", "CUP_I_LR_AA_RACS"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_B_M6LineBacker_USA_W", "CUP_I_M163_Vulcan_RACS"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -36,11 +38,12 @@ ["vehiclesPlanesCAS", ["CUP_B_A10_DYN_USA"]] call _fnc_saveToTemplate; ["vehiclesPlanesAA", ["CUP_I_JAS39_RACS"]] call _fnc_saveToTemplate; -["vehiclesPlanesTransport", ["CUP_B_MV22_USMC_RAMPGUN"]] call _fnc_saveToTemplate; +["vehiclesPlanesTransport", ["CUP_I_C130J_RACS"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["CUP_I_MH6J_RACS", "CUP_I_UH1H_RACS"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_I_SA330_Puma_HC1_RACS", "CUP_I_SA330_Puma_HC2_RACS", "CUP_I_CH47F_RACS", "CUP_I_UH60L_RACS", "CUP_I_UH60L_FFV_RACS", "CUP_I_UH60L_Unarmed_RACS", "CUP_I_UH60L_Unarmed_FFV_Racs"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_B_AH6M_USA", "CUP_B_AH6J_USA", "CUP_B_AH64D_DL_USA", "CUP_I_UH1H_gunship_RACS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_I_AH6J_AT_RACS", "CUP_I_AH6J_RACS", "CUP_I_UH1H_gunship_RACS"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_I_M270_HE_RACS"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_I_M270_HE_RACS", ["CUP_12Rnd_MLRS_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_SLA_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_SLA_Temperate.sqf index 08792e1088..71436d74de 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_SLA_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_SLA_Temperate.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["O_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_O_UAZ_Unarmed_SLA"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_SLA", "CUP_O_UAZ_MG_SLA", "CUP_O_UAZ_METIS_SLA", "CUP_O_UAZ_SPG9_SLA"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_O_UAZ_AGS30_SLA", "CUP_O_UAZ_MG_SLA", "CUP_O_UAZ_METIS_SLA", "CUP_O_UAZ_SPG9_SLA", "CUP_O_Ural_ZU23_SLA"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_O_Ural_SLA"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_O_Ural_Open_SLA"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_O_Ural_Reammo_SLA"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_O_Ural_Repair_SLA"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_O_Ural_Refuel_SLA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_O_UAZ_AMB_RU", "CUP_O_BMP2_AMB_sla"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_O_BMP2_SLA", "CUP_O_BRDM2_SLA", "CUP_O_BRDM2_ATGM_SLA", "CUP_O_BTR60_SLA", "CUP_O_BTR80_SLA", "CUP_O_BTR80A_SLA", "CUP_O_MTLB_pk_SLA"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_O_BRDM2_SLA", "CUP_O_BRDM2_ATGM_SLA", "CUP_O_BTR60_SLA", "CUP_O_MTLB_pk_SLA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_O_BMP2_SLA", "CUP_O_BMP2_SLA", "CUP_O_BTR80_SLA", "CUP_O_BTR80A_SLA"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_O_BMP2_SLA"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_O_T72_RU", "CUP_O_T55_CHDKZ"]] call _fnc_saveToTemplate; -["vehiclesAA", ["CUP_O_ZSU23_ChDKZ"]] call _fnc_saveToTemplate; +["vehiclesAA", ["CUP_O_ZSU23_SLA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["CUP_O_PBX_RU"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["CUP_B_RHIB2Turret_USMC"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["CUP_O_UH1H_SLA", "CUP_O_UH1H_slick_SLA"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_O_Mi8_SLA_1"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_O_Mi8_SLA_2", "CUP_O_Mi24_D_Dynamic_SLA", "CUP_O_Ka50_DL_SLA", "CUP_O_UH1H_gunship_SLA"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_O_Mi8_SLA_2", "CUP_O_UH1H_gunship_SLA"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_O_Mi24_D_Dynamic_SLA", "CUP_O_Ka50_SLA"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_O_BM21_SLA"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_O_BM21_SLA", ["CUP_40Rnd_GRAD_HE"]]]] call _fnc_saveToTemplate; @@ -65,6 +68,8 @@ ["minefieldAT", ["CUP_MineE"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_TKA_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_TKA_Arid.sqf index bc26f797d6..a1541f1ccc 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_TKA_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_TKA_Arid.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["O_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_O_LR_Transport_TKA", "CUP_O_UAZ_Unarmed_TKA", "CUP_O_UAZ_Open_TKA", "CUP_O_BTR40_TKA"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_O_LR_MG_TKA", "CUP_O_LR_SPG9_TKA", "CUP_O_UAZ_AGS30_TKA", "CUP_O_UAZ_MG_TKA", "CUP_O_UAZ_METIS_TKA", "CUP_O_UAZ_SPG9_TKA"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_O_LR_MG_TKA", "CUP_O_LR_SPG9_TKA", "CUP_O_UAZ_AGS30_TKA", "CUP_O_UAZ_MG_TKA", "CUP_O_UAZ_METIS_TKA", "CUP_O_UAZ_SPG9_TKA", "CUP_O_BTR40_MG_TKA", "CUP_O_Ural_ZU23_TKA"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_O_V3S_Covered_TKA", "CUP_O_Ural_TKA"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["CUP_O_V3S_Open_TKA", "CUP_O_Ural_Open_TKA"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_O_V3S_Rearm_TKA", "CUP_O_Ural_Reammo_TKA", "CUP_O_M113A3_Reammo_TKA"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_O_Ural_Repair_TKA", "CUP_O_V3S_Repair_TKA", "CUP_O_M113A3_Repair_TKA"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_O_V3S_Refuel_TKA", "CUP_O_Ural_Refuel_TKA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_O_LR_Ambulance_TKA", "CUP_O_BMP2_AMB_TKA", "CUP_O_M113A3_Med_TKA"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_O_BMP1_TKA", "CUP_O_BMP1P_TKA", "CUP_O_BMP2_TKA", "CUP_O_BMP2_ZU_TKA", "CUP_O_BRDM2_TKA", "CUP_O_BRDM2_ATGM_TKA", "CUP_O_BTR40_MG_TKA", "CUP_O_BTR80_TK", "CUP_O_BTR80A_TK", "CUP_O_M113A3_TKA", "CUP_O_MTLB_pk_TKA"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_O_BRDM2_TKA", "CUP_O_BRDM2_ATGM_TKA", "CUP_O_BTR60_TK", "CUP_O_BTR80_TK", "CUP_O_BTR80A_TK", "CUP_O_MTLB_pk_TKA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_O_BMP1_TKA", "CUP_O_BMP1P_TKA", "CUP_O_BMP2_TKA", "CUP_O_BMP2_ZU_TKA", "CUP_O_M113A3_TKA"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["CUP_O_BMP2_TKA"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_O_T34_TKA", "CUP_O_T55_TK", "CUP_O_T72_TKA"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_O_ZSU23_TK"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ ["vehiclesHelisLight", ["CUP_O_UH1H_TKA", "CUP_O_UH1H_slick_TKA"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_O_Mi17_TK"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_O_UH1H_gunship_TKA", "CUP_O_UH1H_armed_TKA"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["CUP_O_Mi24_D_Dynamic_TK"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_O_BM21_TKA"]] call _fnc_saveToTemplate; @@ -63,6 +66,8 @@ ["minefieldAT", []] call _fnc_saveToTemplate; ["minefieldAPERS", []] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Arid.sqf index 7ce0d450b7..84189caffe 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Arid.sqf @@ -19,15 +19,17 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_nM1025_Unarmed_DF_USA_DES", "CUP_B_nM1025_Unarmed_USA_DES", "CUP_B_nM1025_Unarmed_DF_USA_DES", "CUP_B_nM1038_DF_USA_DES", "CUP_B_nM1038_USA_DES", "CUP_B_nM1038_4s_DF_USA_DES", "CUP_B_nM1038_4s_USA_DES", "CUP_B_M1151_USA", "CUP_B_M1152_USA"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_HMMWV_Crows_M2_USA", "CUP_B_HMMWV_Crows_MK19_USA", "CUP_B_HMMWV_M2_GPK_USA", "CUP_B_nM1025_M2_USA_DES", "CUP_B_nM1025_M2_DF_USA_DES", "CUP_B_nM1025_M240_USA_DES", "CUP_B_nM1025_M240_DF_USA_DES", "CUP_B_nM1025_Mk19_USA_DES", "CUP_B_nM1025_Mk19_DF_USA_DES", "CUP_B_nM1025_SOV_M2_USA_DES", "CUP_B_nM1025_SOV_Mk19_USA_DES", "CUP_B_nM1036_TOW_USA_DES", "CUP_B_nM1036_TOW_DF_USA_DES", "CUP_B_M1151_M2_USA", "CUP_B_M1151_Deploy_USA", "CUP_B_M1151_Mk19_USA", "CUP_B_M1165_GMV_USA", "CUP_B_M1167_USA", "CUP_B_RG31_Mk19_USA", "CUP_B_RG31E_M2_USA", "CUP_B_RG31_M2_USA", "CUP_B_RG31_M2_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_HMMWV_Crows_M2_USA", "CUP_B_HMMWV_Crows_MK19_USA", "CUP_B_HMMWV_M2_GPK_USA", "CUP_B_nM1025_M2_USA_DES", "CUP_B_nM1025_M2_DF_USA_DES", "CUP_B_nM1025_M240_USA_DES", "CUP_B_nM1025_M240_DF_USA_DES", "CUP_B_nM1025_Mk19_USA_DES", "CUP_B_nM1025_Mk19_DF_USA_DES", "CUP_B_nM1025_SOV_M2_USA_DES", "CUP_B_nM1025_SOV_Mk19_USA_DES", "CUP_B_nM1036_TOW_USA_DES", "CUP_B_nM1036_TOW_DF_USA_DES", "CUP_B_M1151_M2_USA", "CUP_B_M1151_Deploy_USA", "CUP_B_M1151_Mk19_USA", "CUP_B_M1165_GMV_USA", "CUP_B_M1167_USA", "CUP_B_M1135_ATGMV_Desert"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_USA"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["B_Truck_01_flatbed_F"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_MTVR_Ammo_USA", "CUP_B_nM1038_Ammo_USA_DES", "CUP_B_nM1038_Ammo_DF_USA_DES"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_nM1038_Repair_USA_DES", "CUP_B_nM1038_Repair_DF_USA_DES", "CUP_B_MTVR_Repair_USA"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_nM997_DF_USA_DES", "CUP_B_nM997_USA_DES", "CUP_B_M1133_MEV_Desert"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_M2Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D", "CUP_B_M7Bradley_USA_D", "CUP_B_M6LineBacker_USA_D", "CUP_B_M1126_ICV_M2_Desert", "CUP_B_M1126_ICV_MK19_Desert", "CUP_B_M1128_MGS_Desert", "CUP_B_M1130_CV_M2_Desert", "CUP_B_M1135_ATGMV_Desert", "CUP_B_M1129_MC_MK19_Desert"]] call _fnc_saveToTemplate; -["vehiclesTanks", ["CUP_B_M1A1SA_Desert_US_Army", "CUP_B_M1A1SA_Desert_TUSK_US_Army", "CUP_B_M1A2SEP_Desert_US_Army", "CUP_B_M1A2SEP_TUSK_II_Desert_US_Army", "CUP_B_M1A2SEP_TUSK_Desert_US_Army", "CUP_B_M1A2C_Desert_US_Army", "CUP_B_M1A2C_TUSK_II_Desert_US_Army", "CUP_B_M1A2C_TUSK_Desert_US_Army"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_M113A3_desert_USA", "CUP_B_M113A3_desert_USA", "CUP_B_RG31_Mk19_USA", "CUP_B_RG31E_M2_USA", "CUP_B_RG31_M2_USA", "CUP_B_RG31_M2_GC_USA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_M2Bradley_USA_D", "CUP_B_M7Bradley_USA_D", "CUP_B_M1126_ICV_M2_Desert", "CUP_B_M1126_ICV_M2_Desert", "CUP_B_M1126_ICV_MK19_Desert"]] call _fnc_saveToTemplate; // "CUP_B_M1129_MC_MK19_Desert" +["vehiclesIFVs", ["CUP_B_M2Bradley_USA_D", "CUP_B_M7Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D", "CUP_B_M2A3Bradley_USA_D"]] call _fnc_saveToTemplate; +["vehiclesTanks", ["CUP_B_M1A1SA_Desert_US_Army", "CUP_B_M1A1SA_Desert_TUSK_US_Army", "CUP_B_M1A2SEP_Desert_US_Army", "CUP_B_M1A2SEP_TUSK_II_Desert_US_Army", "CUP_B_M1A2SEP_TUSK_Desert_US_Army", "CUP_B_M1A2C_Desert_US_Army", "CUP_B_M1A2C_TUSK_II_Desert_US_Army", "CUP_B_M1A2C_TUSK_Desert_US_Army", "CUP_B_M1128_MGS_Desert"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_M6LineBacker_USA_D", "CUP_B_nM1097_AVENGER_USA_DES", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["CUP_B_MH6M_USA", "CUP_B_MH6J_USA"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_B_UH60M_US", "CUP_B_UH60M_FFV_US", "CUP_B_UH60M_Unarmed_US", "CUP_B_UH60M_Unarmed_FFV_US"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_B_AH6M_USA", "CUP_B_AH6J_USA", "CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_AH6M_USA", "CUP_B_AH6J_USA"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_HE_USA"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_B_M270_HE_USA", ["CUP_12Rnd_MLRS_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Temperate.sqf index 20f75bca49..4a90a989aa 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Army_Temperate.sqf @@ -19,15 +19,17 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_M1152_WDL_USA", "CUP_B_M1151_WDL_USA", "CUP_B_nM1038_4s_USA_WDL", "CUP_B_nM1038_4s_DF_USA_WDL", "CUP_B_nM1038_DF_USA_WDL", "CUP_B_nM1038_USA_WDL", "CUP_B_nM1025_Unarmed_DF_USA_WDL", "CUP_B_nM1025_Unarmed_USA_WDL"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_RG31_M2_OD_GC_USA", "CUP_B_RG31_M2_OD_USA", "CUP_B_RG31E_M2_OD_USA", "CUP_B_RG31_Mk19_OD_USA", "CUP_B_M1167_WDL_USA", "CUP_B_M1165_GMV_WDL_USA", "CUP_B_M1151_Mk19_WDL_USA", "CUP_B_M1151_Deploy_WDL_USA", "CUP_B_M1151_M2_WDL_USA", "CUP_B_nM1036_TOW_DF_USA_WDL", "CUP_B_nM1036_TOW_USA_WDL", "CUP_B_nM1025_SOV_Mk19_USA_WDL", "CUP_B_nM1025_SOV_M2_USA_WDL", "CUP_B_nM1025_Mk19_DF_USA_WDL", "CUP_B_nM1025_Mk19_USA_WDL", "CUP_B_nM1025_M240_DF_USA_WDL", "CUP_B_nM1025_M240_USA_WDL", "CUP_B_nM1025_M2_DF_USA_WDL", "CUP_B_nM1025_M2_USA_WDL"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_M1167_WDL_USA", "CUP_B_M1165_GMV_WDL_USA", "CUP_B_M1151_Mk19_WDL_USA", "CUP_B_M1151_Deploy_WDL_USA", "CUP_B_M1151_M2_WDL_USA", "CUP_B_nM1036_TOW_DF_USA_WDL", "CUP_B_nM1036_TOW_USA_WDL", "CUP_B_nM1025_SOV_Mk19_USA_WDL", "CUP_B_nM1025_SOV_M2_USA_WDL", "CUP_B_nM1025_Mk19_DF_USA_WDL", "CUP_B_nM1025_Mk19_USA_WDL", "CUP_B_nM1025_M240_DF_USA_WDL", "CUP_B_nM1025_M240_USA_WDL", "CUP_B_nM1025_M2_DF_USA_WDL", "CUP_B_nM1025_M2_USA_WDL", "CUP_B_M1135_ATGMV_Woodland"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_USA"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["B_Truck_01_flatbed_F"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_MTVR_Ammo_USA", "CUP_B_nM1038_Ammo_USA_WDL", "CUP_B_nM1038_Ammo_DF_USA_WDL"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_nM1038_Repair_DF_USA_WDL", "CUP_B_nM1038_Repair_USA_WDL", "CUP_B_MTVR_Repair_USA"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USA"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_nM997_DF_USA_WDL", "CUP_B_nM997_USA_WDL", "CUP_B_M1133_MEV_Woodland"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_M6LineBacker_USA_W", "CUP_B_M7Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W", "CUP_B_M2Bradley_USA_W", "CUP_B_M1126_ICV_M2_Woodland", "CUP_B_M1126_ICV_MK19_Woodland", "CUP_B_M1128_MGS_Woodland", "CUP_B_M1130_CV_M2_Woodland", "CUP_B_M1135_ATGMV_Woodland", "CUP_B_M1129_MC_MK19_Woodland"]] call _fnc_saveToTemplate; -["vehiclesTanks", ["CUP_B_M1A2C_TUSK_Woodland_US_Army", "CUP_B_M1A2C_TUSK_II_Woodland_US_Army", "CUP_B_M1A2C_Woodland_US_Army", "CUP_B_M1A2SEP_TUSK_Woodland_US_Army", "CUP_B_M1A2SEP_TUSK_II_Woodland_US_Army", "CUP_B_M1A2SEP_Woodland_US_Army", "CUP_B_M1A1SA_TUSK_Woodland_US_Army", "CUP_B_M1A1SA_Woodland_US_Army"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_M113A3_USA", "CUP_B_M113A3_USA", "CUP_B_RG31E_M2_OD_USA", "CUP_B_RG31_Mk19_OD_USA", "CUP_B_RG31_M2_OD_GC_USA", "CUP_B_RG31_M2_OD_USA"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_M2Bradley_USA_W", "CUP_B_M1126_ICV_M2_Woodland", "CUP_B_M1126_ICV_MK19_Woodland"]] call _fnc_saveToTemplate; // mortar carrier: "CUP_B_M1129_MC_MK19_Woodland" +["vehiclesIFVs", ["CUP_B_M2Bradley_USA_W", "CUP_B_M7Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W", "CUP_B_M2A3Bradley_USA_W"]] call _fnc_saveToTemplate; +["vehiclesTanks", ["CUP_B_M1A2C_TUSK_Woodland_US_Army", "CUP_B_M1A2C_TUSK_II_Woodland_US_Army", "CUP_B_M1A2C_Woodland_US_Army", "CUP_B_M1A2SEP_TUSK_Woodland_US_Army", "CUP_B_M1A2SEP_TUSK_II_Woodland_US_Army", "CUP_B_M1A2SEP_Woodland_US_Army", "CUP_B_M1A1SA_TUSK_Woodland_US_Army", "CUP_B_M1A1SA_Woodland_US_Army", "CUP_B_M1128_MGS_Woodland"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_M6LineBacker_USA_W", "CUP_B_nM1097_AVENGER_USA_WDL", "CUP_B_M163_Vulcan_USA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ ["vehiclesPlanesTransport", ["CUP_B_C130J_USMC", "CUP_B_MV22_USMC_RAMPGUN"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["CUP_B_MH6M_USA", "CUP_B_MH6J_USA"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["CUP_B_UH60M_US", "CUP_B_UH60M_FFV_US", "CUP_B_UH60M_Unarmed_US", "CUP_B_UH60M_Unarmed_FFV_US", "CUP_B_MV22_USMC_RAMPGUN"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_B_AH6M_USA", "CUP_B_AH6J_USA", "CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["CUP_B_UH60M_US", "CUP_B_UH60M_FFV_US", "CUP_B_UH60M_Unarmed_US", "CUP_B_UH60M_Unarmed_FFV_US"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_AH6M_USA", "CUP_B_AH6J_USA"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH64D_DL_USA"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_HE_USA"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [["CUP_B_M270_HE_USA", ["CUP_12Rnd_MLRS_HE"]]]] call _fnc_saveToTemplate; @@ -64,6 +67,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Arid.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Arid.sqf index 3f75db2f46..3a79c545b8 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Arid.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_nM1025_Unarmed_USMC_DES", "CUP_B_nM1025_Unarmed_DF_USMC_DES", "CUP_B_nM1038_DF_USMC_DES", "CUP_B_nM1038_USMC_DES", "CUP_B_nM1038_4s_USMC_DES", "CUP_B_nM1038_4s_DF_USMC_DES", "CUP_B_M1151_DSRT_USMC", "CUP_B_M1152_DSRT_USMC"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_nM1025_M2_USMC_DES", "CUP_B_nM1025_M2_DF_USMC_DES", "CUP_B_nM1025_M240_USMC_DES", "CUP_B_nM1025_M240_DF_USMC_DES", "CUP_B_nM1025_Mk19_USMC_DES", "CUP_B_nM1025_Mk19_DF_USMC_DES", "CUP_B_nM1025_SOV_M2_USMC_DES", "CUP_B_nM1025_SOV_Mk19_USMC_DES", "CUP_B_nM1036_TOW_USMC_DES", "CUP_B_nM1036_TOW_DF_USMC_DES", "CUP_B_M1151_M2_DSRT_USMC", "CUP_B_M1151_Deploy_DSRT_USMC", "CUP_B_M1151_Mk19_DSRT_USMC", "CUP_B_M1165_GMV_DSRT_USMC", "CUP_B_M1167_DSRT_USMC", "CUP_B_RG31_Mk19_USMC", "CUP_B_RG31E_M2_USMC", "CUP_B_RG31_M2_USMC", "CUP_B_RG31_M2_GC_USMC"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_nM1025_M2_USMC_DES", "CUP_B_nM1025_M2_DF_USMC_DES", "CUP_B_nM1025_M240_USMC_DES", "CUP_B_nM1025_M240_DF_USMC_DES", "CUP_B_nM1025_Mk19_USMC_DES", "CUP_B_nM1025_Mk19_DF_USMC_DES", "CUP_B_nM1025_SOV_M2_USMC_DES", "CUP_B_nM1025_SOV_Mk19_USMC_DES", "CUP_B_nM1036_TOW_USMC_DES", "CUP_B_nM1036_TOW_DF_USMC_DES", "CUP_B_M1151_M2_DSRT_USMC", "CUP_B_M1151_Deploy_DSRT_USMC", "CUP_B_M1151_Mk19_DSRT_USMC", "CUP_B_M1165_GMV_DSRT_USMC", "CUP_B_M1167_DSRT_USMC"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_USMC"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["B_Truck_01_flatbed_F"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_nM1038_Ammo_USMC_DES", "CUP_B_nM1038_Ammo_DF_USMC_DES", "CUP_B_MTVR_Ammo_USMC"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_MTVR_Repair_USMC", "CUP_B_nM1038_Repair_USMC_DES", "CUP_B_nM1038_Repair_DF_USMC_DES"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USMC"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["CUP_B_nM997_DF_USMC_DES", "CUP_B_nM997_USMC_DES"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_AAV_Unarmed_USMC", "CUP_B_AAV_USMC", "CUP_B_AAV_USMC_TTS", "CUP_B_LAV25_desert_USMC", "CUP_B_LAV25_HQ_desert_USMC", "CUP_B_LAV25M240_desert_USMC"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_M113A3_desert_USA", "CUP_B_M113A3_desert_USA", "CUP_B_RG31E_M2_USMC", "CUP_B_RG31_Mk19_USMC", "CUP_B_RG31_M2_USMC", "CUP_B_RG31_M2_GC_USMC"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_AAV_USMC", "CUP_B_AAV_USMC_TTS", "CUP_B_LAV25_desert_USMC", "CUP_B_LAV25M240_desert_USMC"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_M1A1FEP_Desert_USMC", "CUP_B_M1A1FEP_TUSK_Desert_USMC"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_nM1097_AVENGER_USMC_DES"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["CUP_B_MH6M_USA", "CUP_B_MH6J_USA", "CUP_B_UH1Y_UNA_USMC"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_MH60S_Unarmed_USN", "CUP_MH60S_Unarmed_FFV_USN", "CUP_B_MH60S_USMC", "CUP_B_UH60S_USN", "CUP_B_CH53E_USMC", "CUP_B_MH60L_DAP_2x_USN"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_B_AH1Z_Dynamic_USMC", "CUP_B_MH60L_DAP_4x_USN", "CUP_B_UH1Y_Gunship_Dynamic_USMC"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_MH60L_DAP_4x_USN", "CUP_B_UH1Y_Gunship_Dynamic_USMC"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH1Z_Dynamic_USMC"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_DPICM_USA","CUP_B_M270_HE_USA"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -67,6 +70,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Temperate.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Temperate.sqf index fe4e041f56..95173b68e9 100644 --- a/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_AI_US_Marine_Temperate.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["CUP_B_nM1025_Unarmed_USMC_WDL", "CUP_B_nM1025_Unarmed_DF_USMC_WDL", "CUP_B_nM1038_USMC_WDL", "CUP_B_nM1038_DF_USMC_WDL", "CUP_B_nM1038_4s_USMC_WDL", "CUP_B_nM1038_4s_DF_USMC_WDL", "CUP_B_M1151_USMC", "CUP_B_M1152_USMC"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["CUP_B_nM1025_M2_USMC_WDL", "CUP_B_nM1025_M2_DF_USMC_WDL", "CUP_B_nM1025_M240_USMC_WDL", "CUP_B_nM1025_M240_DF_USMC_WDL", "CUP_B_nM1025_Mk19_USMC_WDL", "CUP_B_nM1025_Mk19_DF_USMC_WDL", "CUP_B_nM1025_SOV_M2_USMC_WDL", "CUP_B_nM1025_SOV_Mk19_USMC_WDL", "CUP_B_nM1036_TOW_USMC_WDL", "CUP_B_nM1036_TOW_DF_USMC_WDL", "CUP_B_M1151_M2_USMC", "CUP_B_M1151_Deploy_USMC", "CUP_B_M1151_Mk19_USMC", "CUP_B_M1165_GMV_USMC", "CUP_B_M1167_USMC", "CUP_B_RG31_Mk19_OD_USMC", "CUP_B_RG31E_M2_OD_USMC", "CUP_B_RG31_M2_OD_USMC", "CUP_B_RG31_M2_OD_GC_USMC"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["CUP_B_nM1025_M2_USMC_WDL", "CUP_B_nM1025_M2_DF_USMC_WDL", "CUP_B_nM1025_M240_USMC_WDL", "CUP_B_nM1025_M240_DF_USMC_WDL", "CUP_B_nM1025_Mk19_USMC_WDL", "CUP_B_nM1025_Mk19_DF_USMC_WDL", "CUP_B_nM1025_SOV_M2_USMC_WDL", "CUP_B_nM1025_SOV_Mk19_USMC_WDL", "CUP_B_nM1036_TOW_USMC_WDL", "CUP_B_nM1036_TOW_DF_USMC_WDL", "CUP_B_M1151_M2_USMC", "CUP_B_M1151_Deploy_USMC", "CUP_B_M1151_Mk19_USMC", "CUP_B_M1165_GMV_USMC", "CUP_B_M1167_USMC"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["CUP_B_MTVR_USMC"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["B_Truck_01_flatbed_F"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["CUP_B_MTVR_Ammo_USMC", "CUP_B_nM1038_Ammo_USMC_WDL", "CUP_B_nM1038_Ammo_DF_USMC_WDL"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["CUP_B_MTVR_Repair_USMC", "CUP_B_nM1038_Repair_USMC_WDL", "CUP_B_nM1038_Repair_DF_USMC_WDL"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["CUP_B_MTVR_Refuel_USMC"]] call _fnc_saveToTemplate; ["vehiclesMedical", []] call _fnc_saveToTemplate; -["vehiclesAPCs", ["CUP_B_AAV_Unarmed_USMC", "CUP_B_AAV_USMC", "CUP_B_AAV_USMC_TTS", "CUP_B_LAV25_USMC", "CUP_B_LAV25M240_USMC", "CUP_B_LAV25_HQ_green"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["CUP_B_M113A3_olive_USA", "CUP_B_M113A3_olive_USA", "CUP_B_RG31E_M2_OD_USMC", "CUP_B_RG31_Mk19_OD_USMC", "CUP_B_RG31_M2_OD_USMC", "CUP_B_RG31_M2_OD_GC_USMC"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["CUP_B_AAV_USMC", "CUP_B_AAV_USMC_TTS", "CUP_B_LAV25_USMC", "CUP_B_LAV25M240_USMC"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["CUP_B_M1A1FEP_Woodland_USMC", "CUP_B_M1A1EP_TUSK_Woodland_USMC", "CUP_B_M60A3_USMC", "CUP_B_M60A3_TTS_USMC"]] call _fnc_saveToTemplate; ["vehiclesAA", ["CUP_B_nM1097_AVENGER_USMC_WDL"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["CUP_B_MH6M_USA", "CUP_B_MH6J_USA", "CUP_B_UH1Y_UNA_USMC"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["CUP_MH60S_Unarmed_USN", "CUP_MH60S_Unarmed_FFV_USN", "CUP_B_MH60S_USMC", "CUP_B_UH60S_USN", "CUP_B_CH53E_USMC", "CUP_B_MH60L_DAP_2x_USN"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["CUP_B_AH1Z_Dynamic_USMC", "CUP_B_MH60L_DAP_4x_USN", "CUP_B_UH1Y_Gunship_Dynamic_USMC"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["CUP_B_MH60L_DAP_4x_USN", "CUP_B_UH1Y_Gunship_Dynamic_USMC"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["CUP_B_AH1Z_Dynamic_USMC"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["CUP_B_M270_HE_USMC","CUP_B_M270_DPICM_USMC"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -67,6 +70,8 @@ ["minefieldAT", ["CUP_Mine"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["APERSMine"]] call _fnc_saveToTemplate; +#include "CUP_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/CUP/CUP_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/CUP/CUP_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..a8515538fd --- /dev/null +++ b/A3A/addons/core/Templates/Templates/CUP/CUP_Vehicle_Attributes.sqf @@ -0,0 +1,46 @@ +["attributesVehicles", [ + + // Weak AA vehicles. Leave threat because they're still dangerous in rebel hands + ["CUP_B_nM1097_AVENGER_USA_DES", ["cost", 70]], + ["CUP_B_nM1097_AVENGER_USA_WDL", ["cost", 70]], + ["CUP_B_M163_Vulcan_USA", ["cost", 100]], + ["CUP_I_M163_Vulcan_RACS", ["cost", 100]], + + // IFVs with bonus armour + ["CUP_B_FV510_GB_D_SLAT", ["cost", 170]], + ["CUP_B_FV510_GB_W_SLAT", ["cost", 170]], + ["CUP_B_MCV80_GB_D_SLAT", ["cost", 170]], + ["CUP_B_MCV80_GB_W_SLAT", ["cost", 170]], + ["CUP_B_M2A3Bradley_USA_D", ["cost", 180], ["threat", 230]], + ["CUP_B_M2A3Bradley_USA_W", ["cost", 180], ["threat", 230]], // also has TOW + + // BMPs a bit better than APC but not Bradley level + ["CUP_O_BMP3_RU", ["cost", 120], ["threat", 150]], + ["CUP_O_BMP2_RU", ["cost", 120], ["threat", 150]], + ["CUP_O_BMP2_SLA", ["cost", 120], ["threat", 150]], + ["CUP_O_BMP2_TKA", ["cost", 120], ["threat", 150]], + ["CUP_B_BMP2_CZ", ["cost", 120], ["threat", 150]], + ["CUP_B_BMP2_CZ_Des", ["cost", 120], ["threat", 150]], + ["CUP_B_BMP2_CDF", ["cost", 120], ["threat", 150]], + + // This one is quite strong by light-armed standards + ["CUP_O_GAZ_Vodnik_BPPU_RU", ["cost", 75], ["threat", 120]], + + // Tank destroyer strykers, not tough + ["CUP_B_M1128_MGS_Woodland", ["cost", 120], ["threat", 180]], + ["CUP_B_M1128_MGS_Desert", ["cost", 120], ["threat", 180]], + + // Trash planes + ["CUP_B_L39_CZ", ["cost", 150]], + ["CUP_O_L39_TK", ["cost", 150]], + + // Attack helis +// ["CUP_O_UH1H_armed_TKA", ["cost", 100]], // few rockets plus door PKs +// ["CUP_I_AH6J_RACS", ["cost", 100]], // few rockets plus fixed miniguns +// ["CUP_O_Ka50_SLA", ["cost", 250]], // rockets & missiles but fixed cannon +// ["CUP_O_Ka50_RU", ["cost", 250]], +// ["CUP_O_Ka52_RU", ["cost", 250]], + ["CUP_B_AH64D_DL_USA", ["cost", 350]] // better than the russian stuff +// ["CUP_B_AH1Z_Dynamic_USMC", ["cost", 300]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/FactionDefaults/EnemyDefaults.sqf b/A3A/addons/core/Templates/Templates/FactionDefaults/EnemyDefaults.sqf index 42e47bf44e..e59ce169df 100644 --- a/A3A/addons/core/Templates/Templates/FactionDefaults/EnemyDefaults.sqf +++ b/A3A/addons/core/Templates/Templates/FactionDefaults/EnemyDefaults.sqf @@ -10,3 +10,5 @@ ["placeIntel_desk", ["Land_CampingTable_F",0]] call _fnc_saveToTemplate; // [classname,azimuth]. ["placeIntel_itemMedium", ["Land_Document_01_F",-155,false]] call _fnc_saveToTemplate; // [classname,azimuth,isComputer]. ["placeIntel_itemLarge", ["Land_Laptop_unfolded_F",-25,true]] call _fnc_saveToTemplate; // [classname,azimuth,isComputer]. + +["attributesVehicles", []] call _fnc_saveToTemplate; \ No newline at end of file diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Arid.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Arid.sqf index cb06abbec2..fbcc722d89 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Arid.sqf @@ -19,16 +19,18 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhs_tigr_msv", "rhs_tigr_m_msv"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["rhs_tigr_sts_msv", "rhsgref_BRDM2_HQ_msv", "rhsgref_BRDM2_msv"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhs_tigr_sts_msv", "rhs_tigr_sts_msv", "RHS_Ural_Zu23_VMF_01"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["rhs_gaz66_msv", "rhs_gaz66o_msv", "rhs_kamaz5350_open_msv", "rhs_kamaz5350_msv"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhs_gaz66_flat_msv", "rhs_gaz66o_flat_msv", "rhs_kamaz5350_flatbed_cover_msv", "rhs_kamaz5350_flatbed_msv"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhs_gaz66_ammo_msv"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhs_gaz66_repair_msv"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["RHS_Ural_Fuel_MSV_01"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhs_gaz66_ap2_msv"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhs_btr80_msv", "rhs_btr80a_msv", "rhs_bmp3m_msv", "rhs_btr80_vdv", "rhs_bmp2d_msv", "rhs_bmp2k_msv"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsgref_BRDM2_HQ_msv", "rhsgref_BRDM2_msv", "rhs_btr80_msv", "rhs_btr80a_msv", "rhs_btr80_vdv"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["rhs_bmp3m_msv", "rhs_bmp2d_msv", "rhs_bmp2k_msv"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhs_t90sm_tv", "rhs_t80uk", "rhs_t72be_tv", "rhs_t72bd_tv", "rhs_t72bd_tv", "rhs_t72be_tv", "rhs_t72bc_tv"]] call _fnc_saveToTemplate; -["vehiclesAA", ["rhs_zsu234_aa", "RHS_Ural_Zu23_VMF_01"]] call _fnc_saveToTemplate; +["vehiclesAA", ["rhs_zsu234_aa"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["O_G_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["rhsusf_mkvsoc"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["rhs_ka60_c"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_Mi8AMT_vdv", "RHS_Mi8mt_vdv", "RHS_Mi8T_vdv"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["rhsgref_mi24g_CAS", "RHS_Mi24P_vvsc", "RHS_Mi24V_vvsc", "rhs_mi28n_vvs", "RHS_Ka52_vvs", "RHS_Mi8MTV3_vdv", "RHS_Mi8mtv3_Cargo_vdv", "RHS_Mi8MTV3_heavy_vdv"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_Mi8MTV3_vdv", "RHS_Mi8MTV3_heavy_vdv", "RHS_Mi24P_vvsc"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["rhsgref_mi24g_CAS", "RHS_Mi24V_vvsc", "rhs_mi28n_vvs", "RHS_Ka52_vvs"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhs_2s1_tv", "rhs_2s3_tv", "RHS_BM21_VV_01"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhs_mine_tm62m"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhs_mine_pmn2"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Temperate.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Temperate.sqf index 978155c664..6d390fa9db 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_AFRF_Temperate.sqf @@ -19,16 +19,17 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhs_tigr_msv", "rhs_tigr_m_msv"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["rhs_tigr_sts_msv", "rhsgref_BRDM2_HQ_msv", "rhsgref_BRDM2_msv"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhs_tigr_sts_msv", "rhs_tigr_sts_msv", "RHS_Ural_Zu23_VMF_01"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["rhs_gaz66_msv", "rhs_gaz66o_msv", "rhs_kamaz5350_open_msv", "rhs_kamaz5350_msv"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhs_gaz66_flat_msv", "rhs_gaz66o_flat_msv", "rhs_kamaz5350_flatbed_cover_msv", "rhs_kamaz5350_flatbed_msv"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhs_gaz66_ammo_msv"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhs_gaz66_repair_msv"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["RHS_Ural_Fuel_MSV_01"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhs_gaz66_ap2_msv"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhs_btr80_msv", "rhs_btr80a_msv", "rhs_bmp3m_msv", "rhs_btr80_vdv", "rhs_bmp2d_msv", "rhs_bmp2k_msv"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsgref_BRDM2_HQ_msv", "rhsgref_BRDM2_msv", "rhs_btr80_msv", "rhs_btr80a_msv", "rhs_btr80_vdv"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["rhs_bmp3m_msv", "rhs_bmp2d_msv", "rhs_bmp2k_msv"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhs_t90sm_tv", "rhs_t80uk", "rhs_t72be_tv", "rhs_t72bd_tv", "rhs_t72bd_tv", "rhs_t72be_tv", "rhs_t72bc_tv"]] call _fnc_saveToTemplate; -["vehiclesAA", ["rhs_zsu234_aa", "RHS_Ural_Zu23_VMF_01"]] call _fnc_saveToTemplate; +["vehiclesAA", ["rhs_zsu234_aa"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["O_G_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["rhsusf_mkvsoc"]] call _fnc_saveToTemplate; @@ -40,7 +41,8 @@ ["vehiclesHelisLight", ["rhs_ka60_c"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_Mi8AMT_vdv", "RHS_Mi8mt_vdv", "RHS_Mi8T_vdv"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["rhsgref_mi24g_CAS", "RHS_Mi24P_vvsc", "RHS_Mi24V_vvsc", "rhs_mi28n_vvs", "RHS_Ka52_vvs", "RHS_Mi8MTV3_vdv", "RHS_Mi8mtv3_Cargo_vdv", "RHS_Mi8MTV3_heavy_vdv"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_Mi8MTV3_vdv", "RHS_Mi8MTV3_heavy_vdv", "RHS_Mi24P_vvsc"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["rhsgref_mi24g_CAS", "RHS_Mi24V_vvsc", "rhs_mi28n_vvs", "RHS_Ka52_vvs"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhs_2s1_tv", "rhs_2s3_tv", "RHS_BM21_VV_01"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +73,8 @@ ["minefieldAT", ["rhs_mine_tm62m"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhs_mine_pmn2"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_CDF.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_CDF.sqf index f324cabc3a..01d540e7ce 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_CDF.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_CDF.sqf @@ -19,16 +19,17 @@ ["vehiclesBasic", ["I_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsgref_cdf_b_reg_uaz", "rhsgref_cdf_b_reg_uaz_open", "rhsgref_BRDM2UM_b"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["rhsgref_cdf_b_reg_uaz_ags", "rhsgref_cdf_b_reg_uaz_dshkm", "rhsgref_BRDM2_b", "rhsgref_BRDM2_ATGM_b", "rhsgref_BRDM2_HQ_b"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsgref_cdf_b_reg_uaz_ags", "rhsgref_cdf_b_reg_uaz_dshkm", "rhsgref_cdf_b_ural_Zu23", "rhsgref_cdf_b_gaz66_zu23"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["rhsgref_cdf_b_gaz66", "rhsgref_cdf_b_gaz66_flat", "rhsgref_cdf_b_gaz66o", "rhsgref_cdf_b_gaz66o_flat", "rhsgref_cdf_b_ural", "rhsgref_cdf_b_ural_open", "rhsgref_cdf_b_zil131", "rhsgref_cdf_b_zil131_flatbed_cover", "rhsgref_cdf_b_zil131_open", "rhsgref_cdf_b_zil131_flatbed"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsgref_cdf_b_gaz66", "rhsgref_cdf_b_gaz66_flat", "rhsgref_cdf_b_gaz66o", "rhsgref_cdf_b_gaz66o_flat", "rhsgref_cdf_b_ural", "rhsgref_cdf_b_ural_open", "rhsgref_cdf_b_zil131", "rhsgref_cdf_b_zil131_flatbed_cover", "rhsgref_cdf_b_zil131_open", "rhsgref_cdf_b_zil131_flatbed"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsgref_cdf_b_gaz66_ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsgref_cdf_b_gaz66_repair", "rhsgref_cdf_b_ural_repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsgref_cdf_b_ural_fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsgref_cdf_b_gaz66_ap2"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsgref_cdf_b_btr60", "rhsgref_cdf_b_btr70", "rhsgref_cdf_b_btr80", "rhsgref_cdf_b_bmd1", "rhsgref_cdf_b_bmd1k", "rhsgref_cdf_b_bmd1p", "rhsgref_cdf_b_bmd1pk", "rhsgref_cdf_b_bmd2", "rhsgref_cdf_b_bmd2k", "rhsgref_cdf_b_bmp1", "rhsgref_cdf_b_bmp1d", "rhsgref_cdf_b_bmp1k", "rhsgref_cdf_b_bmp1p", "rhsgref_cdf_b_bmp2e", "rhsgref_cdf_b_bmp2", "rhsgref_cdf_b_bmp2d", "rhsgref_cdf_b_bmp2k"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsgref_cdf_b_btr60", "rhsgref_cdf_b_btr70", "rhsgref_cdf_b_btr80", "rhsgref_BRDM2_b", "rhsgref_BRDM2_ATGM_b", "rhsgref_BRDM2_HQ_b"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["rhsgref_cdf_b_bmd1", "rhsgref_cdf_b_bmd1k", "rhsgref_cdf_b_bmd1p", "rhsgref_cdf_b_bmd1pk", "rhsgref_cdf_b_bmd2", "rhsgref_cdf_b_bmd2k", "rhsgref_cdf_b_bmp1", "rhsgref_cdf_b_bmp1d", "rhsgref_cdf_b_bmp1k", "rhsgref_cdf_b_bmp1p", "rhsgref_cdf_b_bmp2e", "rhsgref_cdf_b_bmp2", "rhsgref_cdf_b_bmp2d", "rhsgref_cdf_b_bmp2k"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsgref_cdf_b_t72ba_tv", "rhsgref_cdf_b_t72bb_tv", "rhsgref_cdf_b_t80b_tv", "rhsgref_cdf_b_t80bv_tv"]] call _fnc_saveToTemplate; -["vehiclesAA", ["rhsgref_cdf_b_ural_Zu23", "rhsgref_cdf_b_gaz66_zu23", "rhsgref_cdf_b_zsu234"]] call _fnc_saveToTemplate; +["vehiclesAA", ["rhsgref_cdf_b_zsu234"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["rhsusf_mkvsoc"]] call _fnc_saveToTemplate; @@ -40,7 +41,8 @@ ["vehiclesHelisLight", ["rhsgref_cdf_reg_Mi8amt"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["rhsgref_cdf_reg_Mi8amt"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["rhsgref_cdf_b_Mi24D", "rhsgref_cdf_b_Mi24D_Early", "rhsgref_b_mi24g_CAS", "rhsgref_cdf_b_Mi35", "rhsgref_cdf_b_reg_Mi17Sh"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["rhsgref_cdf_b_reg_Mi17Sh"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["rhsgref_cdf_b_Mi24D", "rhsgref_cdf_b_Mi24D_Early", "rhsgref_b_mi24g_CAS", "rhsgref_cdf_b_Mi35"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsgref_cdf_b_2s1", "rhsgref_cdf_b_reg_d30", "rhsgref_cdf_b_reg_BM21"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +73,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arctic.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arctic.sqf index 4a39138fa4..9e387bdbce 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arctic.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arctic.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsusf_M1239_socom_wd", "rhsusf_M1238A1_socom_wd", "rhsusf_m1025_w", "rhsusf_m1043_w", "rhsusf_m998_w_2dr_fulltop", "rhsusf_m998_w_2dr_halftop", "rhsusf_m998_w_2dr", "rhsusf_m998_w_4dr_fulltop", "rhsusf_m998_w_4dr_halftop", "rhsusf_m998_w_4dr", "rhsusf_m1151_usarmy_wd", "rhsusf_m1165_usarmy_wd", "rhsusf_M1220_usarmy_wd", "rhsusf_M1232_usarmy_wd", "rhsusf_m1240a1_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_m2", "rhsusf_m1043_w_m2", "rhsusf_m1045_w", "rhsusf_m1151_m2crows_usarmy_wd", "rhsusf_m1151_m2_v1_usarmy_wd", "rhsusf_m1151_m2_lras3_v1_usarmy_wd", "rhsusf_m1151_m240_v1_usarmy_wd", "rhsusf_m1151_m2_v2_usarmy_wd", "rhsusf_m1151_m240_v2_usarmy_wd", "rhsusf_m966_w", "rhsusf_M1220_M153_M2_usarmy_wd", "rhsusf_M1220_M2_usarmy_wd", "rhsusf_M1230_M2_usarmy_wd", "rhsusf_M1232_M2_usarmy_wd", "rhsusf_M1237_M2_usarmy_wd", "rhsusf_m1240a1_m2_usarmy_wd", "rhsusf_m1240a1_m240_usarmy_wd", "rhsusf_m1240a1_mk19_usarmy_wd", "rhsusf_m1240a1_m2_uik_usarmy_wd", "rhsusf_m1240a1_m240_uik_usarmy_wd", "rhsusf_m1240a1_mk19_uik_usarmy_wd", "rhsusf_m1240a1_m2crows_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_m2", "rhsusf_m1043_w_m2", "rhsusf_m1045_w", "rhsusf_m1151_m2crows_usarmy_wd", "rhsusf_m1151_m2_v1_usarmy_wd", "rhsusf_m1151_m2_lras3_v1_usarmy_wd", "rhsusf_m1151_m240_v1_usarmy_wd", "rhsusf_m1151_m2_v2_usarmy_wd", "rhsusf_m1151_m240_v2_usarmy_wd", "rhsusf_m966_w", "rhsusf_m1240a1_m2_usarmy_wd", "rhsusf_m1240a1_m240_usarmy_wd", "rhsusf_m1240a1_mk19_usarmy_wd", "rhsusf_m1240a1_m2_uik_usarmy_wd", "rhsusf_m1240a1_m240_uik_usarmy_wd", "rhsusf_m1240a1_mk19_uik_usarmy_wd", "rhsusf_m1240a1_m2crows_usarmy_wd"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsusf_M1084A1R_SOV_M2_WD_fmtv_socom", "rhsusf_M1078A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1084A1P2_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M977A4_usarmy_wd", "rhsusf_M977A4_BKIT_usarmy_wd", "rhsusf_M977A4_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsusf_M977A4_AMMO_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsusf_M977A4_REPAIR_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_M2_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsusf_M978A4_usarmy_wd", "rhsusf_M978A4_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsusf_m113_usarmy_medical", "rhsusf_M1230a1_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsusf_M1117_W", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "RHS_M2A2_wd", "RHS_M2A2_BUSKI_WD", "RHS_M2A3_wd", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsusf_M1117_W", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "rhsusf_M1220_M153_M2_usarmy_wd", "rhsusf_M1220_M153_MK19_usarmy_wd", "rhsusf_M1220_M2_usarmy_wd", "rhsusf_M1230_M2_usarmy_wd", "rhsusf_M1232_M2_usarmy_wd", "rhsusf_M1237_M2_usarmy_wd", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["RHS_M2A2_wd", "RHS_M2A3_wd", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["RHS_M2A2_BUSKI_WD", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1aim_tuski_wd","rhsusf_m1a1aimwd_usarmy","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep1tuskiwd_usarmy","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["RHS_MELB_MH6M"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_UH60M", "RHS_UH60M", "RHS_UH60M", "RHS_UH60M", "RHS_UH60M_ESSS2", "RHS_UH60M2", "RHS_CH_47F", "RHS_CH_47F", "RHS_CH_47F", "RHS_CH_47F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H", "RHS_AH64D_wd", "RHS_AH64D_wd_CS", "RHS_AH64D_wd_AA", "RHS_AH64D_wd_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["RHS_AH64D_wd", "RHS_AH64D_wd_CS", "RHS_AH64D_wd_AA", "RHS_AH64D_wd_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy", "rhsusf_M142_usarmy_WD", "RHS_M119_WD"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arid.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arid.sqf index 95c2bdff8e..6b7e6600c2 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Arid.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsusf_M1239_socom_d", "rhsusf_M1238A1_socom_d", "rhsusf_m1025_d", "rhsusf_m1043_d", "rhsusf_m998_d_2dr_fulltop", "rhsusf_m998_d_2dr_halftop", "rhsusf_m998_d_2dr", "rhsusf_m998_d_4dr_fulltop", "rhsusf_m998_d_4dr_halftop", "rhsusf_m998_d_4dr", "rhsusf_m1151_usarmy_d", "rhsusf_m1165_usarmy_d", "rhsusf_M1220_usarmy_d", "rhsusf_M1232_usarmy_d", "rhsusf_m1240a1_usarmy_d"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_d", "rhsusf_M1078A1R_SOV_M2_D_fmtv_socom", "rhsusf_m1025_d_m2", "rhsusf_m1043_d_m2", "rhsusf_m1045_d", "rhsusf_m1151_m2crows_usarmy_d", "rhsusf_m1151_m2_v1_usarmy_d", "rhsusf_m1151_m2_lras3_v1_usarmy_d", "rhsusf_m1151_m240_v1_usarmy_d", "rhsusf_m1151_m2_v2_usarmy_d", "rhsusf_m1151_m240_v2_usarmy_d", "rhsusf_m966_d", "rhsusf_M1220_M153_M2_usarmy_d", "rhsusf_M1220_M2_usarmy_d", "rhsusf_M1230_M2_usarmy_d", "rhsusf_M1232_M2_usarmy_d", "rhsusf_M1237_M2_usarmy_d", "rhsusf_m1240a1_m2_usarmy_d", "rhsusf_m1240a1_m240_usarmy_d", "rhsusf_m1240a1_mk19_usarmy_d", "rhsusf_m1240a1_m2_uik_usarmy_d", "rhsusf_m1240a1_m240_uik_usarmy_d", "rhsusf_m1240a1_mk19_uik_usarmy_d", "rhsusf_m1240a1_m2crows_usarmy_d"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["rhsusf_M1078A1P2_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M1083A1P2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_d", "rhsusf_M1078A1R_SOV_M2_D_fmtv_socom", "rhsusf_m1025_d_m2", "rhsusf_m1043_d_m2", "rhsusf_m1045_d", "rhsusf_m1151_m2crows_usarmy_d", "rhsusf_m1151_m2_v1_usarmy_d", "rhsusf_m1151_m2_lras3_v1_usarmy_d", "rhsusf_m1151_m240_v1_usarmy_d", "rhsusf_m1151_m2_v2_usarmy_d", "rhsusf_m1151_m240_v2_usarmy_d", "rhsusf_m966_d", "rhsusf_m1240a1_m2_usarmy_d", "rhsusf_m1240a1_m240_usarmy_d", "rhsusf_m1240a1_mk19_usarmy_d", "rhsusf_m1240a1_m2_uik_usarmy_d", "rhsusf_m1240a1_m240_uik_usarmy_d", "rhsusf_m1240a1_mk19_uik_usarmy_d", "rhsusf_m1240a1_m2crows_usarmy_d"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["rhsusf_M1078A1P2_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_fmtv_usarmy", "rhsusf_M1083A1P2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsusf_M1084A1R_SOV_M2_D_fmtv_socom", "rhsusf_M1078A1P2_D_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_flatbed_fmtv_usarmy", "rhsusf_M1084A1P2_D_fmtv_usarmy", "rhsusf_M1084A1P2_B_D_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M977A4_usarmy_d", "rhsusf_M977A4_BKIT_usarmy_d", "rhsusf_M977A4_BKIT_M2_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsusf_M977A4_AMMO_usarmy_d", "rhsusf_M977A4_AMMO_BKIT_usarmy_d", "rhsusf_M977A4_AMMO_BKIT_M2_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsusf_M977A4_REPAIR_usarmy_d", "rhsusf_M977A4_REPAIR_BKIT_M2_usarmy_d", "rhsusf_M977A4_REPAIR_BKIT_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsusf_M978A4_usarmy_d", "rhsusf_M978A4_BKIT_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsusf_m113d_usarmy_medical", "rhsusf_M1230a1_usarmy_d"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsusf_M1117_D", "rhsusf_stryker_m1126_m2_d", "rhsusf_stryker_m1126_mk19_d", "rhsusf_stryker_m1127_m2_d", "rhsusf_stryker_m1132_m2_np_d", "rhsusf_m113d_usarmy", "rhsusf_m113d_usarmy_M240", "rhsusf_m113d_usarmy_MK19", "RHS_M2A2", "RHS_M2A2_BUSKI", "RHS_M2A3", "RHS_M2A3_BUSKI", "RHS_M2A3_BUSKIII"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsusf_M1117_D", "rhsusf_m113d_usarmy", "rhsusf_m113d_usarmy_M240", "rhsusf_m113d_usarmy_MK19", "rhsusf_M1220_M153_M2_usarmy_d", "rhsusf_M1220_M153_MK19_usarmy_d", "rhsusf_M1220_M2_usarmy_d", "rhsusf_M1230_M2_usarmy_d", "rhsusf_M1232_M2_usarmy_d", "rhsusf_M1237_M2_usarmy_d", "rhsusf_M1078A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["rhsusf_stryker_m1126_m2_d", "rhsusf_stryker_m1126_mk19_d", "rhsusf_stryker_m1127_m2_d", "rhsusf_stryker_m1132_m2_np_d", "RHS_M2A2", "RHS_M2A3"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["RHS_M2A2_BUSKI", "RHS_M2A3_BUSKI", "RHS_M2A3_BUSKIII"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1aim_tuski_d","rhsusf_m1a1aimd_usarmy","rhsusf_m1a2sep1d_usarmy","rhsusf_m1a2sep1tuskid_usarmy","rhsusf_m1a2sep1tuskiid_usarmy","rhsusf_m1a2sep2d_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["RHS_MELB_MH6M"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_UH60M_d", "RHS_UH60M_d", "RHS_UH60M_d", "RHS_UH60M_d", "RHS_UH60M_d", "RHS_UH60M_d", "RHS_UH60M_ESSS2_d", "RHS_UH60M2_d", "RHS_CH_47F_light", "RHS_CH_47F_light", "RHS_CH_47F_light", "RHS_CH_47F_light"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H", "RHS_AH64D", "RHS_AH64D_CS", "RHS_AH64D_AA", "RHS_AH64D_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["RHS_AH64D", "RHS_AH64D_CS", "RHS_AH64D_AA", "RHS_AH64D_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy", "rhsusf_M142_usarmy_D", "RHS_M119_D"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Temperate.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Temperate.sqf index dbaf0b62cb..adbd127e7a 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Army_Temperate.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsusf_M1239_socom_wd", "rhsusf_M1238A1_socom_wd", "rhsusf_m1025_w", "rhsusf_m1043_w", "rhsusf_m998_w_2dr_fulltop", "rhsusf_m998_w_2dr_halftop", "rhsusf_m998_w_2dr", "rhsusf_m998_w_4dr_fulltop", "rhsusf_m998_w_4dr_halftop", "rhsusf_m998_w_4dr", "rhsusf_m1151_usarmy_wd", "rhsusf_m1165_usarmy_wd", "rhsusf_M1220_usarmy_wd", "rhsusf_M1232_usarmy_wd", "rhsusf_m1240a1_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_m2", "rhsusf_m1043_w_m2", "rhsusf_m1045_w", "rhsusf_m1151_m2crows_usarmy_wd", "rhsusf_m1151_m2_v1_usarmy_wd", "rhsusf_m1151_m2_lras3_v1_usarmy_wd", "rhsusf_m1151_m240_v1_usarmy_wd", "rhsusf_m1151_m2_v2_usarmy_wd", "rhsusf_m1151_m240_v2_usarmy_wd", "rhsusf_m966_w", "rhsusf_M1220_M153_M2_usarmy_wd", "rhsusf_M1220_M2_usarmy_wd", "rhsusf_M1230_M2_usarmy_wd", "rhsusf_M1232_M2_usarmy_wd", "rhsusf_M1237_M2_usarmy_wd", "rhsusf_m1240a1_m2_usarmy_wd", "rhsusf_m1240a1_m240_usarmy_wd", "rhsusf_m1240a1_mk19_usarmy_wd", "rhsusf_m1240a1_m2_uik_usarmy_wd", "rhsusf_m1240a1_m240_uik_usarmy_wd", "rhsusf_m1240a1_mk19_uik_usarmy_wd", "rhsusf_m1240a1_m2crows_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_m2", "rhsusf_m1043_w_m2", "rhsusf_m1045_w", "rhsusf_m1151_m2crows_usarmy_wd", "rhsusf_m1151_m2_v1_usarmy_wd", "rhsusf_m1151_m2_lras3_v1_usarmy_wd", "rhsusf_m1151_m240_v1_usarmy_wd", "rhsusf_m1151_m2_v2_usarmy_wd", "rhsusf_m1151_m240_v2_usarmy_wd", "rhsusf_m966_w", "rhsusf_m1240a1_m2_usarmy_wd", "rhsusf_m1240a1_m240_usarmy_wd", "rhsusf_m1240a1_mk19_usarmy_wd", "rhsusf_m1240a1_m2_uik_usarmy_wd", "rhsusf_m1240a1_m240_uik_usarmy_wd", "rhsusf_m1240a1_mk19_uik_usarmy_wd", "rhsusf_m1240a1_m2crows_usarmy_wd"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsusf_M1084A1R_SOV_M2_WD_fmtv_socom", "rhsusf_M1078A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1084A1P2_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M977A4_usarmy_wd", "rhsusf_M977A4_BKIT_usarmy_wd", "rhsusf_M977A4_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsusf_M977A4_AMMO_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsusf_M977A4_REPAIR_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_M2_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsusf_M978A4_usarmy_wd", "rhsusf_M978A4_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsusf_m113_usarmy_medical", "rhsusf_M1230a1_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsusf_M1117_W", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "RHS_M2A2_wd", "RHS_M2A2_BUSKI_WD", "RHS_M2A3_wd", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsusf_M1117_W", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "rhsusf_M1220_M153_M2_usarmy_wd", "rhsusf_M1220_M153_MK19_usarmy_wd", "rhsusf_M1220_M2_usarmy_wd", "rhsusf_M1230_M2_usarmy_wd", "rhsusf_M1232_M2_usarmy_wd", "rhsusf_M1237_M2_usarmy_wd", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["RHS_M2A2_wd", "RHS_M2A3_wd", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["RHS_M2A2_BUSKI_WD", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1aim_tuski_wd","rhsusf_m1a1aimwd_usarmy","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep1tuskiwd_usarmy","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["RHS_MELB_MH6M"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_UH60M", "RHS_UH60M", "RHS_UH60M", "RHS_UH60M", "RHS_UH60M_ESSS2", "RHS_UH60M2", "RHS_CH_47F", "RHS_CH_47F", "RHS_CH_47F", "RHS_CH_47F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H", "RHS_AH64D_wd", "RHS_AH64D_wd_CS", "RHS_AH64D_wd_AA", "RHS_AH64D_wd_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_MELB_AH6M", "RHS_MELB_AH6M_M", "RHS_MELB_AH6M_H"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["RHS_AH64D_wd", "RHS_AH64D_wd_CS", "RHS_AH64D_wd_AA", "RHS_AH64D_wd_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy", "rhsusf_M142_usarmy_WD", "RHS_M119_WD"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Arid.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Arid.sqf index 043000e1dd..d34498f9ec 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Arid.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsusf_M1239_socom_d", "rhsusf_M1238A1_socom_d", "rhsusf_m1025_d_s", "rhsusf_m1043_d_s", "rhsusf_m998_d_s_2dr_fulltop", "rhsusf_m998_d_s_2dr_halftop", "rhsusf_m998_d_s_2dr", "rhsusf_m998_d_s_4dr_fulltop", "rhsusf_m998_d_s_4dr_halftop", "rhsusf_m998_d_s_4dr", "rhsusf_m1151_usmc_d", "rhsusf_m1165_usmc_d", "rhsusf_m1240a1_usmc_d"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_d", "rhsusf_M1078A1R_SOV_M2_D_fmtv_socom", "rhsusf_m1025_d_s_m2", "rhsusf_m1043_d_s_m2", "rhsusf_m1045_d", "rhsusf_m1151_m2crows_usmc_d", "rhsusf_m1151_m2_v3_usmc_d", "rhsusf_m1151_m240_v3_usmc_d", "rhsusf_m1151_m2_v3_usmc_d", "rhsusf_m1151_m240_v3_usmc_d", "rhsusf_M1232_MC_M2_usmc_d", "rhsusf_m1240a1_m2_usmc_d", "rhsusf_m1240a1_m240_usmc_d", "rhsusf_m1240a1_mk19_usmc_d", "rhsusf_m1240a1_m2crows_usmc_d"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["rhsusf_M1078A1P2_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M1083A1P2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_d", "rhsusf_M1078A1R_SOV_M2_D_fmtv_socom", "rhsusf_m1025_d_s_m2", "rhsusf_m1043_d_s_m2", "rhsusf_m1045_d", "rhsusf_m1151_m2crows_usmc_d", "rhsusf_m1151_m2_v3_usmc_d", "rhsusf_m1151_m240_v3_usmc_d", "rhsusf_m1151_m2_v3_usmc_d", "rhsusf_m1151_m240_v3_usmc_d", "rhsusf_m1240a1_m2_usmc_d", "rhsusf_m1240a1_m240_usmc_d", "rhsusf_m1240a1_mk19_usmc_d", "rhsusf_m1240a1_m2crows_usmc_d"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["rhsusf_M1078A1P2_D_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_fmtv_usarmy", "rhsusf_M1083A1P2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsusf_M1084A1R_SOV_M2_D_fmtv_socom", "rhsusf_M1078A1P2_D_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_D_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_D_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_flatbed_fmtv_usarmy", "rhsusf_M1084A1P2_D_fmtv_usarmy", "rhsusf_M1084A1P2_B_D_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M977A4_usarmy_d", "rhsusf_M977A4_BKIT_usarmy_d", "rhsusf_M977A4_BKIT_M2_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsusf_M977A4_AMMO_usarmy_d", "rhsusf_M977A4_AMMO_BKIT_usarmy_d", "rhsusf_M977A4_AMMO_BKIT_M2_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsusf_M977A4_REPAIR_usarmy_d", "rhsusf_M977A4_REPAIR_BKIT_M2_usarmy_d", "rhsusf_M977A4_REPAIR_BKIT_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsusf_M978A4_usarmy_d", "rhsusf_M978A4_BKIT_usarmy_d"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsusf_m113d_usarmy_medical", "rhsusf_M1230a1_usarmy_d"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsusf_M1117_D", "rhsusf_stryker_m1126_m2_d", "rhsusf_stryker_m1126_mk19_d", "rhsusf_stryker_m1127_m2_d", "rhsusf_stryker_m1132_m2_np_d", "rhsusf_m113d_usarmy", "rhsusf_m113d_usarmy_M240", "rhsusf_m113d_usarmy_MK19", "RHS_M2A2", "RHS_M2A2_BUSKI", "RHS_M2A3", "RHS_M2A3_BUSKI", "RHS_M2A3_BUSKIII"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsusf_M1117_D", "rhsusf_m113d_usarmy", "rhsusf_m113d_usarmy_M240", "rhsusf_m113d_usarmy_MK19", "rhsusf_M1232_MC_M2_usmc_d", "rhsusf_M1232_MC_M2_usmc_d", "rhsusf_M1232_MC_MK19_usmc_d", "rhsusf_M1078A1P2_B_M2_D_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_D_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["rhsusf_stryker_m1126_m2_d", "rhsusf_stryker_m1126_mk19_d", "rhsusf_stryker_m1127_m2_d", "rhsusf_stryker_m1132_m2_np_d", "RHS_M2A2", "RHS_M2A3"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["RHS_M2A2_BUSKI", "RHS_M2A3_BUSKI", "RHS_M2A3_BUSKIII"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_d","rhsusf_m1a2sep1d_usarmy","rhsusf_m1a2sep1tuskiid_usarmy","rhsusf_m1a2sep2d_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ ["vehiclesPlanesTransport", ["RHS_C130J"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["RHS_UH1Y_UNARMED_d"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["RHS_UH1Y_UNARMED_d", "RHS_CH_47F_light", "rhsusf_CH53E_USMC_GAU21_D", "rhsusf_CH53E_USMC_D"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["RHS_AH1Z", "RHS_AH1Z_CS", "RHS_AH1Z_GS", "RHS_UH1Y_d", "RHS_UH1Y_FFAR_d", "RHS_UH1Y_d_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["RHS_CH_47F_light", "rhsusf_CH53E_USMC_GAU21_D", "rhsusf_CH53E_USMC_D"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_UH1Y_d", "RHS_UH1Y_d_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["RHS_AH1Z", "RHS_AH1Z_CS", "RHS_AH1Z_GS"]] call _fnc_saveToTemplate; // "RHS_UH1Y_FFAR_d" ["vehiclesArtillery", ["rhsusf_m109_usarmy", "rhsusf_M142_usarmy_D", "RHS_M119_D"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Temperate.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Temperate.sqf index aed60120e2..5e0a277f9d 100644 --- a/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_AI_USAF_Marines_Temperate.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["B_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["rhsusf_M1239_socom_wd", "rhsusf_M1238A1_socom_wd", "rhsusf_m1025_w_s", "rhsusf_m1043_w_s", "rhsusf_m998_w_s_2dr_fulltop", "rhsusf_m998_w_s_2dr_halftop", "rhsusf_m998_w_s_2dr", "rhsusf_m998_w_s_4dr_fulltop", "rhsusf_m998_w_s_4dr_halftop", "rhsusf_m998_w_s_4dr", "rhsusf_m1151_usmc_wd", "rhsusf_m1165_usmc_wd", "rhsusf_m1240a1_usmc_wd"]] call _fnc_saveToTemplate; -["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_s_m2", "rhsusf_m1043_w_s_m2", "rhsusf_m1045_w_s", "rhsusf_m1151_m2crows_usmc_wd", "rhsusf_m1151_m2_v3_usmc_wd", "rhsusf_m1151_m240_v3_usmc_wd", "rhsusf_m1151_m2_v3_usmc_wd", "rhsusf_m1151_m240_v3_usmc_wd", "rhsusf_M1232_MC_M2_usmc_wd", "rhsusf_m1240a1_m2_usmc_wd", "rhsusf_m1240a1_m240_usmc_wd", "rhsusf_m1240a1_mk19_usmc_wd", "rhsusf_m1240a1_m2crows_usmc_wd"]] call _fnc_saveToTemplate; -["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesLightArmed", ["rhsusf_m1245_m2crows_socom_deploy", "rhsusf_M1078A1R_SOV_M2_WD_fmtv_socom", "rhsusf_m1025_w_s_m2", "rhsusf_m1043_w_s_m2", "rhsusf_m1045_w_s", "rhsusf_m1151_m2crows_usmc_wd", "rhsusf_m1151_m2_v3_usmc_wd", "rhsusf_m1151_m240_v3_usmc_wd", "rhsusf_m1151_m2_v3_usmc_wd", "rhsusf_m1151_m240_v3_usmc_wd", "rhsusf_m1240a1_m2_usmc_wd", "rhsusf_m1240a1_m240_usmc_wd", "rhsusf_m1240a1_mk19_usmc_wd", "rhsusf_m1240a1_m2crows_usmc_wd"]] call _fnc_saveToTemplate; +["vehiclesTrucks", ["rhsusf_M1078A1P2_WD_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_fmtv_usarmy", "rhsusf_M1083A1P2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["rhsusf_M1084A1R_SOV_M2_WD_fmtv_socom", "rhsusf_M1078A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1078A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_WD_flatbed_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_flatbed_fmtv_usarmy", "rhsusf_M1084A1P2_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_WD_fmtv_usarmy", "rhsusf_M1084A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M977A4_usarmy_wd", "rhsusf_M977A4_BKIT_usarmy_wd", "rhsusf_M977A4_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["rhsusf_M977A4_AMMO_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_usarmy_wd", "rhsusf_M977A4_AMMO_BKIT_M2_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["rhsusf_M977A4_REPAIR_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_M2_usarmy_wd", "rhsusf_M977A4_REPAIR_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["rhsusf_M978A4_usarmy_wd", "rhsusf_M978A4_BKIT_usarmy_wd"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["rhsusf_m113_usarmy_medical", "rhsusf_M1230a1_usarmy_wd"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["rhsusf_M1117_W", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "RHS_M2A2_wd", "RHS_M2A2_BUSKI_WD", "RHS_M2A3_wd", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["rhsusf_M1117_W", "rhsusf_m113_usarmy", "rhsusf_m113_usarmy_M240", "rhsusf_m113_usarmy_MK19", "rhsusf_M1232_MC_M2_usmc_wd", "rhsusf_M1232_MC_M2_usmc_wd", "rhsusf_M1232_MC_MK19_usmc_wd", "rhsusf_M1078A1P2_B_M2_WD_fmtv_usarmy", "rhsusf_M1083A1P2_B_M2_WD_fmtv_usarmy"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["RHS_M2A2_wd", "RHS_M2A3_wd", "rhsusf_stryker_m1126_m2_wd", "rhsusf_stryker_m1126_mk19_wd", "rhsusf_stryker_m1127_m2_wd", "rhsusf_stryker_m1132_m2_np_wd"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["RHS_M2A2_BUSKI_WD", "RHS_M2A3_BUSKI_wd", "RHS_M2A3_BUSKIII_wd"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["rhsusf_m1a1fep_wd","rhsusf_m1a2sep1tuskiiwd_usarmy","rhsusf_m1a2sep1wd_usarmy","rhsusf_m1a2sep2wd_usarmy"]] call _fnc_saveToTemplate; ["vehiclesAA", ["RHS_M6_wd"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ ["vehiclesHelisLight", ["RHS_UH1Y_UNARMED"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["RHS_UH1Y_UNARMED", "RHS_CH_47F", "rhsusf_CH53E_USMC_GAU21", "rhsusf_CH53E_USMC"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["RHS_AH1Z_wd", "RHS_AH1Z_wd_CS", "RHS_AH1Z_wd_GS", "RHS_UH1Y", "RHS_UH1Y_FFAR", "RHS_UH1Y_GS"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["RHS_UH1Y", "RHS_UH1Y_GS"]] call _fnc_saveToTemplate; // "RHS_UH1Y_FFAR" weaker version +["vehiclesHelisAttack", ["RHS_AH1Z_wd", "RHS_AH1Z_wd_CS", "RHS_AH1Z_wd_GS"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["rhsusf_m109_usarmy", "rhsusf_M142_usarmy_WD", "RHS_M119_WD"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -71,6 +74,8 @@ ["minefieldAT", ["rhsusf_mine_M19"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["rhsusf_mine_m14"]] call _fnc_saveToTemplate; +#include "RHS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/RHS/RHS_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/RHS/RHS_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..142989ceac --- /dev/null +++ b/A3A/addons/core/Templates/Templates/RHS/RHS_Vehicle_Attributes.sqf @@ -0,0 +1,29 @@ +["attributesVehicles", [ + // Light helis + ["RHS_MELB_AH6M_H", ["cost", 150]], // has 2x Hellfire + + // Bradleys +// ["RHS_M2A2", ["cost", 130], ["threat", 200]], +// ["RHS_M2A3", ["cost", 130], ["threat", 200]], + ["RHS_M2A2_BUSKI", ["cost", 180], ["threat", 250]], + ["RHS_M2A3_BUSKI", ["cost", 180], ["threat", 250]], + ["RHS_M2A3_BUSKIII", ["cost", 200], ["threat", 300]], + + // woodland camo +// ["RHS_M2A2_wd", ["cost", 130], ["threat", 200]], +// ["RHS_M2A3_wd", ["cost", 130], ["threat", 200]], + ["RHS_M2A2_BUSKI_WD", ["cost", 180], ["threat", 250]], + ["RHS_M2A3_BUSKI_wd", ["cost", 180], ["threat", 250]], + ["RHS_M2A3_BUSKIII_wd", ["cost", 200], ["threat", 300]], + + // CDF trash planes + ["rhs_l159_cdf_b_CDF", ["cost", 150]], + ["rhs_l159_cdf_b_CDF_CAP", ["cost", 150]], + + // Apaches +// ["RHS_AH64D_GS", ["cost", 300]], // no hellfires + ["RHS_AH64D", ["cost", 350]], + ["RHS_AH64D_CS", ["cost", 350]], + ["RHS_AH64D_AA", ["cost", 350]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/UNS/UNS_AI_NVA.sqf b/A3A/addons/core/Templates/Templates/UNS/UNS_AI_NVA.sqf index e2128d1d0b..038b24bc14 100644 --- a/A3A/addons/core/Templates/Templates/UNS/UNS_AI_NVA.sqf +++ b/A3A/addons/core/Templates/Templates/UNS/UNS_AI_NVA.sqf @@ -13,22 +13,26 @@ // Vehicles // ////////////////////////// +["attributeLowAir", true] call _fnc_saveToTemplate; // Use fewer air units in general + ["ammobox", "B_supplyCrate_F"] call _fnc_saveToTemplate; ["surrenderCrate", "Box_IND_Wps_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["equipmentBox", "Box_NATO_Equip_F"] call _fnc_saveToTemplate; //Changeing this from default will require you to define logistics attachement offset for the box type ["vehiclesBasic", ["uns_willys"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["uns_Type55"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["uns_Type55_LMG", "uns_Type55_MG", "uns_Type55_patrol", "uns_Type55_twinMG", "uns_Type55_RR57", "uns_Type55_RR73", "uns_Type55_M40", "uns_nvatruck_mg"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["uns_Type55_LMG", "uns_Type55_MG", "uns_Type55_patrol", "uns_Type55_twinMG", "uns_Type55_RR57", "uns_Type55_RR73", "uns_Type55_M40", "uns_BTR152_DSHK", "uns_Type55_ZU", "uns_nvatruck_zpu", "uns_nvatruck_zu23", "uns_nvatruck_s60"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["uns_nvatruck_open", "uns_zil157", "uns_nvatruck_camo", "uns_nvatruck"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", ["uns_nvatruck_open", "uns_zil157"]] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["uns_nvatruck_reammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["uns_nvatruck_repair", "uns_zil157_repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["uns_nvatruck_refuel", "uns_Zil157_refuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["uns_Type63_amb"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["uns_BTR152_DSHK", "uns_Type63_mg", "uns_pt76", "uns_ot34_85_nva"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["uns_nvatruck_mg", "uns_Type63_mg"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["uns_Type63_mg", "uns_pt76", "uns_ot34_85_nva"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["uns_pt76"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["uns_t54_nva", "uns_t55_nva", "uns_to55_nva"]] call _fnc_saveToTemplate; -["vehiclesAA", ["uns_ZSU23_NVA", "uns_ZSU57_NVA", "uns_Type55_ZU", "uns_nvatruck_zpu", "uns_nvatruck_zu23", "uns_nvatruck_s60"]] call _fnc_saveToTemplate; +["vehiclesAA", ["uns_ZSU23_NVA", "uns_ZSU57_NVA"]] call _fnc_saveToTemplate; ["vehiclesTransportBoats", ["UNS_Zodiac_NVA"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["UNS_PATROL_BOAT_NVA", "UNS_ASSAULT_BOAT_NVA"]] call _fnc_saveToTemplate; @@ -40,6 +44,7 @@ ["vehiclesHelisLight", ["uns_Mi8T_VPAF"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["uns_Mi8TV_VPAF_MG"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", []] call _fnc_saveToTemplate; ["vehiclesHelisAttack", []] call _fnc_saveToTemplate; ["vehiclesArtillery", ["uns_m110sp", "Uns_D20_artillery", "Uns_D30_artillery"]] call _fnc_saveToTemplate; @@ -72,6 +77,8 @@ ["minefieldAT", ["uns_mine_t59"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["uns_mine_md82"]] call _fnc_saveToTemplate; +#include "UNS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/UNS/UNS_AI_US.sqf b/A3A/addons/core/Templates/Templates/UNS/UNS_AI_US.sqf index 3ac07a0257..7351b55540 100644 --- a/A3A/addons/core/Templates/Templates/UNS/UNS_AI_US.sqf +++ b/A3A/addons/core/Templates/Templates/UNS/UNS_AI_US.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["uns_M35A2_repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["uns_M35A2_fueltanker", "uns_M35A2_fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["uns_M577_amb"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["uns_xm706e2", "uns_xm706e1", "uns_M113_XM182", "uns_M113_M60", "uns_M113_M134", "uns_M113A1_M2", "uns_M113_30cal", "uns_M113_transport"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["uns_xm706e2", "uns_xm706e1", "uns_M113_XM182", "uns_M113_M134", "uns_M113_30cal", "uns_M113_M2"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["uns_M113A1_XM182", "uns_M113A1_M60", "uns_M113A1_M134", "uns_M113A1_M2", "uns_M113A1_M40", "uns_M132"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["uns_m48a3", "uns_m551", "uns_M67A"]] call _fnc_saveToTemplate; ["vehiclesAA", ["uns_m163"]] call _fnc_saveToTemplate; @@ -38,9 +40,11 @@ ["vehiclesPlanesAA", ["uns_F4E_CAP", "uns_f100b_CAP"]] call _fnc_saveToTemplate; ["vehiclesPlanesTransport", ["uns_c1a5cargo", "uns_C130_H"]] call _fnc_saveToTemplate; -["vehiclesHelisLight", ["uns_H13_transport_Army", "uns_H13_gunship_Army", "uns_oh6_transport", "uns_oh6_m27"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["uns_UH1D_m60", "uns_UH1D_m60_light", "uns_UH1H_m60", "uns_UH1H_m60_light", "uns_h21c_mg", "uns_ch47_m60_army", "uns_hh53b_m134_usaf"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["UNS_AH1G_SUU11", "UNS_AH1G_M195", "UNS_AH1G_M200", "UNS_AH1G", "uns_UH1C_M21_M200", "uns_UH1C_M21_M158", "UNS_UH1C_M3_ARA", "UNS_UH1B_TOW", "uns_UH1C_M6_M200_1AC"]] call _fnc_saveToTemplate; +// First these three are all three-seaters. Not worth the heli? +["vehiclesHelisLight", ["uns_H13_transport_Army", "uns_oh6_transport", "uns_oh6_m27", "uns_UH1D_m60_light", "uns_UH1H_m60_light"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["uns_UH1D_m60_light", "uns_UH1H_m60_light", "uns_UH1D_m60", "uns_UH1H_m60", "uns_h21c_mg", "uns_ch47_m60_army", "uns_hh53b_m134_usaf"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["uns_UH1C_M21_M200", "uns_UH1C_M21_M158", "UNS_UH1C_M3_ARA", "uns_UH1C_M6_M200_1AC"]] call _fnc_saveToTemplate; // "UNS_UH1B_TOW" no other weapons +["vehiclesHelisAttack", ["UNS_AH1G_SUU11", "UNS_AH1G_M195", "UNS_AH1G_M200", "UNS_AH1G"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["uns_m110sp", "uns_m107sp", "uns_M113_M30"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -72,6 +76,8 @@ ["minefieldAT", ["uns_mine_tm57"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["uns_mine_m16"]] call _fnc_saveToTemplate; +#include "UNS_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/UNS/UNS_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/UNS/UNS_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..fe0e379f41 --- /dev/null +++ b/A3A/addons/core/Templates/Templates/UNS/UNS_Vehicle_Attributes.sqf @@ -0,0 +1,20 @@ +["attributesVehicles", [ + + // Filling out higher types + ["uns_nvatruck_mg", ["cost", 40]], + ["uns_Type63_mg", ["cost", 60]], + + // Golf buggies? + ["uns_m274_m40", ["cost", 20]], + ["uns_m274_m60", ["cost", 20]], + + // Super shitty 3-cargo light helis + ["uns_H13_transport_Army", ["cost", 40]], + ["uns_oh6_transport", ["cost", 40]], + ["uns_oh6_m27", ["cost", 40]], + + // No missiles on these, otherwise not actually terrible + ["uns_A1J_CAS", ["cost", 200]], + ["uns_Mig21_CAS", ["cost", 200]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/VN/VN_AI_MACV.sqf b/A3A/addons/core/Templates/Templates/VN/VN_AI_MACV.sqf index 4638b3180c..3399650c9f 100644 --- a/A3A/addons/core/Templates/Templates/VN/VN_AI_MACV.sqf +++ b/A3A/addons/core/Templates/Templates/VN/VN_AI_MACV.sqf @@ -31,14 +31,16 @@ ["vehiclesBasic", ["vn_b_wheeled_m151_01"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["vn_b_wheeled_m151_01", "vn_b_wheeled_m151_02"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["vn_b_wheeled_m151_mg_02", "vn_b_wheeled_m151_mg_03", "vn_b_wheeled_m151_mg_04", "vn_b_wheeled_m151_mg_05"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["vn_b_wheeled_m151_mg_02", "vn_b_wheeled_m151_mg_03", "vn_b_wheeled_m151_mg_04", "vn_b_wheeled_m151_mg_05", "vn_b_wheeled_m54_mg_02"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["vn_b_wheeled_m54_01", "vn_b_wheeled_m54_02"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["vn_b_wheeled_m54_ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["vn_b_wheeled_m54_repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["vn_b_wheeled_m54_fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", []] call _fnc_saveToTemplate; -["vehiclesAPCs", ["vn_b_wheeled_m54_mg_03", "vn_b_wheeled_m54_mg_01", "vn_b_armor_m113_acav_04", "vn_b_armor_m113_acav_02", "vn_b_armor_m113_acav_01", "vn_b_armor_m113_acav_06", "vn_b_armor_m113_acav_03", "vn_b_armor_m113_acav_05", "vn_b_armor_m113_01"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["vn_b_wheeled_m54_mg_03", "vn_b_wheeled_m54_mg_01", "vn_b_armor_m113_01"]] call _fnc_saveToTemplate; +["vehiclesAPCs", ["vn_b_armor_m113_acav_04", "vn_b_armor_m113_acav_02", "vn_b_armor_m113_acav_01", "vn_b_armor_m113_acav_06", "vn_b_armor_m113_acav_03", "vn_b_armor_m113_acav_05"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["vn_b_armor_m41_01_02"]] call _fnc_saveToTemplate; ["vehiclesAA", ["vn_b_wheeled_m54_mg_02"]] call _fnc_saveToTemplate; @@ -52,14 +54,15 @@ ["vehiclesHelisLight", ["vn_b_air_ch34_01_01"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["vn_b_air_uh1c_07_01", "vn_b_air_uh1d_02_01", "vn_b_air_ch34_01_01", "vn_b_air_ch34_03_01"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["vn_b_air_ah1g_02", "vn_b_air_ah1g_03", "vn_b_air_ah1g_04", "vn_b_air_uh1c_01_01", "vn_b_air_uh1c_02_01", "vn_b_air_uh1c_03_01"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["vn_b_air_uh1c_01_01", "vn_b_air_uh1c_02_01", "vn_b_air_uh1c_03_01"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["vn_b_air_ah1g_02", "vn_b_air_ah1g_03", "vn_b_air_ah1g_04", "vn_b_air_ah1g_07", "vn_b_air_ah1g_08", "vn_b_air_ah1g_09"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["vn_b_army_static_m101_02"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ ["vn_b_army_static_m101_02", ["vn_cannon_m101_mag_he_x8", "vn_cannon_m101_mag_ab_x8", "vn_cannon_m101_mag_wp_x8"]] ]] call _fnc_saveToTemplate; -["uavsAttack", []] call _fnc_saveToTemplate; +["uavsAttack", ["vn_b_air_oh6a_01"]] call _fnc_saveToTemplate; // scout helis are fine for this ["uavsPortable", []] call _fnc_saveToTemplate; //Config special vehicles @@ -69,7 +72,7 @@ ["vehiclesPolice", ["vn_b_wheeled_m151_02_mp"]] call _fnc_saveToTemplate; -["staticMGs", ["vn_b_army_static_m2_high", "vn_b_army_static_m60_high", "vn_b_army_static_m1919a4_high"]] call _fnc_saveToTemplate; +["staticMGs", ["vn_b_army_static_m2_high", "vn_b_army_static_m2_high", "vn_b_army_static_m60_high", "vn_b_army_static_m1919a4_high"]] call _fnc_saveToTemplate; ["staticAT", ["vn_b_army_static_tow", "vn_b_army_static_m40a1rr"]] call _fnc_saveToTemplate; ["staticAA", ["vn_b_army_static_m45", "vn_b_navy_static_l70mk2", "vn_b_navy_static_l60mk3"]] call _fnc_saveToTemplate; ["staticMortars", ["vn_b_army_static_mortar_m2"]] call _fnc_saveToTemplate; @@ -82,6 +85,8 @@ ["minefieldAT", ["vn_mine_m15"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["vn_mine_m14"]] call _fnc_saveToTemplate; +#include "VN_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/VN/VN_AI_PAVN.sqf b/A3A/addons/core/Templates/Templates/VN/VN_AI_PAVN.sqf index 69515e3e62..f69d6510de 100644 --- a/A3A/addons/core/Templates/Templates/VN/VN_AI_PAVN.sqf +++ b/A3A/addons/core/Templates/Templates/VN/VN_AI_PAVN.sqf @@ -29,16 +29,20 @@ // Vehicles // ////////////////////////// +["attributeLowAir", true] call _fnc_saveToTemplate; // Use fewer air units in general + ["vehiclesBasic", ["vn_o_bicycle_01"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["vn_o_wheeled_btr40_01"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["vn_o_wheeled_btr40_mg_02", "vn_o_wheeled_btr40_mg_01"]] call _fnc_saveToTemplate; +["vehiclesLightArmed",["vn_o_wheeled_btr40_mg_02", "vn_o_wheeled_btr40_mg_01", "vn_o_wheeled_btr40_mg_03", "vn_o_wheeled_z157_mg_02", "vn_o_wheeled_z157_mg_01"]] call _fnc_saveToTemplate; ["vehiclesTrucks", ["vn_o_wheeled_z157_01", "vn_o_wheeled_z157_02"]] call _fnc_saveToTemplate; ["vehiclesCargoTrucks", []] call _fnc_saveToTemplate; ["vehiclesAmmoTrucks", ["vn_o_wheeled_z157_ammo"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["vn_o_wheeled_z157_repair"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["vn_o_wheeled_z157_fuel"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["vn_o_wheeled_btr40_02"]] call _fnc_saveToTemplate; -["vehiclesAPCs", ["vn_o_armor_m113_acav_01","vn_o_armor_m113_acav_03","vn_o_armor_m113_01"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", ["vn_o_wheeled_z157_01", "vn_o_wheeled_z157_02", "vn_o_armor_m113_01"]] call _fnc_saveToTemplate; // Fill out with trucks to make the tier scaling look more plausible +["vehiclesAPCs", ["vn_o_wheeled_z157_01", "vn_o_wheeled_z157_02", "vn_o_armor_m113_acav_01","vn_o_armor_m113_acav_03"]] call _fnc_saveToTemplate; +["vehiclesIFVs", ["vn_o_armor_pt76a_01","vn_o_armor_pt76b_01","vn_o_armor_type63_01"]] call _fnc_saveToTemplate; ["vehiclesTanks", ["vn_o_armor_m41_01","vn_o_armor_pt76a_01","vn_o_armor_pt76b_01","vn_o_armor_type63_01"]] call _fnc_saveToTemplate; ["vehiclesAA", ["vn_o_wheeled_btr40_mg_03", "vn_o_wheeled_z157_mg_02"]] call _fnc_saveToTemplate; @@ -52,7 +56,8 @@ ["vehiclesHelisLight", ["vn_o_air_mi2_01_03"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["vn_o_air_mi2_01_03"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["vn_o_air_mi2_04_02", "vn_o_air_mi2_05_04"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["vn_o_air_mi2_04_02", "vn_o_air_mi2_04_03", "vn_o_air_mi2_05_04"]] call _fnc_saveToTemplate; // Don't actually work atm +["vehiclesHelisAttack", []] call _fnc_saveToTemplate; ["vehiclesArtillery", ["vn_o_vc_static_mortar_type53", "vn_o_nva_static_h12", "vn_o_nva_static_d44_01"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -84,6 +89,8 @@ ["minefieldAT", ["vn_mine_tripwire_arty"]] call _fnc_saveToTemplate; ["minefieldAPERS", ["vn_mine_punji_02"]] call _fnc_saveToTemplate; +#include "VN_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/VN/VN_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/VN/VN_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..d118a01948 --- /dev/null +++ b/A3A/addons/core/Templates/Templates/VN/VN_Vehicle_Attributes.sqf @@ -0,0 +1,22 @@ +["attributesVehicles", [ + + // In AA arrays but really light-armed + ["vn_b_wheeled_m54_mg_02", ["cost", 60], ["threat", 80]], + ["vn_o_wheeled_btr40_mg_03", ["cost", 60], ["threat", 80]], + ["vn_o_wheeled_z157_mg_02", ["cost", 60], ["threat", 80]], + + // Filling out APC arrays but they're just trucks + ["vn_o_wheeled_z157_01", ["cost", 20], ["threat", 0]], + ["vn_o_wheeled_z157_02", ["cost", 20], ["threat", 0]], + + // Filling out attack helis, but closer to light attack + ["vn_o_air_mi2_04_02", ["cost", 130]], + ["vn_o_air_mi2_04_04", ["cost", 130]], + + // These are probably not super effective + ["vn_o_air_mig19_at", ["cost", 150]], + ["vn_o_air_mig19_cap", ["cost", 200]], + ["vn_b_air_f100d_at", ["cost", 150]], + ["vn_b_air_f100d_cap", ["cost", 200]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_AAF.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_AAF.sqf index b511c01bd2..ff71e420d3 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_AAF.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_AAF.sqf @@ -19,14 +19,16 @@ ["vehiclesBasic", ["I_Quadbike_01_F"]] call _fnc_saveToTemplate; ["vehiclesLightUnarmed", ["I_MRAP_03_F"]] call _fnc_saveToTemplate; -["vehiclesLightArmed",["I_MRAP_03_hmg_F", "I_MRAP_03_gmg_F"]] call _fnc_saveToTemplate; +private _lightArmed = ["I_MRAP_03_hmg_F", "I_MRAP_03_gmg_F"]; ["vehiclesTrucks", ["I_Truck_02_transport_F", "I_Truck_02_covered_F"]] call _fnc_saveToTemplate; private _cargoTrucks = ["I_Truck_02_transport_F", "I_Truck_02_covered_F"]; ["vehiclesAmmoTrucks", ["I_Truck_02_ammo_F"]] call _fnc_saveToTemplate; ["vehiclesRepairTrucks", ["I_Truck_02_box_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["I_Truck_02_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["I_Truck_02_medical_F"]] call _fnc_saveToTemplate; -private _APCs = ["I_APC_tracked_03_cannon_F", "I_APC_Wheeled_03_cannon_F"]; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; +["vehiclesAPCs", ["I_APC_tracked_03_cannon_F", "I_APC_Wheeled_03_cannon_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["I_MBT_03_cannon_F"]] call _fnc_saveToTemplate; private _AA = ["I_LT_01_AA_F"]; @@ -39,8 +41,9 @@ private _AA = ["I_LT_01_AA_F"]; ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["I_Heli_light_03_unarmed_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["I_Heli_light_03_unarmed_F", "I_Heli_Transport_02_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["I_Heli_light_03_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["I_Heli_Transport_02_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["I_Heli_light_03_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["B_Heli_Attack_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["I_Truck_02_MRL_F", "B_MBT_01_arty_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -72,7 +75,8 @@ private _AA = ["I_LT_01_AA_F"]; //If Tank DLC if (allowDLCTanks) then { - _APCs append ["I_LT_01_AT_F", "I_LT_01_cannon_F"]; + // No seats so can't be APC + _lightArmed append ["I_LT_01_AT_F", "I_LT_01_cannon_F"]; }; //If Western Sahara DLC if (allowDLCWS && A3A_hasWS) then { @@ -80,9 +84,11 @@ if (allowDLCWS && A3A_hasWS) then { _AA append ["I_A_Truck_02_aa_lxWS"]; }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; -["vehiclesAPCs", _APCs] call _fnc_saveToTemplate; +["vehiclesLightArmed", _lightArmed] call _fnc_saveToTemplate; ["vehiclesAA", _AA] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Apex.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Apex.sqf index 9892233cec..862f624b9f 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Apex.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Apex.sqf @@ -26,7 +26,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F","O_T_Truck_02_F","O_T_Truck_0 ["vehiclesRepairTrucks", ["O_T_Truck_02_Box_F","O_T_Truck_03_repair_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["O_T_Truck_02_fuel_F","O_T_Truck_03_fuel_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["O_T_Truck_03_medical_ghex_F","O_T_Truck_02_Medical_F"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; ["vehiclesAPCs", ["O_T_APC_Tracked_02_cannon_ghex_F","O_T_APC_Wheeled_02_rcws_v2_ghex_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["O_T_MBT_02_cannon_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["O_T_APC_Tracked_02_AA_ghex_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F","O_T_Truck_02_F","O_T_Truck_0 ["vehiclesPlanesTransport", ["O_T_VTOL_02_infantry_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["O_Heli_Light_02_unarmed_F","O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F", "O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["O_T_MBT_02_arty_ghex_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -75,6 +78,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Arid.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Arid.sqf index 1836d65850..d693831224 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Arid.sqf @@ -26,7 +26,9 @@ private _cargoTrucks = ["O_Truck_02_transport_F", "O_Truck_02_covered_F", "O_Tru ["vehiclesRepairTrucks", ["O_Truck_02_box_F", "O_Truck_03_repair_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["O_Truck_03_fuel_F", "O_Truck_02_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["O_Truck_02_medical_F", "O_Truck_03_medical_F"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; ["vehiclesAPCs", ["O_APC_Tracked_02_cannon_F", "O_APC_Wheeled_02_rcws_v2_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["O_MBT_02_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["O_APC_Tracked_02_AA_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ private _cargoTrucks = ["O_Truck_02_transport_F", "O_Truck_02_covered_F", "O_Tru ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["O_Heli_Light_02_unarmed_F", "O_Heli_Transport_04_covered_F", "O_Heli_Transport_04_bench_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["O_Heli_Attack_02_dynamicLoadout_F", "O_Heli_Light_02_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["O_Heli_Transport_04_covered_F", "O_Heli_Transport_04_bench_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["O_Heli_Light_02_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["O_Heli_Attack_02_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["O_MBT_02_arty_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -74,6 +77,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Enoch.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Enoch.sqf index f0202030cd..d0d16e3d88 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Enoch.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Enoch.sqf @@ -26,7 +26,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F", "O_T_Truck_02_F", "O_T_Truck ["vehiclesRepairTrucks", ["O_T_Truck_02_Box_F","O_T_Truck_03_repair_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["O_T_Truck_02_fuel_F","O_T_Truck_03_fuel_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["O_T_Truck_03_medical_ghex_F","O_T_Truck_02_Medical_F"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; ["vehiclesAPCs", ["O_T_APC_Tracked_02_cannon_ghex_F","O_T_APC_Wheeled_02_rcws_v2_ghex_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["O_T_MBT_02_cannon_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["O_T_APC_Tracked_02_AA_ghex_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F", "O_T_Truck_02_F", "O_T_Truck ["vehiclesPlanesTransport", []] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["O_Heli_Light_02_unarmed_F","O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F", "O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["O_T_MBT_02_arty_ghex_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -75,6 +78,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Temperate.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Temperate.sqf index b9cd9fa279..b2a04429e2 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_CSAT_Temperate.sqf @@ -26,7 +26,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F", "O_T_Truck_02_F", "O_T_Truck ["vehiclesRepairTrucks", ["O_T_Truck_02_Box_F","O_T_Truck_03_repair_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["O_T_Truck_02_fuel_F","O_T_Truck_03_fuel_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["O_T_Truck_03_medical_ghex_F","O_T_Truck_02_Medical_F"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; ["vehiclesAPCs", ["O_T_APC_Tracked_02_cannon_ghex_F","O_T_APC_Wheeled_02_rcws_v2_ghex_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["O_T_MBT_02_cannon_ghex_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["O_T_APC_Tracked_02_AA_ghex_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ private _cargoTrucks = ["O_T_Truck_02_transport_F", "O_T_Truck_02_F", "O_T_Truck ["vehiclesPlanesTransport", ["O_T_VTOL_02_infantry_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["O_Heli_Light_02_unarmed_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["O_Heli_Light_02_unarmed_F","O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F", "O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["O_Heli_Transport_04_bench_black_F","O_Heli_Transport_04_covered_black_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["O_Heli_Light_02_dynamicLoadout_F", "O_Heli_Light_02_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["O_Heli_Attack_02_black_F", "O_Heli_Attack_02_dynamicLoadout_black_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["O_T_MBT_02_arty_ghex_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -75,6 +78,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_LDF.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_LDF.sqf index 82f4c8b65c..89809bdcbc 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_LDF.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_LDF.sqf @@ -26,7 +26,9 @@ private _cargoTrucks = ["I_E_Truck_02_transport_F", "I_E_Truck_02_F"]; ["vehiclesRepairTrucks", ["I_E_Truck_02_Box_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["I_E_Truck_02_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["I_E_Truck_02_Medical_F"]] call _fnc_saveToTemplate; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; ["vehiclesAPCs", ["I_E_APC_tracked_03_cannon_F", "B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F"]] call _fnc_saveToTemplate; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["B_T_MBT_01_TUSK_F", "B_T_MBT_01_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["B_T_APC_Tracked_01_AA_F"]] call _fnc_saveToTemplate; @@ -39,8 +41,9 @@ private _cargoTrucks = ["I_E_Truck_02_transport_F", "I_E_Truck_02_F"]; ["vehiclesPlanesTransport", ["B_T_VTOL_01_infantry_F"]] call _fnc_saveToTemplate; ["vehiclesHelisLight", ["I_E_Heli_light_03_unarmed_F", "B_Heli_Light_01_F"]] call _fnc_saveToTemplate; -["vehiclesHelisTransport", ["I_E_Heli_light_03_unarmed_F", "B_Heli_Transport_03_F", "B_Heli_Transport_01_camo_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["I_E_Heli_light_03_dynamicLoadout_F", "B_Heli_Light_01_armed_F", "B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; +["vehiclesHelisTransport", ["B_Heli_Transport_03_F", "B_Heli_Transport_01_camo_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["I_E_Heli_light_03_dynamicLoadout_F", "B_Heli_Light_01_armed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["B_T_MBT_01_arty_F", "I_E_Truck_02_MRL_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -77,6 +80,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesCargoTrucks", _cargoTrucks] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Apex.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Apex.sqf index 87fca37f94..7d9f90a32b 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Apex.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Apex.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["B_T_Truck_01_Repair_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["B_T_Truck_01_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["B_T_Truck_01_medical_F"]] call _fnc_saveToTemplate; -private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_T_APC_Tracked_01_CRV_F"]; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; +private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F"]; // CRV has no cargo: "B_T_APC_Tracked_01_CRV_F" +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["B_T_MBT_01_TUSK_F", "B_T_MBT_01_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["B_T_APC_Tracked_01_AA_F"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_ ["vehiclesHelisLight", ["B_Heli_Light_01_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["B_Heli_Transport_03_F", "B_Heli_Transport_01_camo_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["B_Heli_Light_01_armed_F", "B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["B_Heli_Light_01_armed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["B_T_MBT_01_arty_F", "B_T_MBT_01_mlrs_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -77,6 +80,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesAPCs", _APCs] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Arid.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Arid.sqf index f86cb3872c..2dd40f1385 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Arid.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Arid.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["B_Truck_01_Repair_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["B_Truck_01_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["B_Truck_01_medical_F"]] call _fnc_saveToTemplate; -private _APCs = ["B_APC_Wheeled_01_cannon_F", "B_APC_Tracked_01_rcws_F", "B_APC_Tracked_01_CRV_F"]; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; +private _APCs = ["B_APC_Wheeled_01_cannon_F", "B_APC_Tracked_01_rcws_F"]; // CRV has no cargo: "B_APC_Tracked_01_CRV_F" +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["B_MBT_01_TUSK_F", "B_MBT_01_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["B_APC_Tracked_01_AA_F"]] call _fnc_saveToTemplate; @@ -40,6 +42,7 @@ private _APCs = ["B_APC_Wheeled_01_cannon_F", "B_APC_Tracked_01_rcws_F", "B_APC_ ["vehiclesHelisLight", ["B_Heli_Light_01_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["B_Heli_Transport_03_F", "B_Heli_Transport_03_unarmed_F", "B_Heli_Transport_01_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["B_Heli_Light_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesHelisAttack", ["B_Heli_Attack_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["B_MBT_01_arty_F","B_MBT_01_mlrs_F"]] call _fnc_saveToTemplate; //this line determines artillery vehicles -- Example: ["vehiclesArtillery", ["B_MBT_01_arty_F"]] -- Array, can contain multiple assets @@ -77,6 +80,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesAPCs", _APCs] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Temperate.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Temperate.sqf index afdcd531a0..5186596c4b 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Temperate.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Temperate.sqf @@ -26,11 +26,12 @@ ["vehiclesRepairTrucks", ["B_T_Truck_01_Repair_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["B_T_Truck_01_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["B_T_Truck_01_medical_F"]] call _fnc_saveToTemplate; -private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_T_APC_Tracked_01_CRV_F"]; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; +private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F"]; //, "B_T_APC_Tracked_01_CRV_F"]; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["B_T_MBT_01_TUSK_F", "B_T_MBT_01_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["B_T_APC_Tracked_01_AA_F"]] call _fnc_saveToTemplate; - ["vehiclesTransportBoats", ["B_Boat_Transport_01_F"]] call _fnc_saveToTemplate; ["vehiclesGunBoats", ["B_Boat_Armed_01_minigun_F"]] call _fnc_saveToTemplate; ["vehiclesAmphibious", ["B_T_APC_Wheeled_01_cannon_F"]] call _fnc_saveToTemplate; @@ -41,7 +42,8 @@ private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_ ["vehiclesHelisLight", ["B_Heli_Light_01_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["B_Heli_Transport_03_F", "B_Heli_Transport_01_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["B_Heli_Light_01_dynamicLoadout_F", "B_Heli_Attack_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["B_Heli_Light_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["B_Heli_Attack_01_dynamicLoadout_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["B_T_MBT_01_mlrs_F","B_T_MBT_01_arty_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -77,6 +79,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesAPCs", _APCs] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Tropical.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Tropical.sqf index e47f8849f3..dc0cc3a38a 100644 --- a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Tropical.sqf +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_AI_NATO_Tropical.sqf @@ -26,7 +26,9 @@ ["vehiclesRepairTrucks", ["B_T_Truck_01_Repair_F"]] call _fnc_saveToTemplate; ["vehiclesFuelTrucks", ["B_T_Truck_01_fuel_F"]] call _fnc_saveToTemplate; ["vehiclesMedical", ["B_T_Truck_01_medical_F"]] call _fnc_saveToTemplate; -private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_T_APC_Tracked_01_CRV_F"]; +["vehiclesLightAPCs", []] call _fnc_saveToTemplate; +private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F"]; //, "B_T_APC_Tracked_01_CRV_F"]; +["vehiclesIFVs", []] call _fnc_saveToTemplate; ["vehiclesTanks", ["B_T_MBT_01_TUSK_F", "B_T_MBT_01_cannon_F"]] call _fnc_saveToTemplate; ["vehiclesAA", ["B_T_APC_Tracked_01_AA_F"]] call _fnc_saveToTemplate; @@ -40,7 +42,8 @@ private _APCs = ["B_T_APC_Wheeled_01_cannon_F", "B_T_APC_Tracked_01_rcws_F", "B_ ["vehiclesHelisLight", ["B_Heli_Light_01_F"]] call _fnc_saveToTemplate; ["vehiclesHelisTransport", ["B_Heli_Transport_03_F", "B_Heli_Transport_01_camo_F"]] call _fnc_saveToTemplate; -["vehiclesHelisAttack", ["B_Heli_Light_01_armed_F", "B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; +["vehiclesHelisLightAttack", ["B_Heli_Light_01_armed_F"]] call _fnc_saveToTemplate; +["vehiclesHelisAttack", ["B_Heli_Attack_01_F"]] call _fnc_saveToTemplate; ["vehiclesArtillery", ["B_T_MBT_01_arty_F", "B_T_MBT_01_mlrs_F"]] call _fnc_saveToTemplate; ["magazines", createHashMapFromArray [ @@ -77,6 +80,8 @@ if (allowDLCWS && A3A_hasWS) then { }; ["vehiclesAPCs", _APCs] call _fnc_saveToTemplate; +#include "Vanilla_Vehicle_Attributes.sqf" + ///////////////////// /// Identities /// ///////////////////// @@ -209,7 +214,7 @@ _sfLoadoutData set ["slRifles", [ ]]; _sfLoadoutData set ["rifles", [ ["arifle_MX_khk_F", "muzzle_snds_H", "acc_pointer_IR", "optic_Holosight_blk_F", ["30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag_Tracer"], [], ""] -]; +]]; _sfLoadoutData set ["carbines", [ ["arifle_MXC_khk_F", "muzzle_snds_H", "acc_pointer_IR", "optic_Holosight_blk_F", ["30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag_Tracer"], [], ""], ["arifle_MXC_khk_F", "muzzle_snds_H", "acc_pointer_IR", "optic_Holosight", ["30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag", "30Rnd_65x39_caseless_khaki_mag_Tracer"], [], ""] diff --git a/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_Vehicle_Attributes.sqf b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_Vehicle_Attributes.sqf new file mode 100644 index 0000000000..f4ae8922f2 --- /dev/null +++ b/A3A/addons/core/Templates/Templates/Vanilla/Vanilla_Vehicle_Attributes.sqf @@ -0,0 +1,12 @@ +["attributesVehicles", [ + // Attack helis with only fixed miniguns + ["O_Heli_Light_02_dynamicLoadout_F", ["cost", 100]], + ["O_Heli_Light_02_F", ["cost", 100]], + ["B_Heli_Light_01_armed_F", ["cost", 100]], + ["B_Heli_Light_01_dynamicLoadout_F", ["cost", 100]], + ["I_E_Heli_light_03_dynamicLoadout_F", ["cost", 100]], + + // AAF trash CAS + ["I_Plane_Fighter_03_dynamicLoadout_F", ["cost", 200]] + +]] call _fnc_saveToTemplate; diff --git a/A3A/addons/core/functions/AI/fn_AIreactOnKill.sqf b/A3A/addons/core/functions/AI/fn_AIreactOnKill.sqf index f820d6efa1..7d3403e3a4 100644 --- a/A3A/addons/core/functions/AI/fn_AIreactOnKill.sqf +++ b/A3A/addons/core/functions/AI/fn_AIreactOnKill.sqf @@ -1,15 +1,16 @@ /* Author: Wurzel0701, Triada, jaj22, Spoffy, Barbolani - Defines and executes the behaviour of AI in case of a KIA in their group + Defines and executes the behaviour of enemy AI in case of a down or KIA in their group Arguments: - The group of which a unit has been killed - The unit which has killed the group unit + The unit which was downed or killed. + The group of the unit. May have changed since. + The unit which downed or killed the unit Return Value: -Scope: Server/HC +Scope: Server/HC, local to unit/group Environment: Scheduled Public: Yes Dependencies: @@ -19,52 +20,46 @@ Dependencies: A3A_faction_all Example: -[_group, _killer] spawn A3A_fnc_AIreactOnKill; +[_unit, _group, _killer] spawn A3A_fnc_AIreactOnKill; */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -params ["_group", "_killer"]; -private _enemy = objNull; -private _aliveGroupMembers = (units _group) select {[_x] call A3A_fnc_canFight}; -private _unitCount = count _aliveGroupMembers; +// TODO: what exactly should killer parameter be here? +params ["_unit", "_group", "_killer"]; -//No group member left in fighting condition, -if(_unitCount == 0) exitWith {}; +if (_unit getVariable ["downedTimeout", 0] > time) exitWith {}; // only count each unit once, at least within timeout +_unit setVariable ["downedTimeout", time + 1200]; //If _killer is not set or the same side (collision for example), abort here if((isNil "_killer") || {(isNull _killer) || {side (group _killer) == side _group}}) exitWith {}; +// Add the unit to recent kills for reaction purposes +[side _group, getPosATL _unit, 10] remoteExec ["A3A_fnc_addRecentDamage", 2]; + +private _enemy = objNull; +private _activeGroupMembers = (units _group) select {_x call A3A_fnc_canFight}; + +//No group member left in fighting condition, no reaction possible +if(count _activeGroupMembers == 0) exitWith {}; + //Call help if possible -if(_group getVariable ["canCallSupportAt", -1] < dateToNumber date) then +if(_group getVariable ["A3A_canCallSupportAt", -1] < time) then { + [_group, _killer] spawn A3A_fnc_callForSupport; +}; + +if (!fleeing leader _group and random 1 < 0.5) then { - private _supportTypes = [_group, _killer] call A3A_fnc_chooseSupport; - if((count _supportTypes) > 0) then - { - //Check if we are attacking the vehicle or man - private _enemyVehicle = objectParent _killer; - if(isNull _enemyVehicle && {!(_killer isKindOf "Man")}) then - { - _enemyVehicle = _enemy; - }; - //Call the support on the unit or its vehicle - if(isNull _enemyVehicle) then - { - [_group, _supportTypes, _killer] spawn A3A_fnc_callForSupport; - } - else - { - [_group, _supportTypes, _enemyVehicle] spawn A3A_fnc_callForSupport; - }; - }; + private _courage = leader _group skill "courage"; + _group allowFleeing (2 - _courage - count _activeGroupMembers / count units _group); }; { if (fleeing _x) then { - if ([_x] call A3A_fnc_canFight) then + if (_x call A3A_fnc_canFight) then { - _enemy = _x findNearestEnemy _x; + private _enemy = _x findNearestEnemy _x; if (!isNull _enemy) then { if ((_x distance _enemy < 50) && (vehicle _x == _x)) then @@ -87,9 +82,9 @@ if(_group getVariable ["canCallSupportAt", -1] < dateToNumber date) then } else { - if ([_x] call A3A_fnc_canFight) then + if (_x call A3A_fnc_canFight) then { - _enemy = _x findNearestEnemy _x; + private _enemy = _x findNearestEnemy _x; if (!isNull _enemy) then { if (([primaryWeapon _x] call BIS_fnc_baseWeapon) in allMachineGuns) then @@ -124,14 +119,7 @@ if(_group getVariable ["canCallSupportAt", -1] < dateToNumber date) then }; }; }; - if (random 1 < 0.5) then - { - if (count units _group > 0) then - { - _x allowFleeing (1 -(_x skill "courage") + (_unitCount/(count units _group))); - }; - }; }; }; - sleep 1 + (random 1); -} forEach _aliveGroupMembers; + sleep (1 + random 1); +} forEach _activeGroupMembers; diff --git a/A3A/addons/core/functions/AI/fn_artillery.sqf b/A3A/addons/core/functions/AI/fn_artillery.sqf deleted file mode 100644 index 11853895e0..0000000000 --- a/A3A/addons/core/functions/AI/fn_artillery.sqf +++ /dev/null @@ -1,80 +0,0 @@ -if (!isServer and hasInterface) exitWith{}; - -private ["_mrkOrigin","_pos","_attackingSide","_countX","_mrkDestination","_veh","_posOrigin","_sideTargets","_posDestination","_typeVehX","_typeAmmunition","_size","_vehicle","_vehCrew","_groupVeh","_roundsX","_objectiveX","_objectivesX","_timeX"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -_mrkOrigin = _this select 0; -_posOrigin = if (_mrkOrigin isEqualType "") then {getMarkerPos _mrkOrigin} else {_mrkOrigin}; -_mrkDestination = _this select 1; -_attackingSide = _this select 2; -private _faction = Faction(_attackingSide); -_sideTargets = _attackingSide call BIS_fnc_enemySides; -_posDestination = getMarkerPos _mrkDestination; -_typeVehX = (_faction get "vehiclesArtillery"); - -if !([_typeVehX] call A3A_fnc_vehAvailable) exitWith {}; - -_typeAmmunition = ((_faction get "magazines") get _typeVehX) #0; - -_pos = [_posOrigin, 50,100, 10, 0, 0.3, 0] call BIS_Fnc_findSafePos; - -_vehicle=[_pos, random 360,_typeVehX, _attackingSide] call A3A_fnc_spawnVehicle; -_veh = _vehicle select 0; -_vehCrew = _vehicle select 1; -{[_x] call A3A_fnc_NATOinit} forEach _vehCrew; -[_veh, _attackingSide] call A3A_fnc_AIVEHinit; -_groupVeh = _vehicle select 2; -_size = [_mrkDestination] call A3A_fnc_sizeMarker; - -if (!alive _veh) exitWith {Error("Arty piece destroyed on spawn, fire mission canceled")}; -if (_posDestination inRangeOfArtillery [[_veh], ((getArtilleryAmmo [_veh]) select 0)]) then - { - while {(alive _veh) and ({_x select 0 == _typeAmmunition} count magazinesAmmo _veh > 0) and (_mrkDestination in forcedSpawn)} do - { - _objectiveX = objNull; - _roundsX = 1; - _objectivesX = vehicles select {(side (group driver _x) in _sideTargets) and (_x distance _posDestination <= _size * 2) and (_attackingSide knowsAbout _x >= 1.4) and (speed _x < 1)}; - if (count _objectivesX > 0) then - { - { - if (typeOf _x in FactionGet(all,"vehiclesAttack")) exitWith {_objectiveX = _x; _roundsX = 4}; - } forEach _objectivesX; - if (isNull _objectiveX) then {_objectiveX = selectRandom _objectivesX}; - } - else - { - _objectivesX = allUnits select {(side (group _x) in _sideTargets) and (_x distance _posDestination <= _size * 2) and (_attackingSide knowsAbout _x >= 1.4) and (_x == leader group _x)}; - if (count _objectivesX > 0) then - { - _countX = 0; - { - _potential = _x; - _countGroup = {(alive _x) and (!captive _x)} count units group _potential; - if (_countGroup > _countX) then - { - if ((_attackingSide == Invaders) or ({(side (group _x) == civilian) and (_x distance _potential < 50)} count allUnits == 0)) then - { - _objectiveX = _potential; - if (_countGroup > 6) then {_roundsX = 2}; - }; - }; - } forEach _objectivesX; - }; - }; - if (!isNull _objectiveX) then - { - _veh commandArtilleryFire [position _objectiveX,_typeAmmunition,_roundsX]; - _timeX = _veh getArtilleryETA [position _objectiveX, ((getArtilleryAmmo [_veh]) select 0)]; - sleep 9 + ((_roundsX - 1) * 3); - } - else - { - sleep 29; - }; - sleep 1; - }; - }; - -[_groupVeh] spawn A3A_fnc_groupDespawner; -[_veh] spawn A3A_fnc_vehDespawner; diff --git a/A3A/addons/core/functions/AI/fn_attackDrillAI.sqf b/A3A/addons/core/functions/AI/fn_attackDrillAI.sqf index 5878ed9bc9..5d6059d6f6 100644 --- a/A3A/addons/core/functions/AI/fn_attackDrillAI.sqf +++ b/A3A/addons/core/functions/AI/fn_attackDrillAI.sqf @@ -1,6 +1,10 @@ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() + private _groupX = _this; +if !(isNil {_groupX getVariable "A3A_AIScriptHandle"}) exitWith {}; // hmm +_groupX setVariable ["A3A_AIScriptHandle", _thisScript]; + _objectivesX = _groupX call A3A_fnc_enemyList; _groupX setVariable ["objectivesX",_objectivesX]; _groupX setVariable ["taskX","Patrol"]; @@ -98,28 +102,15 @@ while {true} do _groupX setVariable ["objectivesX",_objectivesX]; if !(_objectivesX isEqualTo []) then { - _air = objNull; - _tanksX = objNull; + private _air = objNull; + private _tank = objNull; { - _eny = assignedVehicle (_x select 4); - if (_eny isKindOf "Tank") then - { - _tanksX = _eny; - } - else - { - if (_eny isKindOf "Air") then - { - if (count (weapons _eny) > 1) then - { - _air = _eny; - }; - }; - }; - if (!(isNull _air) and !(isNull _tanksX)) exitWith {}; + _eny = assignedVehicle (_x select 4); + if (_eny isKindOf "Tank" and canFire _eny and count (weapons _eny) > 1) exitWith { _tank = _eny }; + if (_eny isKindOf "Air" and canFire _eny and count (weapons _eny) > 1) exitWith { _air = _eny }; } forEach _objectivesX; _LeaderX = leader _groupX; - _allNearFriends = allUnits select {(_x distance _LeaderX < (distanceSPWN/2)) and (side group _x in _friendlies)}; + _allNearFriends = units side _groupX inAreaArray [getPosATL _LeaderX, distanceSPWN/2, distanceSPWN/2]; { _unit = _x; { @@ -132,46 +123,32 @@ while {true} do } forEach _objectivesX; } forEach (_allNearFriends select {_x == leader _x}) - [_LeaderX]; _numNearFriends = count _allNearFriends; - //_air = objNull; - //_tanksX = objNull; _numObjectives = count _objectivesX; _taskX = _groupX getVariable ["taskX","Patrol"]; _nearX = _groupX call A3A_fnc_nearEnemy; _soldiers = ((units _groupX) select {[_x] call A3A_fnc_canFight}) - [_groupX getVariable ["mortarX",objNull]]; _numSoldiers = count _soldiers; + + // Support calls may work here, but disabled for now if !(isNull _air) then { - private _supportTypes = [_groupX, _air] call A3A_fnc_chooseSupport; - if ((count _supportTypes) > 0) then - { - [_groupX, _supportTypes, _air] spawn A3A_fnc_callForSupport; - }; + //[_groupX, _air] spawn A3A_fnc_callForSupport; _groupX setVariable ["taskX","Hide"]; _taskX = "Hide"; }; - if !(isNull _tanksX) then + if !(isNull _tank) then { - private _supportTypes = [_groupX, _tanksX] call A3A_fnc_chooseSupport; - if ((count _supportTypes) > 0) then - { - [_groupX, _supportTypes, _tanksX] spawn A3A_fnc_callForSupport; - }; + //[_groupX, _tank] spawn A3A_fnc_callForSupport; _groupX setVariable ["taskX","Hide"]; _taskX = "Hide"; }; - if (_numObjectives > 2 * _numNearFriends) then + if (_numObjectives > 2 * _numNearFriends and !isNull _nearX) then { - if !(isNull _nearX) then - { - private _supportTypes = [_groupX, _nearX] call A3A_fnc_chooseSupport; - if ((count _supportTypes) > 0) then - { - [_groupX, _supportTypes, _nearX] spawn A3A_fnc_callForSupport; - }; - }; + //[_groupX, _nearX] spawn A3A_fnc_callForSupport; _groupX setVariable ["taskX","Hide"]; _taskX = "Hide"; }; + _transporte = _groupX getVariable ["transporte",objNull]; if (isNull(_groupX getVariable ["transporte",objNull])) then { @@ -309,7 +286,7 @@ while {true} do if (_taskX == "Hide") then { - if ((isNull _tanksX) and {isNull _air} and {_numObjectives <= 2*_numNearFriends}) then + if ((isNull _tank) and {isNull _air} and {_numObjectives <= 2*_numNearFriends}) then { _groupX setVariable ["taskX","Patrol"]; } diff --git a/A3A/addons/core/functions/AI/fn_attackHeli.sqf b/A3A/addons/core/functions/AI/fn_attackHeli.sqf new file mode 100644 index 0000000000..af367552bf --- /dev/null +++ b/A3A/addons/core/functions/AI/fn_attackHeli.sqf @@ -0,0 +1,54 @@ +/* Persistent AI script to make enemy attack helis behave better + Prevents helis giving enemies an easy kill on the first pass, and hovering once they run out of targets + +Scope: Server or HC +Environment: Spawned + +Arguments: + Vehicle (should be attack heli) + Crew group of vehicle, should be occupant or invader + Ground position to kill targets near + +*/ + +// - SAD will still run out of steam with lockWP enabled. +// - everything is dumb +// so basically we still need a monitor function to recreate the waypoint? + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_vehicle", "_group", "_targPos"]; + +// Set script handle so abort routines can remove it later +_group setVariable ["A3A_AIScriptHandle", _thisScript]; + +while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; +_group setBehaviourStrong "COMBAT"; +private _noGunner = isNull gunner _vehicle; + +private _wayPos = _targPos getPos [300 + random 100, random 360]; +private _destroyWP = _group addWaypoint [_wayPos, 0]; +_destroyWP setWaypointType "SAD"; + +private _approach = true; +private _timeout = time + 60 + (_vehicle distance2d _targPos) / 50; +while {true} do { + sleep 10; + if !(alive _vehicle and canFire _vehicle and canMove _vehicle) exitWith {}; + if !((_noGunner or gunner _vehicle call A3A_fnc_canFight) and driver _vehicle call A3A_fnc_canFight) exitWith {}; + + if (_approach and { _vehicle distance2d _wayPos < 300}) then { _timeout = -1; _approach = false }; + if (currentWaypoint _group > 0 or time > _timeout ) then { + _wayPos = _targPos getPos [50 + random 100, random 360]; + _destroyWP setWaypointPosition [_wayPos, 0]; + //Debug_1("Setting current waypoint for attack heli type %1", typeof vehicle leader _group); + _group setCurrentWaypoint _destroyWP; + _timeout = time + 300; + }; +}; + +ServerInfo("Attack heli aborted due to damage"); +_group setVariable ["A3A_AIScriptHandle", nil]; +[_vehicle] spawn A3A_fnc_VEHDespawner; +[_group] spawn A3A_fnc_enemyReturnToBase; diff --git a/A3A/addons/core/functions/AI/fn_callForSupport.sqf b/A3A/addons/core/functions/AI/fn_callForSupport.sqf index b3bcde2222..4bb3b7ddb4 100644 --- a/A3A/addons/core/functions/AI/fn_callForSupport.sqf +++ b/A3A/addons/core/functions/AI/fn_callForSupport.sqf @@ -1,5 +1,3 @@ -params ["_group", "_supportTypes", "_target"]; - /* Simulates the call for support by a group by making the teamleader a bit more dumb for a time Execution on: HC or Server @@ -8,7 +6,6 @@ params ["_group", "_supportTypes", "_target"]; Params: _group: GROUP : The group which should call support - _supportTypes: ARRAY of STRINGs : The types of support the group calls for _target: OBJECT : The target object the group wants support against Returns: @@ -16,48 +13,50 @@ params ["_group", "_supportTypes", "_target"]; */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() + +params ["_group", "_target"]; private _groupLeader = leader _group; +private _side = side _group; -if(side _group == teamPlayer) exitWith -{ - Error_1("Rebel group %1 managed to call callForSupport, not allowed for rebel groups", _group); +if(_side != Occupants and _side != Invaders) exitWith { + Error_2("Non-enemy group %1 of side %2 managed to call callForSupport", _group, _side); }; -if((_group getVariable ["canCallSupportAt", -1]) > (dateToNumber date)) exitWith {}; +//If groupleader is down, dont call support +if !(_groupLeader call A3A_fnc_canFight) exitWith {}; -//Block the group from calling support again -private _date = date; -_date set [4, (_date select 4) + 5]; -private _dateNumber = dateToNumber _date; -_group setVariable ["canCallSupportAt", _dateNumber, true]; +if((_group getVariable ["A3A_canCallSupportAt", -1]) > time) exitWith {}; -//If groupleader is down, dont call support -if !([_groupLeader] call A3A_fnc_canFight) exitWith {}; +private _timeToCallSupport = (10 + random 5) / A3A_balancePlayerScale; +_group setVariable ["A3A_canCallSupportAt", time + 5*_timeToCallSupport]; -Debug_4("Leader of %1 (side %2) is starting to call for help against %3 with helps %4", _group, side _group, _target, _supportTypes); +ServerDebug_4("Leader of %1 (side %2) is starting to request support against %3 (type %4)", _group, _side, _target, typeof _target); //Lower skill of group leader to simulate radio communication (!!!Barbolanis idea!!!) +// Maintain differential leader skills (see NATOinit) private _oldSkill = skill _groupLeader; +private _oldCourage = _groupLeader skill "courage"; _groupLeader setSkill (_oldSkill - 0.2); -//Wait for the call to happen -private _timeToCallSupport = 10 + random 5; sleep _timeToCallSupport; //Reset leader skill _groupLeader setSkill _oldSkill; +_groupLeader setskill ["courage", _oldCourage]; +_groupLeader setskill ["commanding", _oldCourage]; //If the group leader survived the call, proceed -if([_groupLeader] call A3A_fnc_canFight) then +if(_groupLeader call A3A_fnc_canFight) then { - private _revealed = [getPos _groupLeader, side _group] call A3A_fnc_calculateSupportCallReveal; + // why here? Are we intercepting the radio traffic? + private _revealed = [getPosATL _groupLeader, side _group] call A3A_fnc_calculateSupportCallReveal; //Starting the support - Debug_3("%1 managed to call help against %2, reveal value is %3", _group, _target, _revealed); - [_target, _group knowsAbout _target, _supportTypes, side _group, _revealed] remoteExec ["A3A_fnc_sendSupport", 2]; + ServerDebug_2("%1 managed to request support, reveal value is %2", _group, _revealed); + [_side, _target, getPosATL _groupLeader, _group knowsAbout _target, _revealed] remoteExec ["A3A_fnc_requestSupport", 2]; } else { - //Support call failed, resetting cooldown - Debug_1("%1 got no help as the leader is dead or down", _group); - _group setVariable ["canCallSupportAt", -1, true]; + //Support call failed, reset cooldown + ServerDebug_1("%1 failed to request support as the leader is dead or down", _group); + _group setVariable ["A3A_canCallSupportAt", nil]; }; diff --git a/A3A/addons/core/functions/AI/fn_canFight.sqf b/A3A/addons/core/functions/AI/fn_canFight.sqf index be176be995..b41c2b4999 100644 --- a/A3A/addons/core/functions/AI/fn_canFight.sqf +++ b/A3A/addons/core/functions/AI/fn_canFight.sqf @@ -1,7 +1,6 @@ params ["_unit"]; -if (isNull _unit) exitWith {false}; -if (!alive _unit) exitWith {false}; +if (!alive _unit) exitWith {false}; // also works as a null check if (captive _unit) exitWith {false}; if (_unit getVariable ["incapacitated",false]) exitWith {false}; if (_unit getVariable ["surrendered",false]) exitWith {false}; diff --git a/A3A/addons/core/functions/AI/fn_chooseSupport.sqf b/A3A/addons/core/functions/AI/fn_chooseSupport.sqf deleted file mode 100644 index 4942e8cacd..0000000000 --- a/A3A/addons/core/functions/AI/fn_chooseSupport.sqf +++ /dev/null @@ -1,227 +0,0 @@ -params ["_group", "_enemy"]; - -/* Selects a set of supports the groups should call in against the given enemy - - Execution on: All - - Scope: Internal - - Params: - _group: GROUP : The group that wants to call in support - _enemy: OBJECT : The enemy of the group - - Returns: - _supportTypes: ARRAY of STRINGs : The set of supports which should be called in, [] if none needed -*/ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(side _group); -private _supportTypes = []; - -//If enemy is more than 600 meters away we always force the support -private _forceSupport = false; -if(_enemy distance2D (getPos (leader _group)) > 600) then -{ - _forceSupport = true; -}; - -private _enemyVehicle = objectParent _enemy; -//Sometimes the actual vehicle is passed as killer, making sure to catch that -if(isNull _enemyVehicle && {!(_enemy isKindOf "Man")}) then -{ - _enemyVehicle = _enemy; -}; - -//Check groups combat abilities -private _unitsInGroup = {[_x] call A3A_fnc_canFight} count (units _group); - -if(_unitsInGroup == 0) exitWith -{ - //All units uncon, group not able to fight any more - _supportTypes; -}; - -private _ATLauncherInGroup = {((_x call A3A_fnc_typeOfSoldier) == "ATMan") && {[_x] call A3A_fnc_canFight}} count (units _group); -private _AALauncherInGroup = {((_x call A3A_fnc_typeOfSoldier) == "AAMan") && {[_x] call A3A_fnc_canFight}} count (units _group); - -//Determine class of enemy/ his vehicle -switch (true) do -{ - case (_enemy isKindOf "Man"): - { - private _enemiesNearEnemy = count (allUnits select {(side (group _x)) == (side (group _enemy)) && {_x distance2D _enemy < 100}}); - if(_enemiesNearEnemy > 6) then - { - //They are fighting some larger group of enemies - if - ( - _forceSupport || - //Not enough guys to effectively fight - {(_unitsInGroup <= 4) || - //Outnumbered - {(random 2) < (_enemiesNearEnemy/_unitsInGroup)}} - ) then - { - //Use spread out attacks first, if not available use more precise attacks - _supportTypes = ["MORTAR", "CANNON", "AIRSTRIKE", "CARPETBOMB", "AIRDROP", "GUNSHIP", "ORBSTRIKE", "QRF"]; - }; - } - else - { - if(_enemiesNearEnemy > 2) then - { - //They are fighting a medium group of enemies - if - ( - _forceSupport || - //Units are being cowards - {(random 2) < (_enemiesNearEnemy/_unitsInGroup)} - ) then - { - //Use more precise attacks first, if not available use spread out ones - _supportTypes = ["AIRSTRIKE", "MORTAR", "QRF", "CANNON", "CARPETBOMB", "GUNSHIP"]; - }; - } - else - { - //They are fighting a small group of enemies - if - ( - _forceSupport || - //Units are being cowards - {(random 1) < (_enemiesNearEnemy/_unitsInGroup)} - ) then - { - //Use more precise attacks first, if not available use spread out ones - _supportTypes = ["QRF", "MORTAR", "CANNON"]; - }; - }; - }; - }; - case (_enemyVehicle isKindOf "StaticWeapon"): - { - //AI against statics? No way, send in support instantly - _supportTypes = ["AIRSTRIKE", "MISSILE", "CANNON", "CARPETBOMB", "MORTAR", "GUNSHIP"]; - }; - case (_enemyVehicle isKindOf "Tank"): - { - //They are fighting some kind of MBT, check for their AT capabilities - if - ( - _forceSupport || - //Enough to defend themselves, still a little chance to call support - {(_ATLauncherInGroup >= 2) && (random 1 < 0.2) || - //A chance to defend themselves, but a medium chance to call support - {(_ATLauncherInGroup == 1) && (random 1 < 0.5) || - //No chance to defend themselves, call support - {_ATLauncherInGroup == 0}}} - ) then - { - //Use something that can attack targets directly, if not available use strong AoE attacks - _supportTypes = ["CAS", "GUNSHIP", "MISSILE", "CANNON", "AIRDROP", "EMP", "ORBSTRIKE", "MORTAR", "AIRSTRIKE"]; - }; - }; - case (_enemyVehicle isKindOf "LandVehicle"): - { - //They are fighting MRAPs, APCs or trucks (or maybe civilian vehicles) - if - ( - _forceSupport || - //Able to defend themselves, still a chance to call in supports - {((_ATLauncherInGroup >= 1) && (random 1 < 0.25)) || - //Nothing to defend themselves with, call support - {_ATLauncherInGroup == 0}} - ) then - { - //Use something that can target directly, otherwise use something against vehicle groups - _supportTypes = ["CAS", "CANNON", "EMP", "AIRSTRIKE", "MISSILE", "CARPETBOMB", "MORTAR", "GUNSHIP", "AIRDROP"]; - }; - }; - case (_enemyVehicle isKindOf "Plane"): - { - //They are fighting an enemy plane - if - ( - _forceSupport || - //Can defend, small chance for support - {((_AALauncherInGroup >= 2) && (random 1 < 0.2)) || - //Can defend a bit, big chance for support - {((_AALauncherInGroup == 1) && (random 1 < 0.75)) || - //No defense, call support - {_AALauncherInGroup == 0}}} - ) then - { - //Strike back with a dogfighter, if not available fall back to AA or AoE remote weapons - _supportTypes = ["ASF", "SAM", "EMP", "AIRDROP"]; - }; - }; - case (_enemyVehicle isKindOf "Helicopter"): - { - private _vehicleType = typeOf _enemyVehicle; - if(_vehicleType in (_faction get "vehiclesHelisAttack")) then - { - if - ( - _forceSupport || - //Can defend, but it is still an attack helicopter - {((_AALauncherInGroup >= 1) && (random 1 < 0.65)) || - //Nothing to defend, call support - {_AALauncherInGroup == 0}} - ) then - { - //Use the typical AA supports available - _supportTypes = ["SAM", "ASF", "QRF", "EMP", "AIRDROP", "GUNSHIP"]; - }; - } - else - { - if - ( - _forceSupport || - //Cannot defend themselves, call for help - {_AALauncherInGroup == 0} - ) then - { - //Easy enemy, mostly used for transports, send only light support - _supportTypes = ["SAM", "GUNSHIP", "QRF", "ASF"]; - }; - }; - }; - case (_enemyVehicle isKindOf "Ship"): - { - _supportTypes = ["MORTAR", "CAS", "GUNSHIP", "MISSILE"]; - }; - default - { - Error_2("Cannot figure out class for unit %1 (vehicle %2)", _enemy, typeOf _enemyVehicle); - }; -}; - -// Avoid making area attacks against friendlies or groups of houses, although "mistakes" can be made -private _friendlyCount = count (units side _group inAreaArray [getpos _enemy, 150, 150]); -private _maxFriendlies = if (side _group == Invaders) then { random [1, 2, 10] } else { random [0, 0, 5] }; - -private _nearHouses = call { - if (side _group == Invaders) exitWith { 0 }; // invaders are fine with bombing towns - // many buildings within military facilities also count as HOUSE, so first check if we're inside a town radius - private _cityIndex = citiesX findIf { _enemy inArea _x }; - if (_cityIndex == -1) exitWith { 0 }; - count nearestTerrainObjects [getpos _enemy, ["HOUSE"], 100, false]; -}; -private _maxHouses = (1 + random 5) ^ 2; - -if (_friendlyCount > _maxFriendlies or _nearHouses > _maxHouses) then -{ - ServerDebug_3("Area attacks blocked at %1 due to %2 friendlies and %3 houses", getpos _enemy, _friendlyCount, _nearHouses); - _supportTypes = _supportTypes - ["MORTAR", "AIRSTRIKE", "CARPETBOMB", "MISSILE", "ORBSTRIKE"]; -}; - -if(_forceSupport) then -{ - //Remove the slow QRF support if too far away, help needs to be there fast - _supportTypes = _supportTypes - ["QRF"]; - //meh, leave it as a fallback at least - _supportTypes pushBack "QRF"; -}; - -_supportTypes; diff --git a/A3A/addons/core/functions/AI/fn_combatLanding.sqf b/A3A/addons/core/functions/AI/fn_combatLanding.sqf index aa721271a5..52a179c725 100644 --- a/A3A/addons/core/functions/AI/fn_combatLanding.sqf +++ b/A3A/addons/core/functions/AI/fn_combatLanding.sqf @@ -1,31 +1,44 @@ -params ["_helicopter"]; +/* Helicopter flies a combat landing approach, lands and unloads cargo group before returning to base -private _originPos = _helicopter getVariable "PosOrigin"; -private _posDestination = _helicopter getVariable "PosDestination"; -private _landingPad = _helicopter getVariable "LandingPad"; -private _crewGroup = group driver _helicopter; -private _cargoGroup = grpNull; +Scope: Server or HC +Environment: Scheduled, spawned -{ - if(group _x != _crewGroup) exitWith - { - _cargoGroup = group _x; - }; -} forEach (crew _helicopter); +Parameters: + The helicopter to control + Crew group for helicopter + Cargo group for helicopter + Destination position for troops to attack after landing + Position for heli to return to after offloading + Landing position for heli +*/ -private _endPos = getPosASL _landingPad; -private _startPos = getPosASL _helicopter; +params ["_helicopter", "_crewGroup", "_cargoGroup", "_posDestination", "_originPos", "_landPos"]; -private _midPos = +_endPos; -if(A3A_climate isEqualTo "tropical") then -{ - _midPos set [2, (_endPos select 2) + 250]; -} -else -{ - _midPos set [2, (_endPos select 2) + 100]; -}; +// avoid weird situations where they receive RTB instructions before they finish unloading +_crewGroup setVariable ["A3A_AIScriptHandle", _thisScript]; +_cargoGroup setVariable ["A3A_AIScriptHandle", _thisScript]; + +private _landPad = createVehicle ["Land_HelipadEmpty_F", _landpos, [], 0, "NONE"]; +_helicopter setVariable ["LandingPad", _landPad, true]; // cleared up (eventually) by heli deletion handler +//Create the waypoints for the crewGroup +private _vehWP0 = _crewGroup addWaypoint [_landpos, 0]; +_vehWP0 setWaypointType "MOVE"; +_vehWP0 setWaypointSpeed "FULL"; +_vehWP0 setWaypointCompletionRadius 150; +_vehWP0 setWaypointBehaviour "CARELESS"; + +private _midHeight = [100, 150] select (A3A_climate isEqualTo "tropical"); +_helicopter flyInHeight _midHeight; + +waitUntil {sleep 1; (_helicopter distance2D _landPos) < 600}; + +_helicopter flyInHeight 0; // helps to keep it near the ground after landing + +// Landing path setup +private _endPos = getPosASL _landPad; +private _startPos = getPosASL _helicopter; +private _midPos = _endPos vectorAdd [0,0,_midHeight]; private _initialVelocity = (velocity _helicopter); _initialVelocity set [2, 0]; @@ -46,8 +59,6 @@ private _midToEndVector = _endPos vectorDiff _midPos; private _vectorDir = vectorDir _helicopter; private _vectorUp = vectorUp _helicopter; -_helicopter flyInHeight 0; - private _interval = 0; private _time = 0; private _angleStep = 0.25; @@ -101,30 +112,39 @@ while {_interval < 0.9999} do _velocityVector = _lineEnd vectorDiff _lineStart; _velocityVector = (vectorNormalized _velocityVector) vectorMultiply (_initialSpeed * (1 - _interval)); - if((!(alive _helicopter)) || (!(alive _driver))) exitWith {}; + if(!canMove _helicopter || !alive _driver) exitWith {}; }; -if((!(alive _helicopter)) || (!(alive _driver))) exitWith {}; +_cargoGroup leaveVehicle _helicopter; +private _cargoWP1 = _cargoGroup addWaypoint [_posDestination, 10]; +_cargoWP1 setWaypointType "MOVE"; +_cargoWP1 setWaypointBehaviour "AWARE"; +_cargoWP1 setWaypointSpeed "FULL"; +private _cargoWP2 = _cargoGroup addWaypoint [_posDestination, 50]; +_cargoWP2 setWaypointType "SAD"; +_cargoWP2 setWaypointBehaviour "COMBAT"; +_cargoGroup spawn A3A_fnc_attackDrillAI; -[_helicopter] call A3A_fnc_smokeCoverAuto; +if(!canMove _helicopter || !alive _driver) exitWith { deleteVehicle _landPad }; -(units _cargoGroup) allowGetIn false; -doGetOut (units _cargoGroup); +// Dirty hack to stop the heli lurching around near the ground +private _dismountTime = 5 + count units _cargoGroup; +[_helicopter, time + _dismountTime, _midHeight, _landPad] spawn { + params ["_heli", "_endTime", "_flyHeight", "_landPad"]; + while { time < _endTime } do { + _heli setVelocity [0,0,-0.5]; + sleep 1; + }; + _heli flyInHeight _flyHeight; + deleteVehicle _landPad; +}; +[_helicopter] call A3A_fnc_smokeCoverAuto; // Already done by GetOut handler in AIVehInit? -sleep 3; -_helicopter flyInHeight 100; +sleep _dismountTime; +// Heli RTB private _vehWP1 = _crewGroup addWaypoint [_originPos, 0]; _vehWP1 setWaypointType "MOVE"; -_vehWP1 setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; +_vehWP1 setWaypointStatements ["true", "if (local this and alive this) then { deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList }"]; _vehWP1 setWaypointBehaviour "CARELESS"; _crewGroup setCurrentWaypoint _vehWP1; - -_cargoGroup spawn A3A_fnc_attackDrillAI; -private _cargoWP1 = _cargoGroup addWaypoint [_posDestination, 1]; -_cargoWP1 setWaypointType "MOVE"; -_cargoWP1 setWaypointBehaviour "AWARE"; -_cargoWP1 setWaypointSpeed "FULL"; -private _cargoWP2 = _cargoGroup addWaypoint [_posDestination, 2]; -_cargoWP2 setWaypointType "SAD"; -_cargoWP2 setWaypointBehaviour "COMBAT"; diff --git a/A3A/addons/core/functions/AI/fn_enemyGarrison.sqf b/A3A/addons/core/functions/AI/fn_enemyGarrison.sqf new file mode 100644 index 0000000000..1a9c9eefdf --- /dev/null +++ b/A3A/addons/core/functions/AI/fn_enemyGarrison.sqf @@ -0,0 +1,83 @@ +/* + Garrison enemy group at marker and patrol or despawn + +Scope: Server or HC +Environment: Scheduled, should be spawned + +Parameters: + Group to order + Nearby friendly marker to garrison +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_group", "_marker"]; + +if (!local _group) exitWith { + Error("Called with non-local group"); + _this remoteExec ["A3A_fnc_enemyGarrison", leader _group]; +}; +if (sidesX getVariable _marker != side _group) exitWith { + Error("Target marker changed side, switching to RTB"); + [_group] spawn A3A_fnc_enemyReturnToBase; +}; +if (leader _group distance2d markerPos _marker > 500) then { + ServerInfo_1("Warning: Garrisoning group %1m from marker", leader _group distance2d markerPos _marker); +}; + +// Remove from other AI script +private _AIScriptHandle = _group getVariable "A3A_AIScriptHandle"; +if (!isNil "_AIScriptHandle") then { terminate _AIScriptHandle; _group setVariable ["A3A_AIScriptHandle", nil]; }; + +// Remove from despawner +private _despawnerHandle = _group getVariable "A3A_despawnerHandle"; +if (!isNil "_despawnerHandle") then { terminate _despawnerHandle; _group setVariable ["A3A_despawnerHandle", nil]; }; + +ServerDebug_2("Adding group %1 to garrison at %2", _group, _marker); + +// Add units to the garrison list +private _unitTypes = units _group apply { _x getVariable "unitType" }; +[_unitTypes, side _group, _marker, 0] remoteExec ["A3A_fnc_garrisonUpdate", 2]; + +// Pay resource cost now if units were from the legacy/ambient pool +// Probably shouldn't happen, but whatever +if (leader _group getVariable ["A3A_resPool", "legacy"] == "legacy") then { + [count units _group * -10, side _group, "legacy"] remoteExec ["A3A_fnc_addEnemyResources", 2]; +}; + +// Mark units as garrison +{ + _x setVariable ["A3A_resPool", "garrison", true]; + _x setVariable ["markerX", _marker, true]; + _x setVariable ["spawner", nil, true]; +} forEach units _group; + +// Shitty but functional patrol routine +[_group, _marker] spawn { + params ["_group", "_marker"]; + + _group setVariable ["A3A_AIScriptHandle", _thisScript]; + + private _mrkSize = (markerSize _marker # 0 + markerSize _marker # 1) / 2; + private _wp = _group addWaypoint [markerPos _marker, 0]; + _wp setWaypointCompletionRadius 20; + _group setCurrentWaypoint _wp; + + while {!isNull leader _group} do { + if (unitReady leader _group) then { + _wp setWaypointPosition [markerPos _marker, _mrkSize]; + _group setCurrentWaypoint _wp; + }; + sleep 30; + }; +}; + +// Delete these troops when the garrison despawns +[_group, _marker] spawn { + params ["_group", "_marker"]; + _group deleteGroupWhenEmpty true; + _group setVariable ["A3A_despawnerHandle", _thisScript]; + while {spawner getVariable _marker != 2} do { sleep 10 }; + { deleteVehicle _x } forEach units _group; +}; diff --git a/A3A/addons/core/functions/AI/fn_enemyReturnToBase.sqf b/A3A/addons/core/functions/AI/fn_enemyReturnToBase.sqf new file mode 100644 index 0000000000..65318e7f57 --- /dev/null +++ b/A3A/addons/core/functions/AI/fn_enemyReturnToBase.sqf @@ -0,0 +1,84 @@ +/* + Move an enemy group to return to the nearest unspawned base and despawn as soon as possible + Will choose appropriate base depending on occupied vehicle (if any) + If optional marker is provided, will attempt to garrison foot troops there + + NOTE: + This is pretty awful and should be reimplemented in an AI/commander/garrison rework + Fundamental problem with double-counting when adding to a despawned garrison in current system + Plus perf problems with overstuff testing, nearest marker, near spawners etc. + + Parameters: + 1. Group to order + 2. Nearby friendly marker to garrison (Optional) + + Environment: Any +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_group", ["_marker", ""]]; + +// Calling functions aren't too picky about lists of groups +if (isNull _group) exitWith {}; +if (units _group isEqualTo []) exitWith { deleteGroup _group }; + +private _fnc_nearestBase = { + params ["_group", "_potentials"]; + _potentials = _potentials select { (spawner getVariable _x == 2) and (sidesX getVariable [_x, sideUnknown] == side _group) }; + if (count _potentials == 0) exitWith {nil}; + [_potentials, leader _group] call BIS_fnc_nearestPosition; +}; + +// Remove any other AI scripts (eg. attackDrillAI +private _AIScriptHandle = _group getVariable "A3A_AIScriptHandle"; +if (!isNil "_AIScriptHandle") then { terminate _AIScriptHandle; }; // _group setVariable ["A3A_AIScriptHandle", nil] }; + +// Remove any current waypoints +// Turns out that this is actually bugged (for infantry?) and followed vs visible waypoints desync in unpredictable ways +while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; + +// Group in vehicle +if (vehicle leader _group != leader _group) exitWith +{ + [_group] spawn A3A_fnc_groupDespawner; + [vehicle leader _group] spawn A3A_fnc_vehDespawner; // probably already done, but whatever + + // Ignore captured marker, find nearest suitable base to return to + if (vehicle leader _group isKindOf "Air") then { + _marker = [_group, airportsX + ["CSAT_carrier", "NATO_carrier"]] call _fnc_nearestBase; + } else { + _marker = [_group, airportsX + outposts] call _fnc_nearestBase; + }; + if (isNil "_marker") exitWith {}; // just carry on + + { _x disableAI "AUTOCOMBAT" } forEach units _group; + _group setBehaviourStrong "AWARE"; + private _wp = _group addWaypoint [markerPos _marker, 50]; + ServerDebug_2("Group %1 with vehicle %2 returning to base", _group, typeof vehicle leader _group); + _group setCurrentWaypoint _wp; +}; + + +// Foot infantry +// If specified marker is (still) valid, garrison at it +if (_marker != "") then { + if (([_marker] call A3A_fnc_garrisonSize) - count (garrison getVariable [_marker, []]) <= 0) exitWith { _marker = "" }; + if (sidesX getVariable _marker != side _group) exitWith { _marker = "" }; + if (markerPos _marker distance2d leader _group >= 500) exitWith { _marker = "" }; +}; +if (_marker != "") exitWith { [_group, _marker] call A3A_fnc_enemyGarrison }; + +// Foot troops can retreat to any unspawned friendly location +_marker = [_group, outposts + airportsX + resourcesX + factories + seaports] call _fnc_nearestBase; +if (isNil "_marker") exitWith { + ServerDebug_1("Group %1 surrendering due to no retreat locations", _group); + { _x spawn A3A_fnc_surrenderAction } forEach units _group; +}; +[_group] spawn A3A_fnc_groupDespawner; + +{ _x disableAI "AUTOCOMBAT"; _x disableAI "TARGET"; } forEach units _group; +_group setBehaviourStrong "AWARE"; +private _wp = _group addWaypoint [markerPos _marker, 50]; +_group setCurrentWaypoint _wp; +ServerDebug_1("Group %1 returning to base on foot", _group); diff --git a/A3A/addons/core/functions/AI/fn_fleeToSide.sqf b/A3A/addons/core/functions/AI/fn_fleeToSide.sqf index 9be28a2c00..ee79967c0f 100644 --- a/A3A/addons/core/functions/AI/fn_fleeToSide.sqf +++ b/A3A/addons/core/functions/AI/fn_fleeToSide.sqf @@ -3,7 +3,7 @@ params ["_unit", "_side"]; private _marker = respawnTeamPlayer; if (_side != teamPlayer) then { _marker = respawnOccupants; - private _potentials = (outposts + airportsX + resourcesX + factories); + private _potentials = (outposts + airportsX + resourcesX + factories + seaports); _potentials = _potentials select { sidesX getVariable [_x, sideUnknown] == _side }; _potentials = _potentials select { spawner getVariable _x != 0 }; // only flee to unspawned locations if (count _potentials == 0) exitWith {}; diff --git a/A3A/addons/core/functions/AI/fn_interrogate.sqf b/A3A/addons/core/functions/AI/fn_interrogate.sqf index 3ce9b58ad5..52ed481c36 100644 --- a/A3A/addons/core/functions/AI/fn_interrogate.sqf +++ b/A3A/addons/core/functions/AI/fn_interrogate.sqf @@ -21,42 +21,24 @@ if (_unit getVariable ["interrogated", false]) exitWith {}; _unit setVariable ["interrogated", true, true]; _player globalChat "You imperialist! Tell me what you know!"; -private _chance = 0; private _side = side (group _unit); -if (_side == Occupants) then -{ - _chance = 100 - aggressionOccupants; -} -else -{ - _chance = 100 - aggressionInvaders; -}; - -_chance = _chance + 20; +private _chance = 120 - ([aggressionOccupants, aggressionInvaders] select (_side == Invaders)); sleep 5; -if ((round (random 100)) < _chance) then +if (random 100 < _chance) then { if((_unit getVariable "unitType") in FactionGet(all,"SquadLeaders")) then { - if(_unit getVariable ["hasIntel", false]) then - { - _unit globalChat "Okay, I tell you what I know"; - _unit setVariable ["hasIntel", false, true]; - ["Small", _side] spawn A3A_fnc_selectIntel; - } - else - { - _unit globalChat "I would, but I don't know anything"; - }; + _unit globalChat "Okay, I'll tell you what I know"; + ["Medium", _side] remoteExec ["A3A_fnc_selectIntel", 2]; } else { - _unit globalChat "I would, but only our squadleader may knows something"; + _unit globalChat "I don't know anything. Maybe my squad leader does."; }; } else { - _unit globalChat "Screw you, I am not telling anything!"; + _unit globalChat "Screw you, I am not telling anything!"; }; diff --git a/A3A/addons/core/functions/AI/fn_mineSweep.sqf b/A3A/addons/core/functions/AI/fn_mineSweep.sqf index f7f36559c2..c6ffa8bcc3 100644 --- a/A3A/addons/core/functions/AI/fn_mineSweep.sqf +++ b/A3A/addons/core/functions/AI/fn_mineSweep.sqf @@ -5,7 +5,8 @@ if (!isServer and hasInterface) exitWith {}; private ["_costs","_groupX","_unit","_minesX","_radiusX","_roads","_truckX","_mineX","_countX"]; private _typeExp = FactionGet(reb,"unitExp"); -_costs = server getVariable _typeExp + ([FactionGet(reb,"vehicleRepair")] call A3A_fnc_vehiclePrice); +private _typeVeh = FactionGet(reb,"vehicleLightUnarmed"); +_costs = (server getVariable _typeExp) + ([_typeVeh] call A3A_fnc_vehiclePrice); [-1,-1*_costs] remoteExec ["A3A_fnc_resourcesFIA",2]; @@ -18,7 +19,7 @@ sleep 1; _road = [getMarkerPos respawnTeamPlayer] call A3A_fnc_findNearestGoodRoad; _pos = position _road findEmptyPosition [1,30,"B_G_Van_01_transport_F"]; -_truckX = FactionGet(reb,"vehicleRepair") createVehicle _pos; +_truckX = _typeVeh createVehicle _pos; [_truckX, teamPlayer] call A3A_fnc_AIVEHinit; [_unit] spawn A3A_fnc_FIAinit; diff --git a/A3A/addons/core/functions/AI/fn_mortyAI.sqf b/A3A/addons/core/functions/AI/fn_mortyAI.sqf index 4490b300a3..3980261551 100644 --- a/A3A/addons/core/functions/AI/fn_mortyAI.sqf +++ b/A3A/addons/core/functions/AI/fn_mortyAI.sqf @@ -11,7 +11,8 @@ _morty0 setVariable ["typeOfSoldier", if (_typeX == FactionGet(reb,"staticMG")) while {(alive _morty0) and (alive _morty1)} do { waitUntil {sleep 1; {((unitReady _x) and (alive _x))} count units _groupX == count units _groupX}; - _pos = position _morty0 findEmptyPosition [1,30,_typeX]; + _pos = getPosATL _morty0 findEmptyPosition [1,30,_typeX]; + if (_pos isEqualTo []) then { sleep 10; continue }; _mortarX = _typeX createVehicle _pos; removeBackpackGlobal _morty0; removeBackpackGlobal _morty1; diff --git a/A3A/addons/core/functions/AI/fn_paradrop.sqf b/A3A/addons/core/functions/AI/fn_paradrop.sqf index 4c1dcbf419..061f84c121 100644 --- a/A3A/addons/core/functions/AI/fn_paradrop.sqf +++ b/A3A/addons/core/functions/AI/fn_paradrop.sqf @@ -39,16 +39,9 @@ private _groupPilot = group driver _vehicle; _x setBehaviour "CARELESS"; } foreach (units _groupPilot); -{ - _x setVariable ["jumpSave_Backpack", backpack _x]; - _x setVariable ["jumpSave_BackpackItems", backpackItems _x]; - removebackpack _x; -} forEach (units _groupJumper); - private _targetPosition = if(_target isEqualType "") then {getMarkerPos _target} else {_target}; private _originPosition = getMarkerPos _originMarker; -private _entryDistance = 300; _vehicle flyInHeight 1000; _vehicle setCollisionLight false; if(_vehicle isKindOf "Helicopter") then @@ -57,79 +50,73 @@ if(_vehicle isKindOf "Helicopter") then _vehicle flyInHeight 500; }; -private _normalAngle = (_originPosition getDir _targetPosition); -private _attackAngle = (random 120) - 60; -private _entryPos = []; -while {true} do -{ - _entryPos = _targetPosition getPos [_entryDistance, (_normalAngle - 180) - _attackAngle]; - if(!surfaceIsWater _entryPos) exitWith {}; - _attackAngle = (random 120) - 60; +// Try to find a position that isn't on water +private _dropPos = _targetPosition; +for "_i" from 1 to 10 do { + private _testPos = _dropPos getPos [random 150 + 150, random 360]; + if !(surfaceIsWater _testPos) exitWith { _dropPos = _testPos }; }; -private _exitPos = _targetPosition getPos [_entryDistance, _normalAngle + _attackAngle]; +private _angle = (_originPosition getDir _targetPosition); +private _entryPos = _dropPos getPos [-100, _angle]; +private _exitPos = _dropPos getPos [300, _angle]; +{ _x set [2, 500] } forEach [_entryPos, _exitPos, _originPosition]; -{ - _x set [2, 500]; -} forEach [_entryPos, _exitPos, _originPosition]; +while {count waypoints _groupPilot > 0} do { deleteWaypoint [_groupPilot, 0] }; -private _wp = _groupPilot addWaypoint [_entryPos, -1]; +private _wp = _groupPilot addWaypoint [_entryPos, 0]; _wp setWaypointType "MOVE"; -_wp setWaypointSpeed "NORMAL"; -_wp setWaypointStatements ["true", "if !(local this) exitWith {}; (vehicle this) setVariable ['dropPosReached', true];"]; +_wp setWaypointSpeed "NORMAL"; // Blackfish cannot turn at limited? -private _wp1 = _groupPilot addWaypoint [_exitPos, -1]; +private _wp1 = _groupPilot addWaypoint [_exitPos, 0]; _wp1 setWaypointType "MOVE"; _wp1 setWaypointSpeed "NORMAL"; -private _wp2 = _groupPilot addWaypoint [_originPosition, -1]; +private _wp2 = _groupPilot addWaypoint [_originPosition, 0]; _wp2 setWaypointType "MOVE"; _wp2 setWaypointSpeed "FULL"; _wp2 setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; -waitUntil {sleep 1; (_vehicle getVariable ["dropPosReached", false]) || (!alive _vehicle) || (!canMove _vehicle)}; +waitUntil {sleep 1; (currentWaypoint _groupPilot > 0) || (!alive _vehicle) || (!canMove _vehicle)}; -if(_vehicle getVariable ["dropPosReached", false]) then +if(currentWaypoint _groupPilot > 0) then { - Debug("Drop pos reached"); + ServerDebug_1("Drop pos %1 reached", _dropPos); _vehicle setCollisionLight true; { unAssignVehicle _x; //Move them into alternating left/right positions, so their parachutes are less likely to kill each other private _pos = if (_forEachIndex % 2 == 0) then {_vehicle modeltoWorld [7, -20, -5]} else {_vehicle modeltoWorld [-7, -20, -5]}; - _x setPos _pos; + _x setPosASL AGLtoASL _pos; _x spawn { - waitUntil {sleep 0.25; ((getPos _this) select 2) < 105}; - _this addBackpack "B_Parachute"; + sleep (getPosATL _this # 2 / 70); // can't fall faster than that, save some checks + waitUntil {sleep 0.25; getPosATL _this # 2 < 120}; + private _chute = createVehicle ["Steerable_Parachute_F", getPosATL _this, [], 0, "CAN_COLLIDE"]; + _this moveInDriver _chute; private _smokeGrenade = selectRandom allSmokeGrenades; private _smoke = _smokeGrenade createVehicle (getPosATL _this); waitUntil { sleep 1; isTouchingGround _this}; - _this addBackpack (_this getVariable "jumpSave_Backpack"); - { - _this addItemToBackpack _x; - } forEach (_this getVariable "jumpSave_BackpackItems"); + deleteVehicle _chute; }; sleep 0.5; } forEach units _groupJumper; }; +while {count waypoints _groupJumper > 0} do { deleteWaypoint [_groupJumper, 0] }; + +// Waiting here because Arma likes to randomly delete paratrooper waypoints on landing +waitUntil { sleep 1; isTouchingGround leader _groupJumper }; + +sleep 10; // wait until everyone else has landed + +_wpMove = _groupJumper addWaypoint [_targetPosition, 0]; +_wpMove setWaypointType "MOVE"; +_wpMove setWaypointBehaviour "AWARE"; +_groupJumper setCurrentWaypoint _wpMove; + if !(_isReinforcement) then { - private _posLeader = position (leader _groupJumper); - _posLeader set [2,0]; - private _wpRegroup = _groupJumper addWaypoint [_posLeader,0]; - _wpRegroup setWaypointType "MOVE"; - _wpRegroup setWaypointSpeed "FULL"; - _wpRegroup setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; - private _wpCharge = _groupJumper addWaypoint [_targetPosition, 50]; - _wpCharge setWaypointType "MOVE"; - _wpCharge setWaypointBehaviour "COMBAT"; - _wpCharge setWaypointStatements ["true","if !(local this) exitWith {}; {if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - _wpClear = _groupJumper addWaypoint [_targetPosition, 2]; + _wpClear = _groupJumper addWaypoint [_targetPosition, 0]; _wpClear setWaypointType "SAD"; -} -else -{ - _wp4 = _groupJumper addWaypoint [_targetPosition, 0, 0]; - _wp4 setWaypointType "MOVE"; + _groupJumper spawn A3A_fnc_attackDrillAI; }; diff --git a/A3A/addons/core/functions/AI/fn_surrenderAction.sqf b/A3A/addons/core/functions/AI/fn_surrenderAction.sqf index 6c63105594..82b904d9c8 100644 --- a/A3A/addons/core/functions/AI/fn_surrenderAction.sqf +++ b/A3A/addons/core/functions/AI/fn_surrenderAction.sqf @@ -82,15 +82,15 @@ if (_unitSide == Occupants) then { [0, 1, getPos _unit] remoteExec ["A3A_fnc_citySupportChange", 2]; }; -// check for zone capture private _markerX = _unit getVariable "markerX"; -if (!isNil "_markerX") then { [_markerX, _unitSide] remoteExec ["A3A_fnc_zoneCheck",2] }; +if (!isNil "_markerX") then { [_markerX, _unitSide] remoteExec ["A3A_fnc_zoneCheck", 2] }; + // timed cleanup functions [_unit] spawn A3A_fnc_postmortem; [_boxX] spawn A3A_fnc_postmortem; -sleep 2; // Also protects against box kills +sleep 3; // Also protects against box kills _unit allowDamage true; _unit addEventHandler ["HandleDamage", { // If unit gets injured after the delay, run away diff --git a/A3A/addons/core/functions/Base/fn_addActionBreachVehicle.sqf b/A3A/addons/core/functions/Base/fn_addActionBreachVehicle.sqf index 80e94ea767..fa62c2b01e 100644 --- a/A3A/addons/core/functions/Base/fn_addActionBreachVehicle.sqf +++ b/A3A/addons/core/functions/Base/fn_addActionBreachVehicle.sqf @@ -2,12 +2,4 @@ FIX_LINE_NUMBERS() params ["_vehicle"]; -private _type = typeOf _vehicle; - -if ( - _type in FactionGet(all,"vehiclesAPCs") - || _type in FactionGet(all,"vehiclesTanks") - || _type in FactionGet(all,"vehiclesAA") -) exitWith { - [_vehicle, ["Breach Vehicle", A3A_fnc_startBreachVehicle,nil,4,false,true,"","(isPlayer _this) && (_this == vehicle _this)",5]] remoteExec ["addAction", 0, _vehicle]; -}; +[_vehicle, ["Breach Vehicle", A3A_fnc_startBreachVehicle,nil,4,false,true,"","(isPlayer _this) && (_this == vehicle _this)",5]] remoteExec ["addAction", 0, _vehicle]; diff --git a/A3A/addons/core/functions/Base/fn_addAggression.sqf b/A3A/addons/core/functions/Base/fn_addAggression.sqf index 46e40303b2..db94f83989 100644 --- a/A3A/addons/core/functions/Base/fn_addAggression.sqf +++ b/A3A/addons/core/functions/Base/fn_addAggression.sqf @@ -6,6 +6,7 @@ Arguments: The side for which the aggro should be added The amount of aggro to add The amount of minutes the aggro should stay + True if aggro effect shouldn't be inversely scaled by playerScale Return Value: @@ -30,7 +31,8 @@ params [ ["_side", sideUnknown, [sideUnknown]], ["_aggroChange", 0, [0]], - ["_aggroTime", 0, [0]] + ["_aggroTime", 0, [0]], + ["_doNotAdjust", false, [false]] ]; _fn_convertMinutesToDecayRate = @@ -50,6 +52,8 @@ if(_aggroChange == 0) exitWith {}; waitUntil {!prestigeIsChanging}; prestigeIsChanging = true; +if (!_doNotAdjust) then { _aggroChange = _aggroChange / A3A_balancePlayerScale }; + private _decayRate = [_aggroChange, _aggroTime] call _fn_convertMinutesToDecayRate; if(gameMode != 4 && (_side == Occupants)) then diff --git a/A3A/addons/core/functions/Base/fn_addEnemyResources.sqf b/A3A/addons/core/functions/Base/fn_addEnemyResources.sqf new file mode 100644 index 0000000000..df7841a868 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_addEnemyResources.sqf @@ -0,0 +1,56 @@ + +/* +Maintainer: John Jordan + Add or remove resources from enemy faction + +Scope: Server only +Environment: Scheduled or unscheduled + +Arguments: + Positive or negative count of resources to add + Side of enemy faction to adjust + Resource pool type, currently "attack", "defence" or "legacy" +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +if (!isServer) exitWith { Error("Server-only function miscalled") }; + +params ["_count", "_side", "_type"]; + +if (_side != Occupants && _side != Invaders) exitWith { Error_1("Called with invalid side: %1", _side) }; +if (isNil "_count" or {!finite _count}) exitWith { Error("Called with invalid count") }; + +Debug_3("Adding %1 resources of type %2 to side %3", _count, _type, _side); + +if (_type isEqualTo "defence") exitWith { + if (_side == Invaders) then { + A3A_resourcesDefenceInv = A3A_resourcesDefenceInv + _count; + } else { + A3A_resourcesDefenceOcc = A3A_resourcesDefenceOcc + _count; + }; +}; +if (_type isEqualTo "attack") exitWith { + if (_side == Invaders) then { + A3A_resourcesAttackInv = A3A_resourcesAttackInv + _count; + } else { + A3A_resourcesAttackOcc = A3A_resourcesAttackOcc + _count; + }; +}; +if (_type isEqualTo "legacy") exitWith { + [_count/2, _side, "defence"] call A3A_fnc_addEnemyResources; + [_count/2, _side, "attack"] call A3A_fnc_addEnemyResources; +}; + +Error_1("Called with unknown type: %1", _type); + +/* +private _varName = call { + if (_type == "defence") exitWith { ["A3A_resourcesDefenceOcc", "A3A_resourcesDefenceInv"] select (_side == Invaders) }; + if (_type == "attack") exitWith { ["A3A_resourcesAttackOcc", "A3A_resourcesAttackInv"] select (_side == Invaders) }; +}; + +if (isNil "_varName") exitWith {}; + +isNil { missionNamespace setVariable [_varName, (missionNamespace getVariable _varName) + _count, true] }; +*/ \ No newline at end of file diff --git a/A3A/addons/core/functions/Base/fn_addRecentDamage.sqf b/A3A/addons/core/functions/Base/fn_addRecentDamage.sqf new file mode 100644 index 0000000000..923937f540 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_addRecentDamage.sqf @@ -0,0 +1,22 @@ +/* Adds an entry to the enemy recent damage records on the server + +Scope: Server +Environment: Preferably unscheduled + +Arguments: + Side that took the damage, must be occupants or invaders + Position that damage was taken + Resource value of damage, max 999 +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +if (!isServer) exitWith { Error("Server-only function miscalled") }; + +params ["_side", "_pos", "_value"]; + +if (_side != Occupants && _side != Invaders) exitWith { Error_1("Called with invalid side: %1", _side) }; + +private _killPosValue = [_pos#0, _pos#1, 1000*20 + round _value]; // upper part is a time in minutes, lower part is value +([A3A_recentDamageOcc, A3A_recentDamageInv] select (_side == Invaders)) pushBack _killPosValue; diff --git a/A3A/addons/core/functions/Base/fn_aggressionUpdateLoop.sqf b/A3A/addons/core/functions/Base/fn_aggressionUpdateLoop.sqf index b7e5a37651..03e7224d92 100644 --- a/A3A/addons/core/functions/Base/fn_aggressionUpdateLoop.sqf +++ b/A3A/addons/core/functions/Base/fn_aggressionUpdateLoop.sqf @@ -1,26 +1,18 @@ -/* This loop updates the aggression every minute +/* This loop updates the aggression and various balance parameters every minute, and generates attacks - Execution on: Server +Environment: Server, spawned - Scope: Internal - - Params: - None - - Returns: - Nothing +Arguments: + None */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() while {true} do { - sleep 60; + A3A_activePlayerCount = count ((allPlayers - entities "HeadlessClient_F") select { !(_x getVariable ["isAFK", false]) }); //Sleep if no player is online - if (isMultiplayer && (count (allPlayers - (entities "HeadlessClient_F")) == 0)) then - { - waitUntil {sleep 10; (count (allPlayers - (entities "HeadlessClient_F")) > 0)}; - }; + if (A3A_activePlayerCount == 0) then { sleep 60; continue }; waitUntil {!prestigeIsChanging}; prestigeIsChanging = true; @@ -38,49 +30,89 @@ while {true} do prestigeIsChanging = false; [] call A3A_fnc_calculateAggression; + // Update the recent kill lists, clear out expired entries + { _x set [2, _x#2 - 1000] } forEach A3A_recentDamageOcc; + { _x set [2, _x#2 - 1000] } forEach A3A_recentDamageInv; + A3A_recentDamageOcc = A3A_recentDamageOcc select { _x#2 > 0 }; + A3A_recentDamageInv = A3A_recentDamageInv select { _x#2 > 0 }; + + // Key balance numbers! + // players ^ 0.8 because we have some enemy skill scaling, plus proportionally lower activity with higher player counts + private _lastScale = A3A_balancePlayerScale; + A3A_balancePlayerScale = (A3A_activePlayerCount ^ 0.8 + 1 + tierWar / 4) / 6; // Normalized to 1 == 5 players @ war tier 6 + A3A_balancePlayerScale = A3A_balancePlayerScale * A3A_enemyBalanceMul; + A3A_balanceVehicleCost = 100 + tierWar * 10; // pretty close to true + A3A_balanceResourceRate = A3A_balancePlayerScale * A3A_balanceVehicleCost; // base resources gained per 10 minutes + // back off the tier scaling a bit for reb vs occ vs inv, because you get some natural tier scaling due to attack choice + if (gameMode == 1) then { A3A_balanceResourceRate = A3A_balanceResourceRate * (1 - tierWar / 35) }; + publicVariable "A3A_balancePlayerScale"; // needed for determining enemy skill on headless clients + + // Rescale defence resources when player count or difficulty changes + A3A_resourcesDefenceOcc = A3A_resourcesDefenceOcc * A3A_balancePlayerScale / _lastScale; + A3A_resourcesDefenceInv = A3A_resourcesDefenceInv * A3A_balancePlayerScale / _lastScale; + + // Old balance param still used for marker spawning decisions at the moment + difficultyCoef = floor (A3A_activePlayerCount / 5); + publicVariable "difficultyCoef"; + if(gameMode != 4) then { - //Update attack countdown for occupants and execute attack if needed - attackCountdownOccupants = attackCountdownOccupants - (60 * (0.5 + (aggressionOccupants/100))); - if (attackCountdownOccupants < 0) then + private _aggroMul = [1.0 + aggressionOccupants/200, 0.5 + aggressionOccupants/200] select (gameMode != 1); + private _resRateDef = _aggroMul * A3A_balanceResourceRate / 10; + private _resRateAtk = _aggroMul * A3A_balanceResourceRate * A3A_enemyAttackMul / 15; // Attack rate is 2/3 of defence + + private _noAirport = -1 == airportsX findIf { sidesX getVariable _x == Occupants }; + if (_noAirport) then { _resRateDef = _resRateDef * 0.6; _resRateAtk = _resRateAtk * 0.6 }; + + // Move some attack resources to or from defence depending on defence resource level + private _maxDef = _resRateDef*100; + private _shift = linearConversion [0, _maxDef, A3A_resourcesDefenceOcc, -0.5, 0.5, true]; + _resRateDef = _resRateDef - _resRateAtk * _shift; + _resRateAtk = _resRateAtk + _resRateAtk * _shift; + + Debug_4("Adding %1 def resources to %2 and %3 atk resources to %4", _resRateDef, A3A_resourcesDefenceOcc, _resRateAtk, A3A_resourcesAttackOcc); + A3A_resourcesDefenceOcc = (A3A_resourcesDefenceOcc + _resRateDef) min _maxDef; + A3A_resourcesAttackOcc = A3A_resourcesAttackOcc + _resRateAtk; + + if (A3A_resourcesAttackOcc > 0 && !bigAttackInProgress) then { - attackCountdownOccupants = 0; - if (!bigAttackInProgress) then - { - [Occupants] spawn A3A_fnc_rebelAttack; - } - else - { - [600, Occupants] call A3A_fnc_timingCA; + private _success = [Occupants] call A3A_fnc_chooseAttack; + if (!_success) then { + // something went wrong, don't spam + A3A_resourcesAttackOcc = A3A_resourcesAttackOcc - _resRateAtk*10; }; - } - else - { - //timingCA broadcasts the value in the if case - publicVariable "attackCountdownOccupants"; }; }; if (gameMode != 3) then { - //Update attack countdown for invaders and execute attack if needed - attackCountdownInvaders = attackCountdownInvaders - (60 * (0.5 + (aggressionInvaders/100))); - if (attackCountdownInvaders < 0) then + private _aggroMul = [1.0 + aggressionInvaders/200, 0.5 + aggressionInvaders/200] select (gameMode != 1); + private _resRateDef = _aggroMul * A3A_invaderBalanceMul * A3A_balanceResourceRate / 10; + private _resRateAtk = _aggroMul * A3A_invaderBalanceMul * A3A_balanceResourceRate * A3A_enemyAttackMul / 15; + + private _noAirport = -1 == airportsX findIf { sidesX getVariable _x == Invaders }; + if (_noAirport) then { _resRateDef = _resRateDef * 0.2 }; // Invaders continue attacking but stop defending + + // Move some attack resources to or from defence depending on defence resource level + private _maxDef = _resRateDef*100; + private _shift = linearConversion [0, _maxDef, A3A_resourcesDefenceInv, -0.5, 0.5, true]; + _resRateDef = _resRateDef - _resRateAtk * _shift; + _resRateAtk = _resRateAtk + _resRateAtk * _shift; + + Debug_4("Adding %1 def resources to %2 and %3 atk resources to %4", _resRateDef, A3A_resourcesDefenceInv, _resRateAtk, A3A_resourcesAttackInv); + A3A_resourcesDefenceInv = (A3A_resourcesDefenceInv + _resRateDef) min _maxDef; + A3A_resourcesAttackInv = A3A_resourcesAttackInv + _resRateAtk; + + if (A3A_resourcesAttackInv > 0 && !bigAttackInProgress) then { - attackCountdownInvaders = 0; - if (!bigAttackInProgress) then - { - [Invaders] spawn A3A_fnc_rebelAttack; - } - else - { - [600, Invaders] call A3A_fnc_timingCA; + private _success = [Invaders] call A3A_fnc_chooseAttack; + if (!_success) then { + // something went wrong, don't spam + A3A_resourcesAttackInv = A3A_resourcesAttackInv - _resRateAtk*10; }; - } - else - { - //timingCA broadcasts the value in the if case - publicVariable "attackCountdownInvaders"; }; }; + + sleep 60; }; + diff --git a/A3A/addons/core/functions/Base/fn_airspaceControl.sqf b/A3A/addons/core/functions/Base/fn_airspaceControl.sqf index 7155e1054f..010a8fd8f6 100644 --- a/A3A/addons/core/functions/Base/fn_airspaceControl.sqf +++ b/A3A/addons/core/functions/Base/fn_airspaceControl.sqf @@ -75,17 +75,22 @@ private _fn_sendSupport = { if(side _x == _markerSide) then { - _x reveal [_vehicle, 4]; + _x reveal [_vehicle, 4]; // TODO: doesn't actually work, needs remoteExec }; } forEach allGroups; - private _revealValue = [getMarkerPos _marker, _markerSide] call A3A_fnc_calculateSupportCallReveal; + //Take actions against the aircraft + // Let support system decide whether it's worth reacting to + private _revealValue = [getMarkerPos _marker, _markerSide] call A3A_fnc_calculateSupportCallReveal; + [_markerSide, _vehicle, markerPos _marker, 4, _revealValue] remoteExec ["A3A_fnc_requestSupport", 2]; + +/* switch (_airType) do { case (MIL_HELI): { Debug_3("Rebel military helicopter %1 detected by %2 (side %3), sending support now!", _vehicle, _marker, _markerSide); - [_vehicle, 4, ["SAM", "ASF", "GUNSHIP"], _markerSide, _revealValue] remoteExec ["A3A_fnc_sendSupport", 2]; + [_vehicle, _markerSide, markerPos _marker, 4, _revealValue] remoteExec ["A3A_fnc_requestSupport", 2]; }; case (JET): { @@ -97,6 +102,7 @@ private _fn_sendSupport = Debug_3("Rebel civil helicopter %1 detected by %2 (side %3), revealed for all groups!", _vehicle, _marker, _markerSide); }; }; +*/ }; private _fn_checkNoFlyZone = diff --git a/A3A/addons/core/functions/Base/fn_arePositionsConnected.sqf b/A3A/addons/core/functions/Base/fn_arePositionsConnected.sqf index eb37e21810..2bfab9af0b 100644 --- a/A3A/addons/core/functions/Base/fn_arePositionsConnected.sqf +++ b/A3A/addons/core/functions/Base/fn_arePositionsConnected.sqf @@ -25,11 +25,8 @@ params ["_pos2", [0,0,0], ["", []]] ]; -if (_pos1 isEqualType "") then {_pos1 = getMarkerPos _pos1}; -if (_pos2 isEqualType "") then {_pos2 = getMarkerPos _pos2}; - -private _node1 = [_pos1] call A3A_fnc_getNearestNavPoint; -private _node2 = [_pos2] call A3A_fnc_getNearestNavPoint; +private _node1 = if (_pos1 isEqualType "") then {[_pos1] call A3A_fnc_getMarkerNavPoint} else {[_pos1] call A3A_fnc_getNearestNavPoint}; +private _node2 = if (_pos2 isEqualType "") then {[_pos2] call A3A_fnc_getMarkerNavPoint} else {[_pos2] call A3A_fnc_getNearestNavPoint}; private _result = [_node1, _node2] call A3A_fnc_areNodesConnected; _result; diff --git a/A3A/addons/core/functions/Base/fn_buildHQ.sqf b/A3A/addons/core/functions/Base/fn_buildHQ.sqf index ac6776cbb2..394bd3b1af 100644 --- a/A3A/addons/core/functions/Base/fn_buildHQ.sqf +++ b/A3A/addons/core/functions/Base/fn_buildHQ.sqf @@ -19,7 +19,7 @@ petros setBehaviour "SAFE"; // Put petros back on the server, otherwise might cause issues on disconnect [group petros, 2] remoteExec ["setGroupOwner", 2]; -[getPos petros] call A3A_fnc_relocateHQObjects; +[getPos petros, false] remoteExec ["A3A_fnc_relocateHQObjects", 2]; if (isNil "placementDone") then {placementDone = true; publicVariable "placementDone"}; sleep 5; diff --git a/A3A/addons/core/functions/Base/fn_chooseAttack.sqf b/A3A/addons/core/functions/Base/fn_chooseAttack.sqf new file mode 100644 index 0000000000..bdb7038345 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_chooseAttack.sqf @@ -0,0 +1,154 @@ +/* +Maintainer: John Jordan + Choose and launch an appropriate attack + +Arguments: + Source side for attack + +Return value: + false if no valid attack was found +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side"]; + +Info_1("Starting attack choice script for side %1", _side); + + +// Make a weighted list of rebel attack targets +private _targetsAndWeights = [teamPlayer, _side] call A3A_fnc_findAttackTargets; +_targetsAndWeights params ["_targets", "_weights"]; + +// Give targets within mission distance higher weight +// Returns total multiplier due to this adjustment +private _rebWeightMul = call { + if (_targets isEqualTo []) exitWith {1}; + private _totalW = 0; private _distW = 0; + private _hqPos = markerPos "Synd_HQ"; + { + _totalW = _totalW + _x; + if (markerPos (_targets#_forEachIndex#0) distance2d _hqPos > distanceMission) then { continue }; + _distW = _distW + _x; + _weights set [_forEachIndex, _x * A3A_attackMissionDistMul]; + } forEach _weights; + 1 + _distW * (A3A_attackMissionDistMul - 1) / _totalW; +}; + +// Add in the targets for the other enemy side +if (gameMode == 1) then +{ + private _enemySide = [Occupants, Invaders] select (_side == Occupants); + private _targetsAndWeightsEnemy = [_enemySide, _side] call A3A_fnc_findAttackTargets; + if (_targetsAndWeightsEnemy#0 isEqualTo []) exitWith {}; + + // Reduce chance of attacking rebels a bit at lower war tiers & aggro + private _aggro = [aggressionOccupants, aggressionInvaders] select (_side == Invaders); + private _weightFactor = (0.4 + tierWar/30 + _aggro/200) / _rebWeightMul; + _weights = _weights apply { _x * _weightFactor }; + + _targets append (_targetsAndWeightsEnemy#0); + _weights append (_targetsAndWeightsEnemy#1); +}; + +if (_targets isEqualTo []) exitWith { + Info_1("Aborting attack by %1 because no targets available", _side); + false; +}; + +Debug("Final target choice list:"); +{ + Debug_2("Target: weight %1, %2", (_weights#_forEachIndex) toFixed 3, _x); +} forEach _targets; + +// Cull anything worse than 10:1 value ratio, otherwise we'll launch some really stupid attacks occasionally +private _minWeight = selectMax _weights / 10; +private _culledTargets = []; +{ + private _weight = _weights select _forEachIndex; + if (_weight > _minWeight) then { _culledTargets append [_x, _weight] }; +} forEach _targets; + + +// Now we just pick a target +private _target = selectRandomWeighted _culledTargets; +_target params ["_targetMrk", "_originMrk", "_targetValue", "_localThreat", "_flyoverThreat", "_countLandAttackBases"]; +Debug_1("Selected attack is %1", _target); + +// Only need to check stuff that would actually break +if (sidesX getVariable _targetMrk == _side) exitWith { + Info_1("Aborting attack because target (%1) already captured", _targetMrk); + false; +}; +if (sidesX getVariable _originMrk != _side) exitWith { + // do we check spawner status too? + Info_1("Aborting attack because origin (%1) changed sides", _originMrk); + false; +}; + + +if (_targetMrk in citiesX) exitWith { + if (_side == Invaders) then { + // Punishment, unsimulated + Info_2("Starting punishment mission from %1 to %2", _originMrk, _targetMrk); + [_targetMrk, _originMrk] spawn A3A_fnc_invaderPunish; + } else { + // Supply convoy, unsimulated + // Do we allow these even if there's already a convoy? Probably not harmful. + Info_2("Sending supply convoy from %1 to %2", _originMrk, _targetMrk); + [[_targetMrk, _originMrk, "Supplies", "attack"],"A3A_fnc_convoy"] call A3A_fnc_scheduler; + }; + true; +}; + +if (_targetMrk == "Synd_HQ") exitWith { + Info_2("Starting HQ attack from %1", _originMrk); + [_side, _originMrk] spawn A3A_fnc_attackHQ; + true; +}; + +// Otherwise it's a major attack. Then we need to decide whether to simulate: +if((spawner getVariable _targetMrk) != 2 || (sidesX getVariable _targetMrk) == teamPlayer) then +{ + // Sending real attack, execute the fight + private _waves = round (1 + random 1 + _localThreat / 1000); // TODO: magic number + Info_3("Starting waved attack with %1 waves from %2 to %3", _waves, _originMrk, _targetMrk); + [_targetMrk, _originMrk, _waves] spawn A3A_fnc_wavedAttack; + true; +} +else +{ + // Get the available defence resources + private _defSide = [Occupants, Invaders] select (_side == Occupants); + private _defResources = [_defSide, _side, _targetMrk, 1] call A3A_fnc_maxDefenceSpend; // might need multiplier? + + // subtract that from defender and equal quantity for attacker + [-_defResources, _defSide, "defence"] call A3A_fnc_addEnemyResources; + + // land units are a bit cheaper, attack is generally more expensive than defence + private _atkResources = _defResources + _localThreat + _flyoverThreat; + _atkResources = _atkResources * (0.75 + 2^(-_countLandAttackBases)); + [-_atkResources, _side, "attack"] call A3A_fnc_addEnemyResources; + + // Flip marker and add garrison once flipped + [_side, _targetMrk] spawn A3A_fnc_markerChange; // add simulation param here? or just rely on spawn status? + Info_4("Simulated capture of %1 by %2, atk resources %3, def resources %4", _targetMrk, _side, _atkResources, _defResources); + + sleep 10; + if (sidesX getVariable _targetMrk != _side) exitWith { + Error_2("%1 still not switched to side %2 after 10 seconds", _targetMrk, _side); + false; + }; + + // Get the garrison for free because we already paid for them in the simulated attack + private _maxTroops = 12 max round ((0.5 + random 0.5) * ([_targetMrk] call A3A_fnc_garrisonSize)); + private _soldiers = []; + private _faction = Faction(_side); + while {count _soldiers < _maxTroops} do { + _soldiers append selectRandom ((_faction get "groupsSquads") + (_faction get "groupsMedium")); + }; + _soldiers resize _maxTroops; + [_soldiers, _side, _targetMrk, 0] spawn A3A_fnc_garrisonUpdate; + true; +}; + diff --git a/A3A/addons/core/functions/Base/fn_chooseAttackType.sqf b/A3A/addons/core/functions/Base/fn_chooseAttackType.sqf deleted file mode 100644 index 98a8a7d27c..0000000000 --- a/A3A/addons/core/functions/Base/fn_chooseAttackType.sqf +++ /dev/null @@ -1,64 +0,0 @@ -params ["_posDestination", "_side", ["_supportName", "Small attack"]]; - -/* Chooses the type of attack or QRF used against the destination position - - Execution on: HC or Server - - Scope: Internal - - Parameters: - _posDestination: POSITION : The target destination - _side: SIDE : The attacking side - _supportName: STRING : The callname of the support (Optional: default is "Small attack") - - Returns: - _typeOfAttack: STRING : The type of the attack, "" if no attack should happen -*/ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -//Search for nearby enemies -private _enemyGroups = allGroups select -{ - (side _x != _side) && - {side _x != civilian && - {(getPos (leader _x) distance2D _posDestination) < distanceSPWN2}} -}; -private _nearEnemies = []; -{ - _nearEnemies append ((units _x) select {alive _x}); -} forEach _enemyGroups; - -//Select the type of attack (or more precise against what the attack will fight) -private _typeOfAttack = "Normal"; -{ - if !(isNull (objectParent _x)) then - { - private _enemyVehicle = objectParent _x; - if (_enemyVehicle isKindOf "Plane") exitWith - { - _typeOfAttack = "Air" - }; - if (_enemyVehicle isKindOf "Helicopter") then - { - _weapons = getArray (configfile >> "CfgVehicles" >> (typeOf _enemyVehicle) >> "weapons"); - if (_weapons isEqualType []) then - { - if (count _weapons > 1) then - { - _typeOfAttack = "Air" - }; - }; - } - else - { - if (_enemyVehicle isKindOf "Tank") then - { - _typeOfAttack = "Tank" - }; - }; - }; - if (_typeOfAttack != "Normal") exitWith {}; -} forEach _nearEnemies; - -_typeOfAttack; diff --git a/A3A/addons/core/functions/Base/fn_economicsAI.sqf b/A3A/addons/core/functions/Base/fn_economicsAI.sqf deleted file mode 100644 index cb85bfaa7f..0000000000 --- a/A3A/addons/core/functions/Base/fn_economicsAI.sqf +++ /dev/null @@ -1,88 +0,0 @@ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -//Original Author: Barbolani -//Edited and updated by the Antstasi Community Development Team - -params [["_timeInHours", 1/6], ["_occScale", 1], ["_invScale", 1.2]]; - -// Increase one type by _increase*_typeCoeff, if total of types is lower than _baseCap*_typeCoeff -_fnc_economics = { - params ["_types", "_typeCoeff", "_baseCap", "_increase"]; - - if (_types isEqualTo []) exitWith {}; - - isNil { - private _totalItems = 0; - { - // fractions don't count towards cap - _totalItems = _totalItems + floor (timer getVariable [_x, 0]); - } forEach _types; - - if (_totalItems < _typeCoeff * _baseCap) then { - private _type = selectRandom _types; - private _currentItems = timer getVariable [_type, 0]; - timer setVariable [_type, _currentItems + _typeCoeff * _increase, true]; - }; - }; -}; - -// Community with ~30 players killed roughly 2 APCs per hour, probably similar for attack helis -// However they weren't spawning QRFs or singleAttacks due to maxUnits bugs, so this is probably low -// Air vehicles set fairly high because we're using a lot of them since 2.4 -// Coeff 1.0 means one vehicle per hour with 9 players @ tierWar 7, or two vehicles per hour for 26 players. - -// 9 players @ tierWar 7 => balanceScale 1 -private _playerScale = call A3A_fnc_getPlayerScale; -private _balanceScale = _playerScale * (3 + tierWar) / 10; - -//--------------------------------------Occupants-------------------------------------------------- -private _airbases = { sidesX getVariable [_x, sideUnknown] == Occupants } count airportsX; -private _outposts = { sidesX getVariable [_x, sideUnknown] == Occupants } count outposts; -private _seaports = { sidesX getVariable [_x, sideUnknown] == Occupants } count seaports; - -private _airCap = _occScale * _balanceScale * (4 + _airbases*2); -private _groundCap = _occScale * _balanceScale * (4 + _airbases + _outposts*0.5); -private _increase = _occScale * _balanceScale * _timeInHours; - -[FactionGet(occ,"staticAT"), 1.0, _groundCap, _increase] call _fnc_economics; -[FactionGet(occ,"staticAA"), 1.0, _groundCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesAPCs"), 1.8, _groundCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesTanks"), 0.6, _groundCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesAA"), 0.6, _groundCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesArtillery"), 0.3, _groundCap, _increase] call _fnc_economics; // not used atm? -[FactionGet(occ,"vehiclesGunBoats"), 1.0, _balanceScale * (2 + _seaports*2), _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesPlanesCAS"), 0.25, _airCap, _increase] call _fnc_economics; // only used for major attacks -[FactionGet(occ,"vehiclesPlanesAA"), 0.25, _airCap, _increase] call _fnc_economics; // only used for major attacks -[FactionGet(occ,"vehiclesPlanesTransport"), 1.5, _airCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesHelisTransport"), 2.5, _airCap, _increase] call _fnc_economics; -[FactionGet(occ,"vehiclesHelisAttack"), 1.2, _airCap, _increase] call _fnc_economics; - -private _natoArray = flatten [FactionGet(occ,"staticAT"), FactionGet(occ,"staticAA"), FactionGet(occ,"vehiclesAPCs"), FactionGet(occ,"vehiclesTanks"), FactionGet(occ,"vehiclesAA"), FactionGet(occ,"vehiclesGunBoats"), FactionGet(occ,"vehiclesPlanesCAS"), FactionGet(occ,"vehiclesPlanesAA"), FactionGet(occ,"vehiclesPlanesTransport"), FactionGet(occ,"vehiclesHelisTransport"), FactionGet(occ,"vehiclesHelisAttack"), FactionGet(occ,"vehiclesArtillery")]; -_natoArray = _natoArray apply { [_x, timer getVariable [_x, 0]] }; -DebugArray("Occupants arsenal", _natoArray); - -//--------------------------------------Invaders--------------------------------------------------- -_airbases = { sidesX getVariable [_x, sideUnknown] == Invaders } count airportsX; -_outposts = { sidesX getVariable [_x, sideUnknown] == Invaders } count outposts; -_seaports = { sidesX getVariable [_x, sideUnknown] == Invaders } count seaports; - -_airCap = _invScale * _balanceScale * (4 + _airbases*2); -_groundCap = _invScale * _balanceScale * (4 + _airbases + _outposts*0.5); -_increase = _invScale * _balanceScale * _timeInHours; - -[FactionGet(inv,"staticAT"), 1.0, _groundCap, _increase] call _fnc_economics; -[FactionGet(inv,"staticAA"), 1.0, _groundCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesAPCs"), 1.8, _groundCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesTanks"), 0.6, _groundCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesAA"), 0.6, _groundCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesArtillery"), 0.3, _groundCap, _increase] call _fnc_economics; // not used atm? -[FactionGet(inv,"vehiclesGunBoats"), 1.0, _balanceScale * (2 + _seaports*2), _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesPlanesCAS"), 0.25, _airCap, _increase] call _fnc_economics; // only used for major attacks -[FactionGet(inv,"vehiclesPlanesAA"), 0.25, _airCap, _increase] call _fnc_economics; // only used for major attacks -[FactionGet(inv,"vehiclesPlanesTransport"), 1.5, _airCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesHelisTransport"), 2.5, _airCap, _increase] call _fnc_economics; -[FactionGet(inv,"vehiclesHelisAttack"), 1.2, _airCap, _increase] call _fnc_economics; - -private _csatArray = flatten [FactionGet(inv,"staticAT"), FactionGet(inv,"staticAA"), FactionGet(inv,"vehiclesAPCs"), FactionGet(inv,"vehiclesTanks"), FactionGet(inv,"vehiclesAA"), FactionGet(inv,"vehiclesGunBoats"), FactionGet(inv,"vehiclesPlanesCAS"), FactionGet(inv,"vehiclesPlanesAA"), FactionGet(inv,"vehiclesPlanesTransport"), FactionGet(inv,"vehiclesHelisTransport"), FactionGet(inv,"vehiclesHelisAttack"), FactionGet(inv,"vehiclesArtillery")]; -_csatArray = _csatArray apply { [_x, timer getVariable [_x, 0]] }; -DebugArray("Invaders arsenal", _csatArray); diff --git a/A3A/addons/core/functions/Base/fn_findAttackTargets.sqf b/A3A/addons/core/functions/Base/fn_findAttackTargets.sqf new file mode 100644 index 0000000000..52b999ff51 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_findAttackTargets.sqf @@ -0,0 +1,206 @@ +/* +Maintainer: John Jordan + Generates possible attack targets and weights given target and attacking sides + +Arguments: + Target side + Attacking side + +Return Value: + [targets, weights] + Where each element of targets is an array of: + [targetMarker, sourceMarker, value, localThreat, flyoverThreat, countLandAttackBases] +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_targetSide", "_side"]; + + +private _possibleStartBases = airportsX select {sidesX getVariable [_x, sideUnknown] == _side && [_x] call A3A_fnc_airportCanAttack}; +_possibleStartBases pushBack (["NATO_carrier", "CSAT_carrier"] select (_side == Invaders)); +private _airportPositions = _possibleStartBases apply { markerPos _x }; + +private _possibleTargets = airportsX + outposts + seaports + factories + resourcesX; +if (_targetSide == teamPlayer) then {_possibleTargets = _possibleTargets + citiesX}; +_possibleTargets = _possibleTargets select {sidesX getVariable [_x,sideUnknown] == _targetSide}; + +// Add rebel HQ as attack target if the enemy side knows about it +private _hqInfo = [A3A_curHQInfoOcc, A3A_curHQInfoInv] select (_side == Invaders); +if (_targetSide == teamPlayer and _hqInfo >= 1) then { _possibleTargets pushBack "Synd_HQ" }; + +if (count _possibleTargets == 0 || count _possibleStartBases == 0) exitWith { + Info("Attack found no suitable targets or no suitable start bases, aborting!"); [[], []]; +}; +Debug_2("%1 possible targets for attack found, possible start points are %2", count _possibleTargets, _possibleStartBases); + + +//**************** Data preparation ************************************************************* + +// Build X/Y/threat array for all enemy locations +private _markersXYT = []; +private _maxThreatDist = distanceForAirAttack + 1000; +{ + private _markerSide = sidesX getVariable [_x, sideUnknown]; + if (_markerSide == _side) then { continue }; + if (gameMode != 1 && _markerSide != _targetSide) then { continue }; + if (_airportPositions inAreaArray [markerPos _x, _maxThreatDist, _maxThreatDist] isEqualTo []) then { continue }; + + private _threat = 10 * count (garrison getVariable [_x, []]); + if (_markerSide == teamPlayer) then { + _threat = _threat + 50 * count (staticsToSave inAreaArray _x); + } else { + // based on typical static count + _threat = _threat + call { + if (_x in controlsX or _x in seaports) exitWith { 50 }; + if (_x in outposts) exitWith { 150 }; + if (_x in airportsX) exitWith { 600 }; + 0; + }; + }; + //Debug_2("Marker %1, threat %2", _x, _threat); + if (_threat == 0) then { continue }; + _markersXYT pushBack [markerPos _x # 0, markerPos _x # 1, _threat]; +} forEach markersX; + + +// use these for target value determination +private _radioTowers = antennas + antennasDead; + +private _lowAir = Faction(_side) getOrDefault ["attributeLowAir", false]; + +// Build list of friendly bases with ground attack capability +// airportCanAttack state might change during the actual attack, so this is only approximate +private _landBases = []; +{ + if (sidesX getVariable [_x, sideUnknown] != _side) then { continue }; + if ([_x] call A3A_fnc_airportCanAttack) then { _landBases pushBack _x }; +} forEach (airportsX + outposts); + + +private _rebelPlayers = allPlayers - (entities "HeadlessClient_F"); +private _rebelAISpawners = (units teamPlayer - _rebelPlayers) select { _x getVariable ["spawner", false] }; + +//**************** Actual target search ************************************************************* + +private _finalTargets = []; +private _finalWeights = []; +{ + // Early-out if there are no airbases within range + if (_airportPositions inAreaArray [markerPos _x, distanceForAirAttack, distanceForAirAttack] isEqualTo []) then { continue }; + + // Target value calc + private _value = if (_x in citiesX) then { + // just base this on population? + private _baseValue = sqrt ((server getVariable _x) # 0); // Low-value but threat is probably low too due to lack of garrison + if (_side == Occupants) exitWith { _baseValue * (1.5 - tierWar / 10) }; // Occupants more likely to care about towns at low tiers + _baseValue * (tierWar / 5); // Invaders more likely to care at high tiers + } else { + private _baseValue = call { + if (_x in outposts) exitWith { [20, 25] select (count (_radioTowers inAreaArray _x) > 0) }; + if (_x == "Synd_HQ") exitWith { 60 }; + if (_x in seaports) exitWith { 20 }; + if (_x in airportsX) exitWith { [60, 90] select (count _possibleStartBases == 1) }; // If down to carrier, more important to take an airfield + if (_x in factories) exitWith { 15 }; + 10; // resources + }; + _baseValue + ([_x, true] call A3A_fnc_garrisonSize) / 2; // Bit of preference for large/defensible targets. Don't use frontline adjustment here + }; + + // calculate local target difficulty + private _target = _x; + private _targpos = markerPos _x; + private _localMarkers = _markersXYT inAreaArray [_targpos, 1500, 1500]; + private _nonLocalMarkers = _markersXYT - _localMarkers; + private _localThreat = 0; + { + private _dist = _x distance2d _targpos; + private _threat = (_x#2) * linearConversion [500, 1500, _dist, 1, 0, true]; + _localThreat = _localThreat + _threat; + if (_dist > 500) then { _nonLocalMarkers pushBack [_x#0, _x#1, (_x#2) - _threat] }; + } forEach _localMarkers; + + // If it's rebel, assume active defence. Avoid attacking enemy targets that are already under attack by rebels + if (_targetSide == teamPlayer) then { + _localThreat = _localThreat + 150; + } else { + _localThreat = _localThreat + 30 * count (_rebelPlayers inAreaArray [_targpos, 500, 500]); + }; + // Rebel AIs count either way, as they're relatively static + _localThreat = _localThreat + 10 * count (_rebelAISpawners inAreaArray [_targpos, 500, 500]); + + // Supply convoys shortcut + if (_x in citiesX and _side == Occupants) then { + private _landBase = [_x] call A3A_fnc_findBasesForConvoy; + if (_landBase == "") then { continue }; // no suitable base found + _finalTargets pushBack [_target, _landBase, _value, _localThreat, 0, 1]; + _finalWeights pushBack (_value / _localThreat^0.8) ^ 2; + continue; + }; + + // Count ground attack bases that are usable against the target + private _countLand = call { + private _targNavIndex = _target call A3A_fnc_getMarkerNavPoint; + private _suppMarkers = [_targNavIndex, _lowAir] call A3A_fnc_findLandSupportMarkers apply { _x#0 }; + count (_suppMarkers arrayIntersect _landBases); + }; + + // Check distance and add flyover threat for each airport source + private _weights = []; + private _totalWeight = 0; + private _maxWeight = 0; + { + private _basePos = markerPos _x; + private _dist = _basePos distance2d _targPos; + if (_dist > distanceForAirAttack) then { continue }; + private _midpoint = (_basePos vectorAdd _targPos) vectorMultiply 0.5; + private _targDir = _basePos getDir _targPos; + private _flyoverMarkers = _nonLocalMarkers inAreaArray [_midpoint, 1200, _dist/2, _targDir, true]; + private _sideVec = [cos _targDir, -sin _targDir, 0]; + private _flyoverThreat = 0; + { + private _dist = abs ((_x vectorDiff _basePos) vectorDotProduct _sideVec); + private _threat = (_x#2) * linearConversion [200, 1200, _dist, 1, 0, true]; + _flyoverThreat = _flyoverThreat + _threat; + if (_flyoverThreat > 300) exitWith {}; // early out + + //private _flyoverPos = _x; + //private _mrkIndex = markersX findIf { markerPos _x distance2d _flyoverPos < 10 }; + //Debug_3("From %1, dist %2 threat %3", markersX select _mrkIndex, _dist, _threat); + + } forEach _flyoverMarkers; + + //Debug_3("%1 flyover threat from %2 to %3", _flyoverThreat, _x, _target); + + if (_flyoverThreat > 300) then { continue }; + _finalTargets pushBack [_target, _x, _value, _localThreat, _flyoverThreat, _countLand]; + + private _difficulty = if (_lowAir) then { + private _distFactor = linearConversion [0, distanceForAirAttack, _dist, 0.5, 1.5, true]; + (_localThreat + 2*_flyoverThreat) * (_distFactor + 3^(-_countLand)); + } else { + private _distFactor = linearConversion [0, distanceForAirAttack, _dist, 0.65, 1, true]; + (_localThreat + 2*_flyoverThreat) * (_distFactor + 2^(-_countLand)); + }; + private _weight = (_value / _difficulty^0.8) ^ 2; // prefer high value over low difficulty a bit + //Debug_5("%1 to %2: Diff: %3, value: %4, weight: %5", _x, _target, _difficulty, _value, _weight); + + _maxWeight = _weight max _maxWeight; + _totalWeight = _totalWeight + _weight; + _weights pushBack _weight; + + } forEach _possibleStartBases; + + // Normalize so that more sources doesn't lead to higher target chance + { _finalWeights pushBack (_x * _maxWeight / _totalWeight) } forEach _weights; + +} forEach _possibleTargets; + +// Multiply up for readability +_finalWeights = _finalWeights apply { _x * 10 }; +{ + Debug_2("Target: weight %1, %2", (_finalWeights#_forEachIndex) toFixed 3, _x); +} forEach _finalTargets; + +[_finalTargets, _finalWeights]; + diff --git a/A3A/addons/core/functions/Base/fn_findBaseForQRF.sqf b/A3A/addons/core/functions/Base/fn_findBaseForQRF.sqf deleted file mode 100644 index eabe79418c..0000000000 --- a/A3A/addons/core/functions/Base/fn_findBaseForQRF.sqf +++ /dev/null @@ -1,74 +0,0 @@ -params ["_posDestination", "_side"]; - -/* Finds a base for QRF or small attacks - - Execution on: HC or Server - - Scope: Internal - - Parameters: - _posDestination: POSITION : The position which should be attacked - _side: SIDE : The attacking side - - Returns: - STRING : The name of the marker to start the attack from, "" if none available -*/ - -private _threatEvalLand = [_posDestination,_side] call A3A_fnc_landThreatEval;; - -//Start selecting the starting base -private _availableAirports = (airportsX + ["CSAT_carrier", "NATO_carrier"]) select -{ - (sidesX getVariable [_x,sideUnknown] == _side) && - {([_x,true] call A3A_fnc_airportCanAttack) && - {(getMarkerPos _x) distance2D _posDestination < distanceForAirAttack}} -}; - -if (A3A_hasIFA && (_threatEvalLand <= 15)) then -{ - _availableAirports = _availableAirports select {(getMarkerPos _x distance2D _posDestination < distanceForLandAttack)} -}; - -private _outposts = if (_threatEvalLand <= 15) then -{ - outposts select - { - (sidesX getVariable [_x,sideUnknown] == _side) && - {([_x,true] call A3A_fnc_airportCanAttack) && - {(getMarkerPos _x distance _posDestination < distanceForLandAttack) && - {[_posDestination, getMarkerPos _x] call A3A_fnc_arePositionsConnected}}} - } -} -else -{ - [] -}; - -_availableAirports = _availableAirports + _outposts; -private _nearestMarker = [(resourcesX + factories + airportsX + outposts + seaports),_posDestination] call BIS_fnc_nearestPosition; -private _markerOrigin = ""; -_availableAirports = _availableAirports select -{ - ({_x == _nearestMarker} count (killZones getVariable [_x,[]])) < 3 -}; - -private _finalOriginMarkers = []; -{ - private _vehicleSpawnPossible = ([_x, "Vehicle"] call A3A_fnc_findSpawnPosition) isEqualType []; - if(_vehicleSpawnPossible) then - { - _finalOriginMarkers pushBack _x; - }; - //If marker not spawned, released locked places - if(spawner getVariable [_x, -1] == 2) then - { - [_x] call A3A_fnc_freeSpawnPositions; - }; -} forEach _availableAirports; - -if !(_availableAirports isEqualTo []) then -{ - _markerOrigin = [_availableAirports, _posDestination] call BIS_fnc_nearestPosition; -}; - -_markerOrigin; diff --git a/A3A/addons/core/functions/Base/fn_garbageCleaner.sqf b/A3A/addons/core/functions/Base/fn_garbageCleaner.sqf index 66bdb04e58..0c117fc032 100644 --- a/A3A/addons/core/functions/Base/fn_garbageCleaner.sqf +++ b/A3A/addons/core/functions/Base/fn_garbageCleaner.sqf @@ -5,23 +5,29 @@ private _timeSinceLastGC = [[serverTime-A3A_lastGarbageCleanTime] call A3A_fnc_s ["Garbage Cleaner","Please wait for GC to finish.
Last GC was " + _timeSinceLastGC + " ago."] remoteExec ["A3A_fnc_customHint", 0]; Info("Cleaning garbage..."); -private _rebelSpawners = allUnits select { side group _x == teamPlayer && {_x getVariable ["spawner",false]} }; +private _rebelSpawners = units teamPlayer select { _x getVariable ["spawner",false] }; +_rebelSpawners pushBack petros; private _fnc_distCheck = { params["_object", "_dist"]; - private _inRange = { if (_x distance _object <= _dist) exitWith {1}; false } count _rebelSpawners; - if (_inRange == 0) then { deleteVehicle _object }; + if (_rebelSpawners inAreaArray [getPosATL _object, _dist, _dist] isEqualTo []) then { deleteVehicle _object }; }; { deleteVehicle _x } forEach allDead; { deleteVehicle _x } forEach (allMissionObjects "WeaponHolder"); { deleteVehicle _x } forEach (allMissionObjects "WeaponHolderSimulated"); -{ if (isNull attachedTo _x) then { [_x, distanceSPWN1] call _fnc_distCheck } } forEach (allMissionObjects FactionGet(occ,"surrenderCrate"));// Surrender boxes NATO -{ if (isNull attachedTo _x) then { [_x, distanceSPWN1] call _fnc_distCheck } } forEach (allMissionObjects FactionGet(inv,"surrenderCrate"));// Surrender boxes CSAT +{ if (isNull attachedTo _x) then { [_x, 500] call _fnc_distCheck } } forEach (allMissionObjects FactionGet(occ,"surrenderCrate"));// Surrender boxes NATO +{ if (isNull attachedTo _x) then { [_x, 500] call _fnc_distCheck } } forEach (allMissionObjects FactionGet(inv,"surrenderCrate"));// Surrender boxes CSAT { deleteVehicle _x } forEach (allMissionObjects "Leaflet_05_F"); // Drone drop leaflets { deleteVehicle _x } forEach (allMissionObjects "Ejection_Seat_Base_F"); // All vanilla ejection seats +// Cleanup rebel vehicles +{ + // Locked check is a hack for roadblock vehicles + if !(_x isKindOf "StaticWeapon" or locked _x > 1) then { [_x, 500] call _fnc_distCheck }; +} forEach (vehicles select {_x getVariable ["ownerSide", sideUnknown] == teamPlayer}); + if (A3A_hasACE) then { { deleteVehicle _x } forEach (allMissionObjects "ACE_bodyBagObject"); { deleteVehicle _x } forEach (allMissionObjects "UserTexture1m_F"); // ACE spraycan tags diff --git a/A3A/addons/core/functions/Base/fn_getPlayerScale.sqf b/A3A/addons/core/functions/Base/fn_getPlayerScale.sqf deleted file mode 100644 index 037e6e606e..0000000000 --- a/A3A/addons/core/functions/Base/fn_getPlayerScale.sqf +++ /dev/null @@ -1 +0,0 @@ -(8 + count (allPlayers - entities "HeadlessClient_F")) / 17; diff --git a/A3A/addons/core/functions/Base/fn_getRecentDamage.sqf b/A3A/addons/core/functions/Base/fn_getRecentDamage.sqf new file mode 100644 index 0000000000..e669bf9b33 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_getRecentDamage.sqf @@ -0,0 +1,22 @@ +/* +Maintainer: John Jordan + Returns recent losses (in resource units) taken by side within specified area + +Scope: Server only + +Arguments: + The side that took the damage (occupants or invaders) + Center position + Radius in metres + +Return value: + Recent damage taken by side within area +*/ + +params ["_side", "_center", "_radius"]; + +private _recentDamage = 0; +private _damageEvents = [A3A_recentDamageOcc, A3A_recentDamageInv] select (_side == Invaders); +_damageEvents = _damageEvents inAreaArray [_center, _radius, _radius]; // should this be related to marker size? hmm +{ _recentDamage = _recentDamage + (_x#2) % 1000 } forEach _damageEvents; +_recentDamage; diff --git a/A3A/addons/core/functions/Base/fn_getVehiclePoolForAttacks.sqf b/A3A/addons/core/functions/Base/fn_getVehiclePoolForAttacks.sqf deleted file mode 100644 index c323824f4a..0000000000 --- a/A3A/addons/core/functions/Base/fn_getVehiclePoolForAttacks.sqf +++ /dev/null @@ -1,157 +0,0 @@ -/* Returns a weighted and balanced vehicle pool for the given side and filter - - Execution on: All - - Scope: External - - Params: - _side: SIDE : The side for which the vehicle pool should be used - _filter: ARRAY of STRINGS : The bases classes of units that should be filtered out (for example ["LandVehicle"] or ["Air"]) - - Returns: - _vehiclePool: ARRAY : [vehicleName, weight, vehicleName2, weight2] -*/ - -params ["_side", ["_filter", []]]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -private _isOcc = _side isEqualTo Occupants; -private _vehicleSelection = []; - -Debug_2("Now searching for attack vehicle pool for %1 with filter %2", _side, _filter); -//In general is Invaders always a bit less chill than the occupants, they will use heavier vehicles more often and earlier -private _vehicleSelection = switch (tierWar) do { - case (1): { - [ - [_faction get "vehiclesLightArmed", if (_isOcc) then {15} else {5}], - [_faction get "vehiclesTrucks", if (_isOcc) then {10} else {15}], - [_faction get "vehiclesHelisLight", if (_isOcc) then {25} else {25}], - [_faction get "vehiclesAPCs", if (_isOcc) then {35} else {30}], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {15} else {25}] - ] - }; - case (2): { - [ - [_faction get (if (_isOcc) then {"vehiclesLightArmed"} else {"vehiclesAA"}), if (_isOcc) then {15} else {10}], - [_faction get "vehiclesHelisLight", if (_isOcc) then {25} else {15}], - [_faction get "vehiclesAPCs", 40], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {20} else {35}] - ] - }; - case (3): - { - [ - [_faction get "vehiclesHelisLight", if (_isOcc) then {15} else {5}], - [_faction get "vehiclesAPCs", 35], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {40} else {30}], - [_faction get "vehiclesAA", if (_isOcc) then {10} else {15}] - ] + (if (_isOcc) then { [] } else {[ - [_faction get "vehiclesHelisAttack", 15] - ]}); - }; - case (4): - { - [ - [_faction get "vehiclesAPCs", if (_isOcc) then {30} else {15}], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {40} else {15}], - [_faction get "vehiclesAA", 15], - [_faction get "vehiclesHelisAttack", if (_isOcc) then {15} else {20}] - ] + (if (_isOcc) then { [] } else {[ - [_faction get "vehiclesTanks", 15], - [_faction get "vehiclesPlanesTransport", 20] - ]}); - }; - case (5): - { - [ - [_faction get "vehiclesAPCs", if (_isOcc) then {20} else {15}], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {20} else {10}], - [_faction get "vehiclesAA", 15], - [_faction get "vehiclesHelisAttack", if (_isOcc) then {30} else {15}], - [_faction get "vehiclesTanks", if (_isOcc) then {15} else {20}] - ] + (if (_isOcc) then { [] } else {[ - [_faction get "vehiclesPlanesTransport", 15] - ]}); - }; - case (6): - { - [ - [_faction get "vehiclesAPCs", if (_isOcc) then {15} else {10}], - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), if (_isOcc) then {10} else {5}], - [_faction get "vehiclesAA", 10], - [_faction get "vehiclesHelisAttack", 20], - [_faction get "vehiclesTanks", if (_isOcc) then {15} else {20}], - [_faction get "vehiclesPlanesTransport", 15] - ]; - }; - case (7); - case (8); - case (9); - case (10): - { - [ - [_faction get "vehiclesAPCs", 10], - [_faction get "vehiclesAA", if (_isOcc) then {5} else {10}], - [_faction get "vehiclesHelisAttack", if (_isOcc) then {20} else {25}], - [_faction get "vehiclesTanks", if (_isOcc) then {20} else {25}], - [_faction get "vehiclesPlanesTransport", 15] - ] + (if (_isOcc) then { [ - [(_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"), 10] - ] } else { [] }); - }; -}; - -//Use this function to filter out any unwanted elements -_fn_checkElementAgainstFilter = -{ - params ["_element", "_filter"]; - - private _passed = true; - { - if(_element isKindOf _x) exitWith - { - _passed = false; - Debug_2("%1 didnt passed filter %2", _element, _x); - }; - } forEach _filter; - - _passed; -}; - -//Break unit arrays down to single vehicles -private _vehiclePool = []; -{ - if((_x select 0) isEqualType []) then - { - private _points = 0; - private _vehicleCount = count (_x select 0); - if(_vehicleCount != 0) then - { - _points = (_x select 1)/_vehicleCount; - } - else - { - Error("Found vehicle array with no defined vehicles!"); - }; - { - if(([_x, _filter] call _fn_checkElementAgainstFilter) && {[_x] call A3A_fnc_vehAvailable}) then - { - _vehiclePool pushBack _x; - _vehiclePool pushBack _points; - }; - } forEach (_x select 0); - } - else - { - if(([_x select 0, _filter] call _fn_checkElementAgainstFilter) && {[_x select 0] call A3A_fnc_vehAvailable}) then - { - _vehiclePool pushBack (_x select 0); - _vehiclePool pushBack (_x select 1); - }; - }; -} forEach _vehicleSelection; - -Debug_4("For %1 and war level %2 selected units are %3, filter was %4", _side, tierWar, _vehiclePool, _filter); - -_vehiclePool; diff --git a/A3A/addons/core/functions/Base/fn_getVehiclePoolForQRFs.sqf b/A3A/addons/core/functions/Base/fn_getVehiclePoolForQRFs.sqf deleted file mode 100644 index e6e4ad6de0..0000000000 --- a/A3A/addons/core/functions/Base/fn_getVehiclePoolForQRFs.sqf +++ /dev/null @@ -1,236 +0,0 @@ -/* Returns a weighted and balanced vehicle pool for the given side and filter - - Execution on: All - - Scope: External - - Params: - _side: SIDE : The side for which the vehicle pool should be used - _filter: ARRAY of STRINGS : The bases classes of units that should be filtered out (for example ["LandVehicle"] or ["Air"]) - - Returns: - _vehiclePool: ARRAY : [vehicleName, weight, vehicleName2, weight2] -*/ - -params ["_side", ["_filter", []]]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -private _isOcc = _side isEqualTo Occupants; - -#define EntryCommon(VEH, Q_OCC, Q_INV) [VEH, if (_isOcc) then {Q_OCC} else {Q_INV}] -#define VEH(VAR) (_faction get VAR) - -Debug_2("Now searching for QRF vehicle pool for %1 with filter %2", _side, _filter); -//In general is Invaders always a bit less chill than the occupants, they will use heavier vehicles more often and earlier -private _vehicleSelection = switch (tierWar) do -{ - //General idea: Send only ground units as players should be able to loot and grab the crate before the enemy arrives with a QRF - // JJ: As of 2.3-prerelease, this function is always called with either an air or ground filter, so air/ground balancing is not valid - case (1): - { - [ - EntryCommon(VEH("vehiclesHelisLight"), 100, 100) - ] + (if (_isOcc) then {[ - [VEH("vehiclesPolice"), 40], - [VEH("vehiclesMilitiaCars"), 30], - [VEH("vehiclesMilitiaTrucks"), 20], - [VEH("vehiclesMilitiaLightArmed"), 10] - ]} else {[ - [VEH("vehiclesLightUnarmed"), 40], - [VEH("vehiclesTrucks"), 40], - [VEH("vehiclesLightArmed"), 20] - ]}); - }; - //General idea: Enemies get airborne, police units are reduced and replaced by military units - case (2): - { - [ - EntryCommon(VEH("vehiclesHelisLight"), 100, 80), - EntryCommon(VEH("vehiclesLightUnarmed"), 15, 20), - EntryCommon(VEH("vehiclesLightArmed"), 10, 30), - EntryCommon(VEH("vehiclesTrucks"), 25, 40) - ] + (if (_isOcc) then {[ - [VEH("vehiclesPolice"), 15], - [VEH("vehiclesMilitiaCars"), 15], - [VEH("vehiclesMilitiaTrucks"), 10], - [VEH("vehiclesMilitiaLightArmed"), 10] - ]} else {[ - [VEH("vehiclesAPCs"), 10] - ]}); - }; - //General idea: No police units any more, armed vehicles and first sightings of APCs - case (3): - { - [ - EntryCommon(VEH("vehiclesHelisLight"), 80, 60), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 20, 40), - EntryCommon(VEH("vehiclesLightUnarmed"), 10, 5), - EntryCommon(VEH("vehiclesLightArmed"), 20, 45), - EntryCommon(VEH("vehiclesTrucks"), 40, 30), - EntryCommon(VEH("vehiclesAPCs"), 10, 20) - ] + (if (_isOcc) then {[ - [VEH("vehiclesMilitiaTrucks"), 10], - [VEH("vehiclesMilitiaLightArmed"), 10] - ]} else {[]}); - }; - //General idea: Unarmed vehicles vanish, trucks start to get replaced by APCs, first sighting of transport helicopters - case (4): - { - [ - EntryCommon(VEH("vehiclesHelisLight"), 50, 40), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 50, 50), - EntryCommon(VEH("vehiclesLightArmed"), 35, 40), - EntryCommon(VEH("vehiclesTrucks"), 40, 10), - EntryCommon(VEH("vehiclesAPCs"), 25, 40) - ] + (if (_isOcc) then {[]} else {[ - [VEH("vehiclesHelisAttack"), 10], - [VEH("vehiclesTanks"), 10] - ]}); - }; - //General idea: Get rid of any unarmed vehicle, Invaders start to bring the big guns - case (5): - { - [ - EntryCommon(VEH("vehiclesHelisLight"), 30, 25), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 60, 50), - EntryCommon(VEH("vehiclesLightArmed"), 30, 30), - EntryCommon(VEH("vehiclesTrucks"), 25, 10), - EntryCommon(VEH("vehiclesAPCs"), 35, 40), - EntryCommon(VEH("vehiclesTanks"), 10, 20), - EntryCommon(VEH("vehiclesHelisAttack"), 10, 15) - ] + (if (_isOcc) then {[]} else {[ - [VEH("vehiclesPlanesTransport"), 10] - ]}); - }; - //General idea: No light vehicles any more, Invaders start to bring attack helicopter - case (6): - { - [ - EntryCommon(VEH("vehiclesLightArmed"), 25, 25), - EntryCommon(VEH("vehiclesTrucks"), 15, 5), - EntryCommon(VEH("vehiclesAPCs"), 45, 45), - EntryCommon(VEH("vehiclesTanks"), 15, 20), - EntryCommon(VEH("vehiclesHelisLight"), 20, 15), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 60, 50), - EntryCommon(VEH("vehiclesPlanesTransport"), 10, 15), - EntryCommon(VEH("vehiclesHelisAttack"), 10, 20) - ] + (if (_isOcc) then {[]} else {[ - [VEH("vehiclesAA"), 5] - ]}); - }; - //General idea: Getting rid of light helis, Invaders start the endgame - case (7): - { - [ - EntryCommon(VEH("vehiclesLightArmed"), 20, 25), - EntryCommon(VEH("vehiclesTrucks"), 10, 5), - EntryCommon(VEH("vehiclesAPCs"), 50, 40), - EntryCommon(VEH("vehiclesAA"), 5, 5), - EntryCommon(VEH("vehiclesTanks"), 15, 25), - EntryCommon(VEH("vehiclesHelisLight"), 10, 10), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 55, 40), - EntryCommon(VEH("vehiclesPlanesTransport"), 20, 25), - EntryCommon(VEH("vehiclesHelisAttack"), 15, 25) - ]; - }; - //General idea, Occupants start to throw in everything, Invaders upgrade to maximum - case (8): - { - [ - EntryCommon(VEH("vehiclesLightArmed"), 15, 20), - EntryCommon(VEH("vehiclesTrucks"), 10, 5), - EntryCommon(VEH("vehiclesAPCs"), 50, 40), - EntryCommon(VEH("vehiclesAA"), 5, 10), - EntryCommon(VEH("vehiclesTanks"), 20, 25), - EntryCommon(VEH("vehiclesHelisLight"), 10, 5), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 40, 40), - EntryCommon(VEH("vehiclesPlanesTransport"), 25, 25), - EntryCommon(VEH("vehiclesHelisAttack"), 20, 25) - ]; - }; - //General idea: Occupants get access to all, invaders start to heavily rely on tanks and attack helis - case (9): - { - [ - EntryCommon(VEH("vehiclesLightArmed"), 10, 10), - EntryCommon(VEH("vehiclesTrucks"), 5, 5), - EntryCommon(VEH("vehiclesAPCs"), 50, 40), - EntryCommon(VEH("vehiclesAA"), 10, 10), - EntryCommon(VEH("vehiclesTanks"), 25, 30), - EntryCommon(VEH("vehiclesHelisLight"), 5, 5), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 35, 35), - EntryCommon(VEH("vehiclesPlanesTransport"), 25, 25), - EntryCommon(VEH("vehiclesHelisAttack"), 25, 30) - ]; - }; - //General idea: Occupants finish with a focus on infantry units supported by combat vehicles, while Invaders tend to use heavy armor - case (10): - { - [ - EntryCommon(VEH("vehiclesLightArmed"), 5, 5), - EntryCommon(VEH("vehiclesTrucks"), 5, 5), - EntryCommon(VEH("vehiclesAPCs"), 50, 45), - EntryCommon(VEH("vehiclesAA"), 10, 10), - EntryCommon(VEH("vehiclesTanks"), 30, 35), - EntryCommon(VEH("vehiclesHelisLight"), 5, 5), - EntryCommon(VEH("vehiclesHelisLight") + VEH("vehiclesHelisTransport"), 30, 30), - EntryCommon(VEH("vehiclesPlanesTransport"), 25, 25), - EntryCommon(VEH("vehiclesHelisAttack"), 25, 30) - ]; - }; -}; - -//Use this function to filter out any unwanted elements -_fn_checkElementAgainstFilter = -{ - params ["_element", "_filter"]; - - private _passed = true; - { - if(_element isKindOf _x) exitWith - { - _passed = false; - Debug_2("%1 didnt passed filter %2", _element, _x); - }; - } forEach _filter; - - _passed; -}; - -//Break unit arrays down to single vehicles -private _vehiclePool = []; -{ - if((_x select 0) isEqualType []) then - { - private _points = 0; - private _vehicleCount = count (_x select 0); - if(_vehicleCount != 0) then - { - _points = (_x select 1)/_vehicleCount; - } - else - { - Error("Found vehicle array with no defined vehicles!"); - }; - { - if(([_x, _filter] call _fn_checkElementAgainstFilter) && {[_x] call A3A_fnc_vehAvailable}) then - { - _vehiclePool pushBack _x; - _vehiclePool pushBack _points; - }; - } forEach (_x select 0); - } - else - { - if(([_x select 0, _filter] call _fn_checkElementAgainstFilter) && {[_x select 0] call A3A_fnc_vehAvailable}) then - { - _vehiclePool pushBack (_x select 0); - _vehiclePool pushBack (_x select 1); - }; - }; -} forEach _vehicleSelection; - -Debug_4("For %1 and war level %2 selected units are %3, filter was %4", _side, tierWar, _vehiclePool, _filter); - -_vehiclePool; diff --git a/A3A/addons/core/functions/Base/fn_getVehiclesAirSupport.sqf b/A3A/addons/core/functions/Base/fn_getVehiclesAirSupport.sqf new file mode 100644 index 0000000000..db0a405255 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_getVehiclesAirSupport.sqf @@ -0,0 +1,38 @@ +/* +Maintainer: John Jordan + Returns a weighted air support vehicle pool based on war level and side + Includes both classnames (attack helis) and support types (just "CAS" atm) + +Arguments: + The side for which the vehicle pool should be generated (occupants or invaders) + 1-10 range, war-level based vehicle quality + +Return value: + [vehType, weight, vehType2, weight2, ...] +*/ +params ["_side", "_level"]; +_level = (_level max 1 min 10) - 1; +private _faction = [A3A_faction_occ, A3A_faction_inv] select (_side == Invaders); + +private _fnc_addArrayToWeights = { + params ["_vehArray", "_baseWeight"]; + { _vehWeights append [_x, _baseWeight / count _vehArray] } forEach _vehArray; +}; + +private _vehWeights = []; + +private _lightAHWeight = [70, 65, 60, 55, 50, 45, 40, 35, 30, 25] select _level; +private _AHWeight = [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50] select _level; +private _casWeight = [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] select _level; + +// eventually add dive bombers? + +if (_faction get "vehiclesHelisLightAttack" isEqualTo []) then { _AHWeight = _AHWeight + _lightAHWeight }; +if (_faction get "vehiclesHelisAttack" isEqualTo []) then { _casWeight = _casWeight + _AHWeight }; +if (_faction get "vehiclesPlanesCAS" isEqualTo []) then { _AHWeight = _AHWeight + _casWeight }; + +if (_faction get "vehiclesPlanesCAS" isNotEqualTo []) then { _vehWeights append ["CAS", _casWeight] }; +[_faction get "vehiclesHelisAttack", _AHWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesHelisLightAttack", _lightAHWeight] call _fnc_addArrayToWeights; + +_vehWeights; diff --git a/A3A/addons/core/functions/Base/fn_getVehiclesGroundSupport.sqf b/A3A/addons/core/functions/Base/fn_getVehiclesGroundSupport.sqf new file mode 100644 index 0000000000..a47608f903 --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_getVehiclesGroundSupport.sqf @@ -0,0 +1,40 @@ +/* +Maintainer: John Jordan + Returns a weighted ground support vehicle pool based on war level and side + +Arguments: + The side for which the vehicle pool should be generated (occupants or invaders) + 1-10 range, war-level based vehicle quality + +Return value: + [vehType, weight, vehType2, weight2, ...] +*/ +params ["_side", "_level"]; +_level = (_level max 1 min 10) - 1; +private _faction = [A3A_faction_occ, A3A_faction_inv] select (_side == Invaders); + +private _fnc_addArrayToWeights = { + params ["_vehArray", "_baseWeight"]; + { _vehWeights append [_x, _baseWeight / count _vehArray] } forEach _vehArray; +}; + +private _vehWeights = []; + +private _milCarWeight = [50, 40, 30, 20, 10, 0, 0, 0, 0, 0] select _level; +private _carWeight = [50, 50, 50, 50, 50, 50, 50, 40, 35, 30] select _level; +private _aaWeight = [ 0, 0, 3, 5, 7, 8, 10, 12, 13, 14] select _level; +private _tankWeight = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 50] select _level; + +// filter out weak AA that shouldn't be tier-scaled (eg. Avenger, zu23) +private _vehAA = (_faction get "vehiclesAA") select { A3A_vehicleResourceCosts get _x >= 100 }; +if (_vehAA isEqualTo []) then { _tankWeight = _tankWeight + _aaWeight }; + +// only occupants use militia vehicles? +if (_side == Occupants) then { + [_faction get "vehiclesMilitiaLightArmed", _milCarWeight] call _fnc_addArrayToWeights; +}; +[_faction get "vehiclesLightArmed", _carWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesTanks", _tankWeight] call _fnc_addArrayToWeights; +[_vehAA, _aaWeight] call _fnc_addArrayToWeights; + +_vehWeights; diff --git a/A3A/addons/core/functions/Base/fn_getVehiclesGroundTransport.sqf b/A3A/addons/core/functions/Base/fn_getVehiclesGroundTransport.sqf new file mode 100644 index 0000000000..e1d9ca354a --- /dev/null +++ b/A3A/addons/core/functions/Base/fn_getVehiclesGroundTransport.sqf @@ -0,0 +1,52 @@ +/* +Maintainer: John Jordan + Returns a weighted ground transport vehicle pool based on war level and side + +Arguments: + The side for which the vehicle pool should be generated (occupants or invaders) + 1-10 range, war-level based vehicle quality + +Return value: + [vehType, weight, vehType2, weight2, ...] +*/ +params ["_side", "_level"]; +_level = (_level max 1 min 10) - 1; +private _faction = [A3A_faction_occ, A3A_faction_inv] select (_side == Invaders); + +private _fnc_addArrayToWeights = { + params ["_vehArray", "_baseWeight"]; + { _vehWeights append [_x, _baseWeight / count _vehArray] } forEach _vehArray; +}; + +private _vehWeights = []; + +private _policeWeight = [40, 20, 0, 0, 0, 0, 0, 0, 0, 0] select _level; +private _milCarWeight = [40, 30, 20, 10, 5, 0, 0, 0, 0, 0] select _level; +private _milTruckWeight = [50, 40, 30, 20, 10, 0, 0, 0, 0, 0] select _level; +private _carWeight = [20, 25, 20, 10, 10, 10, 5, 5, 5, 5] select _level; +private _armedCarWeight = [20, 25, 30, 30, 30, 25, 20, 20, 15, 15] select _level; +private _truckWeight = [50, 45, 40, 35, 30, 25, 20, 15, 10, 5] select _level; +private _lapcWeight = [30, 40, 50, 50, 45, 40, 35, 30, 25, 20] select _level; +private _apcWeight = [ 0, 10, 15, 20, 25, 30, 35, 40, 40, 40] select _level; +private _ifvWeight = [ 0, 0, 2, 4, 6, 8, 12, 16, 20, 25] select _level; + +// Assumption is that at least one of APC or battle bus exists +if (_faction get "vehiclesIFVs" isEqualTo []) then { _apcWeight = _apcWeight + _ifvWeight }; +if (_faction get "vehiclesAPCs" isEqualTo []) then { _bbWeight = _bbWeight + _apcWeight }; +if (_faction get "vehiclesLightAPCs" isEqualTo []) then { _apcWeight = _apcWeight + _lapcWeight/2; _truckWeight = _truckWeight + _lapcWeight/2; }; + +// only occupants use militia vehicle types? +if (_side == Occupants) then +{ + [_faction get "vehiclesPolice", _policeWeight] call _fnc_addArrayToWeights; + [_faction get "vehiclesMilitiaCars", _milCarWeight] call _fnc_addArrayToWeights; + [_faction get "vehiclesMilitiaTrucks", _milTruckWeight] call _fnc_addArrayToWeights; +}; +[_faction get "vehiclesLightUnarmed", _carWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesLightArmedTroop", _armedCarWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesTrucks", _truckWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesLightAPCs", _lapcWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesAPCs", _apcWeight] call _fnc_addArrayToWeights; +[_faction get "vehiclesIFVs", _ifvWeight] call _fnc_addArrayToWeights; + +_vehWeights; diff --git a/A3A/addons/core/functions/Base/fn_markerChange.sqf b/A3A/addons/core/functions/Base/fn_markerChange.sqf index e5af479b23..3509dce7f6 100644 --- a/A3A/addons/core/functions/Base/fn_markerChange.sqf +++ b/A3A/addons/core/functions/Base/fn_markerChange.sqf @@ -62,22 +62,31 @@ garrison setVariable [format ["%1_requested", _markerX], [], true]; if (_winner == teamPlayer) then { - _super = if (_markerX in airportsX) then {true} else {false}; - [_markerX, _looser, _super] spawn - { - params ["_marker", "_loser", "_super"]; - private _waitTime = (6 - tierWar/2) * (0.5 + random 0.5); - sleep (_waitTime * 60); - if(sidesX getVariable [_marker, sideUnknown] == _loser) exitWith {}; - [[_marker, _loser, _super], "A3A_fnc_singleAttack"] call A3A_fnc_scheduler; + // Old garrison surrender + private _oldGarrison = units _looser select { _x getVariable ["markerX", ""] == _markerX }; + { _x spawn A3A_fnc_surrenderAction } forEach _oldGarrison; + + // Cap to 0.6 max to reward captures without previous support calls + private _resources = [_looser, teamPlayer, _markerX, 0.6] call A3A_fnc_maxDefenceSpend; + + // Don't send anything if it'd be too small + private _minAttack = (1 + random 0.5) * A3A_balanceResourceRate; + if (_resources < _minAttack) exitWith { + Debug_2("Available resources (%1) below minimum attack (%2), sending no counterattack", _resources, _minAttack); }; + + private _vehCount = round (random 0.5 + _resources / A3A_balanceVehicleCost); + private _reveal = [markerPos _markerX] call A3A_fnc_calculateSupportCallReveal; + _reveal = [_looser, markerPos _markerX, _reveal] call A3A_fnc_useRadioKey; + + [[_markerX, _looser, _vehCount, _reveal], "A3A_fnc_singleAttack"] call A3A_fnc_scheduler; + + // just estimates here. + A3A_supportStrikes pushBack [_looser, "TROOPS", markerPos _markerX, time + 2700, 2700, _resources]; + A3A_supportSpends pushBack [_looser, markerPos _markerX, markerPos _markerX, _resources, time]; } else { - _soldiers = []; - {_soldiers pushBack (_x getVariable "unitType")} forEach (allUnits select {(_x distance _positionX < (_size*3)) and (_x getVariable ["spawner",false]) and (side group _x == _winner) and (vehicle _x == _x) and (alive _x)}); - [_soldiers,_winner,_markerX,0] remoteExec ["A3A_fnc_garrisonUpdate",2]; - //New system ================================================================= private _type = "Other"; switch (true) do @@ -87,7 +96,7 @@ else case (_markerX in citiesX): {_type = "City"}; }; private _preference = garrison getVariable (format ["%1_preference", _type]); - // pre-fill most of the garrison, because otherwise we're spamming a lot of fake reinf + // pre-fill most of the garrison, because otherwise we're spamming a lot of fake reinf private _indexToReinf = floor (random count _preference); private _garrison = []; private _request = []; @@ -288,7 +297,7 @@ if (_winner == teamPlayer) then if (!isNull _flagX) then { //[_flagX,"remove"] remoteExec ["A3A_fnc_flagaction",0,_flagX]; - //_flagX setVariable ["A3A_flagCaptureETA", nil, true]; + //_flagX setVariable ["isGettingCaptured", nil, true]; [_flagX,"SDKFlag"] remoteExec ["A3A_fnc_flagaction",0,_flagX]; [_flagX,FactionGet(reb,"flagTexture")] remoteExec ["setFlagTexture",_flagX]; sleep 2; @@ -297,16 +306,8 @@ if (_winner == teamPlayer) then //[_flagX,"garage"] remoteExec ["A3A_fnc_flagaction",[teamPlayer,civilian],_flagX]; if (_markerX in seaports) then {[_flagX,"seaport"] remoteExec ["A3A_fnc_flagaction",[teamPlayer,civilian],_flagX]}; }; - ([Occupants] + _prestigeOccupants) spawn A3A_fnc_addAggression; - ([Invaders] + _prestigeInvaders) spawn A3A_fnc_addAggression; - [_markerX] spawn { - params ["_markerX"]; - // This allows enemies to retake rebel markers with random junk until the marker is despawned - while { spawner getVariable _markerX != 2 and sidesX getVariable _markerX == teamPlayer } do { - sleep 60; - [_markerX,teamPlayer] remoteExec ["A3A_fnc_zoneCheck",2]; - }; - }; + [Occupants, _prestigeOccupants#0, _prestigeOccupants#1, true] spawn A3A_fnc_addAggression; + [Invaders, _prestigeInvaders#0, _prestigeInvaders#1, true] spawn A3A_fnc_addAggression; } else { @@ -318,9 +319,16 @@ else [_x, _winner, true] call A3A_fnc_vehKilledOrCaptured; } forEach _staticWeapons; + // Clear out captured statics on marker despawn + [_staticWeapons, _markerX] spawn { + params ["_statics", "_markerX"]; + waitUntil { sleep 1; spawner getVariable _markerX == 2 }; + { deleteVehicle _x } forEach (_statics - staticsToSave); + }; + if (!isNull _flagX) then { - //_flagX setVariable ["A3A_flagCaptureETA", nil, true]; + //_flagX setVariable ["isGettingCaptured", nil, true]; if (_looser == teamPlayer) then { [_flagX,"remove"] remoteExec ["A3A_fnc_flagaction",0,_flagX]; @@ -338,32 +346,11 @@ else }; if (_looser == teamPlayer) then { - ([Occupants] + _prestigeOccupants) spawn A3A_fnc_addAggression; - ([Invaders] + _prestigeInvaders) spawn A3A_fnc_addAggression; - if ((random 10 < ((tierWar + difficultyCoef)/4)) and !("DEF_HQ" in A3A_activeTasks) and (isPlayer theBoss)) then {[[],"A3A_fnc_attackHQ"] remoteExec ["A3A_fnc_scheduler",2]}; + [Occupants, _prestigeOccupants#0, _prestigeOccupants#1, true] spawn A3A_fnc_addAggression; + [Invaders, _prestigeInvaders#0, _prestigeInvaders#1, true] spawn A3A_fnc_addAggression; }; }; -/* -if ((_winner != teamPlayer) and (_looser != teamPlayer)) then - { - if (_markerX in outposts) then - { - _closeX = (seaports + resourcesX + factories) select {((getMarkerPos _x) distance _positionX < distanceSPWN) and (sidesX getVariable [_x,sideUnknown] != teamPlayer)}; - if (_looser == Occupants) then {_closeX = _closeX select {sidesX getVariable [_x,sideUnknown] == Occupants}} else {_closeX = _closeX select {sidesX getVariable [_x,sideUnknown] == Invaders}}; - {[_winner,_x] spawn A3A_fnc_markerChange; sleep 5} forEach _closeX; - } - else - { - if (_markerX in airportsX) then - { - _closeX = (seaports + outposts) select {((getMarkerPos _x) distance _positionX < distanceSPWN) and (sidesX getVariable [_x,sideUnknown] != teamPlayer)}; - _closeX append ((factories + resourcesX) select {(sidesX getVariable [_x,sideUnknown] != teamPlayer) and (sidesX getVariable [_x,sideUnknown] != _winner) and ([airportsX,_x] call BIS_fnc_nearestPosition == _markerX)}); - if (_looser == Occupants) then {_closeX = _closeX select {sidesX getVariable [_x,sideUnknown] == Occupants}} else {_closeX = _closeX select {sidesX getVariable [_x,sideUnknown] == Invaders}}; - {[_winner,_x] spawn A3A_fnc_markerChange; sleep 5} forEach _closeX; - }; - }; - }; -*/ + markersChanging = markersChanging - [_markerX]; ["markerChange", [_markerX, _winner]] call EFUNC(Events,triggerEvent); diff --git a/A3A/addons/core/functions/Base/fn_mrkUpdate.sqf b/A3A/addons/core/functions/Base/fn_mrkUpdate.sqf index 6c9e9ad2f4..2935b02536 100644 --- a/A3A/addons/core/functions/Base/fn_mrkUpdate.sqf +++ b/A3A/addons/core/functions/Base/fn_mrkUpdate.sqf @@ -11,7 +11,7 @@ if (_marker in airportsX) then { _mrkD setMarkerTypeLocal (_faction get "flagMarkerType"); _mrkD setMarkerColorLocal "Default"; } else { - if (_marker in destroyedSites) exitWith { _mrkD setMarkerColorLocal "ColorBlack" }; + if (_marker in destroyedSites and _marker in citiesX) exitWith { _mrkD setMarkerColorLocal "ColorBlack" }; if (_mrkSide == teamPlayer) exitWith { _mrkD setMarkerColorLocal colorTeamPlayer }; _mrkD setMarkerColorLocal ([colorOccupants, colorInvaders] select (_mrkSide == Invaders)); }; diff --git a/A3A/addons/core/functions/Base/fn_onHeadlessClientDisconnect.sqf b/A3A/addons/core/functions/Base/fn_onHeadlessClientDisconnect.sqf index f4297f0ae3..1b511205c5 100644 --- a/A3A/addons/core/functions/Base/fn_onHeadlessClientDisconnect.sqf +++ b/A3A/addons/core/functions/Base/fn_onHeadlessClientDisconnect.sqf @@ -1,10 +1,14 @@ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + private _owner = param [4]; if (_owner in hcArray) then { + Info_2("Headless client ID %1 disconnected from HC array %2", _owner, hcArray); if ({owner _x == _owner} count allUnits > 0) then { - [] spawn { + A3A_HCErrorHandle = [] spawn { while {true} do { [petros,"hint","A Headless Client has been disconnected. This will cause malfunctions. Head back to HQ for saving ASAP and ask and Admin for a restart", "Headless Client"] remoteExec ["A3A_fnc_commsMP"]; @@ -16,4 +20,4 @@ if (_owner in hcArray) then { hcArray = hcArray - [_owner]; }; -}; \ No newline at end of file +}; diff --git a/A3A/addons/core/functions/Base/fn_placementselection.sqf b/A3A/addons/core/functions/Base/fn_placementselection.sqf index ac97995cb0..730330b147 100644 --- a/A3A/addons/core/functions/Base/fn_placementselection.sqf +++ b/A3A/addons/core/functions/Base/fn_placementselection.sqf @@ -100,15 +100,7 @@ if (visiblemap) then { } forEach _controlsX; [_positionClicked] remoteExec ["A3A_fnc_createPetros", 2]; }; - [_positionClicked] call A3A_fnc_relocateHQObjects; - //If it's a new game, we teleport everyone to new HQ, yay! - if (_newGame) then { - { - if ((side _x == teamPlayer) or (side _x == civilian)) then { - _x setPos getPos petros; - }; - } forEach (call A3A_fnc_playableUnits); - }; + [_positionClicked, _newGame] remoteExec ["A3A_fnc_relocateHQObjects", 2]; openmap [false,false]; }; diff --git a/A3A/addons/core/functions/Base/fn_rebelAttack.sqf b/A3A/addons/core/functions/Base/fn_rebelAttack.sqf deleted file mode 100644 index cb86d018fd..0000000000 --- a/A3A/addons/core/functions/Base/fn_rebelAttack.sqf +++ /dev/null @@ -1,438 +0,0 @@ -params [["_side", sideEnemy]]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -/* Handles the large attack that also are missions - - Execution on: HC or Server - - Scope: Internal - - Params: - None - - Returns: - Nothing -*/ - -private _originalSide = _side; - -Info_1("Starting large attack script for side %1", _side); - -if (A3A_hasIFA and (sunOrMoon < 1)) exitWith -{ - Info("Aborting attack as IFA has no nightvision (at least thats what I assume)"); -}; - -private _possibleTargets = markersX - controlsX - outpostsFIA - ["Synd_HQ","NATO_carrier","CSAT_carrier"] - destroyedSites;; -private _possibleStartBases = airportsX select {([_x,false] call A3A_fnc_airportCanAttack)}; -private _targetSide = sideEnemy; -//No AI vs AI, possible targets are only bases held by rebels -if (gameMode != 1) then -{ - _possibleTargets = _possibleTargets select {sidesX getVariable [_x,sideUnknown] == teamPlayer}; - _possibleStartBases = _possibleStartBases select {sidesX getVariable [_x,sideUnknown] == _side}; - _targetSide = teamPlayer; -} -else -{ - //Select the target side and reduce possible targets based on it - private _playersHold = 0; - private _ownHold = 0; - private _enemyAIHold = 0; - - { - switch (sidesX getVariable [_x, sideUnknown]) do - { - case (teamPlayer): - { - _playersHold = _playersHold + 1; - }; - case (_side): - { - _ownHold = _ownHold + 1; - }; - default - { - _enemyAIHold = _enemyAIHold + 1; - }; - }; - } forEach (airportsX + outposts + seaports + factories + resourcesX); - - private _allTargetsCount = _playersHold + _ownHold + _enemyAIHold; - - private _playersHoldRatio = _playersHold / _allTargetsCount; - private _enemyAIHoldRatio = _enemyAIHold / _allTargetsCount; - - private _attackerAggro = 0; - private _defenderAggro = 0; - private _enemySide = sideUnknown; - - if(_side == Occupants) then - { - _attackerAggro = aggressionOccupants; - _defenderAggro = aggressionInvaders; - _enemySide = Invaders; - } - else - { - _attackerAggro = aggressionInvaders; - _defenderAggro = aggressionOccupants; - _enemySide = Occupants; - }; - - //Select the side to attack and the remaining targets - _targetSide = selectRandomWeighted [teamPlayer, (0.5 * _playersHoldRatio) + (0.5 * (_attackerAggro/100)), _enemySide, _enemyAIHoldRatio]; - - //Side selected, check for counter attack - if(_targetSide != teamPlayer) then - { - private _aggroChance = (100 - _defenderAggro) - (100 - _attackerAggro); - private _winChance = 50 - (_aggroChance/2); - private _loseChance = 100 - _winChance; - Debug_2("Attacker win chance is %1, counter chance is %2", _winChance, _loseChance); - private _attackerWon = selectRandomWeighted [false, _loseChance, true, _winChance]; - if(!_attackerWon) then - { - Debug_2("Attack from %1 got countered by %2, reversing attack sides", _side, _enemySide); - _targetSide = _side; - _side = _enemySide; - }; - }; - - _possibleStartBases = _possibleStartBases select {sidesX getVariable [_x,sideUnknown] == _side}; - _possibleTargets = _possibleTargets select {sidesX getVariable [_x,sideUnknown] == _targetSide}; - Debug_1("Selected target side is %1", _targetSide); -}; - -if((_side == Occupants) && (gameMode != 4)) then -{ - _possibleStartBases pushBack "NATO_carrier"; -}; -if((_side == Invaders) && (gameMode != 3)) then -{ - _possibleStartBases pushBack "CSAT_carrier"; -}; - -//On low level remove cities from target list -if (gameMode != 4) then -{ - if (tierWar < 3) then {_possibleTargets = _possibleTargets - citiesX;}; -} -else -{ - if (tierWar < 5) then {_possibleTargets = _possibleTargets - citiesX;}; -}; - -// Remove cities anyway unless they're rebel-controlled, because punishments vs occupants are broken -_possibleTargets = _possibleTargets - (citiesX select {sidesX getVariable [_x, sideUnknown] != teamPlayer}); - -//Attacks on rebels should be closer than mission range -_possibleTargets = _possibleTargets select {sidesX getVariable [_x, sideUnknown] != teamPlayer || (getMarkerPos _x) distance2D (getMarkerPos "Synd_HQ") < distanceMission}; - -if((count _possibleTargets == 0) || (count _possibleStartBases == 0)) exitWith -{ - Info("Attack found no suitable targets or no suitable start bases, aborting!"); -}; - -Debug_2("%1 possible targets for attack found, possible start points are %2", count _possibleTargets, _possibleStartBases); - -private _easyTargets = []; -private _availableTargets = []; -{ - private _startAirport = _x; - private _airportSide = sidesX getVariable [_startAirport, sideUnknown]; - - //Gather position and killzones of airport - private _killZones = killZones getVariable [_startAirport, []]; - private _startAirportPos = getMarkerPos _startAirport; - { - //For each target, calculate the distance to the airport - private _target = _x; - private _distance = (getMarkerPos _target) distance2D _startAirportPos; - //In air range, add to target list - if(_distance < distanceForAirAttack) then - { - //If in land range, half the distance - if(_distance < distanceForLandAttack && {[_startAirport, _target] call A3A_fnc_arePositionsConnected}) then - { - _distance = _distance * 0.5; - }; - - //If the target is surrounded by our friendly markers, remove points - private _nearbyFriendlyMarkers = (markersX - controlsX - citiesX - outpostsFIA) select - { - (sidesX getVariable [_x,sideUnknown] == _airportSide) && - {(getMarkerPos _x) distance2D (getMarkerPos _target) < 1500} - }; - _distance = _distance - (300 * (count _nearbyFriendlyMarkers)); - if (_distance < 0) then {_distance = 0}; - - //if(count _nearbyFriendlyMarkers >= 5 && {!(_target in citiesX)}) then - //{ - // Debug_1("%1 is surrounded by us, considering easy target", _target); - // _easyTargets pushBack _target; - //}; - - //If in killzones, double the distance - if (_target in _killZones) then - { - _distance = _distance * 2; - }; - - //Add airport to the possible start bases for attack to this target, use distance as points (the lower the better) - private _index = _availableTargets findIf {(_x select 0) == _target}; - if(_index == -1) then - { - _availableTargets pushBack [_target, [[_startAirport, _distance]]]; - } - else - { - private _targetArray = _availableTargets select _index; - (_targetArray select 1) pushBack [_startAirport, _distance]; - }; - }; - } forEach _possibleTargets; -} forEach _possibleStartBases; - -if (count _availableTargets == 0) exitWith -{ - Info("Attack could not find available targets, aborting!"); -}; - -{ - _x params ["_target", "_baseArray"]; - - //Multiplier is used as an overall multiplier based on types - private _targetMultiplier = 1; - //Additional points based on marker specific traits - private _targetPoints = 0; - - //Selecting a multiplier based on target type (lowest is best) - switch (true) do - { - case (_target in airportsX): {_targetMultiplier = 0.05}; - case (_target in outposts): {_targetMultiplier = 0.25}; - case (_target in resourcesX): {_targetMultiplier = 0.35}; - case (_target in factories): {_targetMultiplier = 0.5}; - case (_target in seaports): {_targetMultiplier = 0.7}; - case (_target in citiesX): {_targetMultiplier = [2, 0.5] select (_side == Invaders)}; - //If I have missed something, multiplier stays the same - default {_targetMultiplier = 1}; - }; - - //Adding points based on nearby friendly locations - private _nearbyFriendlyMarkers = (markersX - controlsX - citiesX - outpostsFIA) select - { - (sidesX getVariable [_x,sideUnknown] == _targetSide) && - {(getMarkerPos _x) distance2D (getMarkerPos _target) < 1500} - }; - _targetPoints = 500 * (count _nearbyFriendlyMarkers); - - //Adding points based on garrison and statics - private _garrison = garrison getVariable [_target,[]]; - private _nearbyStatics = staticsToSave select {(_x distance2D (getMarkerPos _target)) < distanceSPWN}; - _targetPoints = _targetPoints + (10 * (count _garrison) + (50 * (count _nearbyStatics))); - - //if((count _garrison <= 8) && (_targetSide == teamPlayer) && {(count _nearbyStatics <= 2) && {!(_target in citiesX)}}) then - //{ - //Only minimal garrison, consider it an easy target - // Debug_1("%1 has only minimal garrison, considering easy target", _target); - // _easyTargets pushBackUnique _target; - //}; - - //Apply the new points to the base array - _baseArray = _baseArray apply {[_x select 0, ((_x select 1) + _targetPoints) * _targetMultiplier]}; -} forEach _availableTargets; - -/* -All targets are now having values which airport can attack them how efficient -We will check for easy targets first, if we have four of them we will attack them -instead of starting one large attack. In both cases we check which are the most efficient ones -to attack from which airport -*/ - -private _fnc_flipMarker = -{ - params ["_side", "_marker"]; - Info_2("Autowin %1 for side %2 to avoid unnecessary calculations", _marker, _side); - [_side, _marker] spawn A3A_fnc_markerChange; - private _faction = Faction(_side); - sleep 10; - private _maxTroops = 12 max round ((0.5 + random 0.5) * ([_marker] call A3A_fnc_garrisonSize)); - private _soldiers = []; - while {count _soldiers < _maxTroops} do - { - _soldiers append selectRandom ((_faction get "groupsSquads") + (_faction get "groupsMedium")); - }; - _soldiers resize _maxTroops; - [_soldiers,_side,_marker,0] remoteExec ["A3A_fnc_garrisonUpdate",2]; -}; - - -// JJ: Easy targets currently disabled due to overspawning/ineffectiveness -if(count _easyTargets >= 4) then -{ - //We got four easy targets, attacking them now - private _attackList = [objNull, objNull, objNull, objNull]; - { - private _target = _x; - private _index = _availableTargets findIf {(_x select 0) == _target}; - private _startArray = (_availableTargets select _index) select 1; - - //Search for the best option for attacking this target (lowest number is best) - private _attackParams = objNull; - { - if(!(_attackParams isEqualType []) || {(_attackParams select 1) > (_x select 1)}) then - { - _attackParams = _x; - }; - } forEach _startArray; - _attackParams pushBack _target; - - //Check if the attack is better than one of the current selected ones - private _insertIndex = _attackList findIf {(!(_x isEqualType [])) || {(_x select 1) > (_attackParams select 1)}}; - if(_insertIndex != -1) then - { - if(_insertIndex == 3) then - { - _attackList set [3, _attackParams]; - } - else - { - //Sort in and push all worse option down by one - for "_i" from 3 to _insertIndex step -1 do - { - _attackList set [_i + 1, _attackList select _i]; - }; - //Set attack and then cut of the last option - _attackList set [_insertIndex, _attackParams]; - _attackList resize 4; - }; - }; - } forEach _easyTargets; - - DebugArray("Found four targets to attack, these are:", _attackList); - - //In case of four small attacks have 90 minutes break - [5400, _originalSide] call A3A_fnc_timingCA; - - //Execute the attacks from the given bases to the targets - { - private _target = _x select 2; - private _nearPlayers = allPlayers findIf {(getMarkerPos (_target) distance2D _x) < 1500}; - if((_nearPlayers != -1) || ((spawner getVariable _target) != 2) || (sidesX getVariable _target == teamPlayer)) then - { - Info_2("Starting single attack against %1 from %2", _target, _x select 0); - [[_target, _x select 0, false],"A3A_fnc_singleAttack"] remoteExec ["A3A_fnc_scheduler",2]; - sleep 180; - } - else - { - private _side = sidesX getVariable (_x select 0); - [_side, _target] spawn _fnc_flipMarker; - }; - sleep 15; - } forEach _attackList; -} -else -{ - //Not enough easy targets, attack the best non easy target if available - private _mainTarget = objNull; - private _easyTarget = objNull; - { - _x params ["_target", "_startArray"]; - - //Select the best attack option for the target - private _attackParams = objNull; - { - if(!(_attackParams isEqualType []) || {(_attackParams select 1) > (_x select 1)}) then - { - _attackParams = _x; - }; - } forEach _startArray; - _attackParams pushBack _target; - - //It makes less sense to hit a weak target with a strong waved attack, save it seperated - if (_target in _easyTargets) then - { - if (!(_easyTarget isEqualType []) || {(_easyTarget select 1) > (_attackParams select 1)}) then - { - _easyTarget = _attackParams; - }; - } - else - { - if(!(_mainTarget isEqualType []) || {(_mainTarget select 1) > (_attackParams select 1)}) then - { - _mainTarget = _attackParams; - }; - }; - } forEach _availableTargets; - - Debug_2("Main target is %1, easy target is %2", _mainTarget, _easyTarget); - - //If one if the target is not set, use the other one - private _finalTarget = objNull; - if(!(_mainTarget isEqualType [])) then - { - Debug("Main target not set, selecting easy target"); - _finalTarget = _easyTarget; - } - else - { - if(!(_easyTarget isEqualType [])) then - { - Debug("Easy target not set, selecting main target"); - _finalTarget = _mainTarget; - } - else - { - //If both are set, select easy target only if it is 2 times better than the main target - if(((_easyTarget select 1) * 2) < (_mainTarget select 1)) then - { - _finalTarget = _easyTarget; - } - else - { - _finalTarget = _mainTarget; - }; - }; - }; - - Debug_1("Selected target is %1!", _finalTarget); - - _finalTarget params ["_attackOrigin", "_attackPoints", "_attackTarget"]; - - //Select the number of waves based on the points as higher points mean higher difficulty - // JJ: Nope, degenerate behaviour with target distance. Revert to a dumb version for the moment. - private _waves = - 0.5 + random 1 + - + ([0, 1.5] select (_attackTarget in airportsX)) - + ([0, 0.5] select (_attackTarget in outposts)) - + ([0, 0.5] select (_side == Invaders)) - + (tierWar / 10); - - _waves = 1 max (round _waves); - - //Send the actual attacks - if (sidesX getVariable [_attackOrigin, sideUnknown] == Occupants || {!(_attackTarget in citiesX)}) then - { - private _nearPlayers = allPlayers findIf {(getMarkerPos (_attackTarget) distance2D _x) < 1500}; - if((_nearPlayers != -1) || ((spawner getVariable _attackTarget) != 2) || (sidesX getVariable _attackTarget == teamPlayer) || (_attackTarget in citiesX)) then - { - //Sending real attack, execute the fight - Info_3("Starting waved attack with %1 waves from %2 to %3", _waves, _attackOrigin, _attackTarget); - [_attackTarget, _attackOrigin, _waves, _originalSide] spawn A3A_fnc_wavedCA; - } - else - { - [_side, _attackTarget] spawn _fnc_flipMarker; - [3600, _originalSide] call A3A_fnc_timingCA; - }; - } - else - { - Info_2("Starting punishment mission from %1 to %2", _attackOrigin, _attackTarget); - [_attackTarget, _attackOrigin] spawn A3A_fnc_invaderPunish; - }; -}; diff --git a/A3A/addons/core/functions/Base/fn_relocateHQObjects.sqf b/A3A/addons/core/functions/Base/fn_relocateHQObjects.sqf index f6f69dd06f..096f154bfe 100644 --- a/A3A/addons/core/functions/Base/fn_relocateHQObjects.sqf +++ b/A3A/addons/core/functions/Base/fn_relocateHQObjects.sqf @@ -1,4 +1,25 @@ -params ["_newPosition"]; +params ["_newPosition", "_isNewGame"]; + +// Update cur/old HQ knowledge. Shouldn't be interrupted +isNil { + if (_isNewGame) exitWith {}; + private _oldPos = markerPos "Synd_HQ"; + _oldPos set [2, A3A_curHQInfoOcc]; + A3A_oldHQInfoOcc pushBack +_oldPos; + A3A_curHQInfoOcc = 0; + { + private _dist = _x distance2d _newPosition; + A3A_curHQInfoOcc = A3A_curHQInfoOcc max linearConversion [0, 1000, _dist, _x#2, 0, true]; + } forEach A3A_oldHQInfoOcc; + + _oldPos set [2, A3A_curHQInfoInv]; + A3A_oldHQInfoInv pushBack +_oldPos; + A3A_curHQInfoInv = 0; + { + private _dist = _x distance2d _newPosition; + A3A_curHQInfoInv = A3A_curHQInfoInv max linearConversion [0, 1000, _dist, _x#2, 0, true]; + } forEach A3A_oldHQInfoInv; +}; respawnTeamPlayer setMarkerPos _newPosition; posHQ = _newPosition; publicVariable "posHQ"; @@ -39,5 +60,16 @@ mapX hideObjectGlobal false; fireX hideObjectGlobal false; flagX hideObjectGlobal false; + "Synd_HQ" setMarkerPos _newPosition; -chopForest = false; publicVariable "chopForest"; \ No newline at end of file +chopForest = false; publicVariable "chopForest"; + +//If it's a new game, we teleport everyone to new HQ, yay! +if (_isNewGame) then { + { + if ((side _x == teamPlayer) or (side _x == civilian)) then { + _x setPosATL _newPosition; + }; + } forEach (call A3A_fnc_playableUnits); +}; + diff --git a/A3A/addons/core/functions/Base/fn_remUnitCount.sqf b/A3A/addons/core/functions/Base/fn_remUnitCount.sqf deleted file mode 100644 index a509a0d07d..0000000000 --- a/A3A/addons/core/functions/Base/fn_remUnitCount.sqf +++ /dev/null @@ -1,18 +0,0 @@ -/* -Params: - : Side of units to check. - -Returns: - Remaining units for that side on this machine. -*/ - -params ["_side"]; - -private _unitCount = {(local _x) and (alive _x)} count allUnits; -private _remUnitCount = maxUnits - _unitCount; -if (gameMode < 3) then -{ - private _sideCount = {(local _x) and (alive _x) and (side group _x == _side)} count allUnits; - _remUnitCount = _remUnitCount min (maxUnits * 0.7 - _sideCount); -}; -_remUnitCount; diff --git a/A3A/addons/core/functions/Base/fn_scheduler.sqf b/A3A/addons/core/functions/Base/fn_scheduler.sqf index 242f9af8c4..8955c75b3e 100644 --- a/A3A/addons/core/functions/Base/fn_scheduler.sqf +++ b/A3A/addons/core/functions/Base/fn_scheduler.sqf @@ -1,21 +1,24 @@ if (!isServer) exitWith {}; + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -scriptName "fn_scheduler"; -private _params = _this select 0; -private _function = _this select 1; -Info_2("Scheduled function: %1, Function params: %2",_function,_params); + +params ["_params", "_function"]; +Info_2("Scheduled function: %1, Function params: %2", _function, _params); + if (count hcArray == 0) exitWith {_params remoteExec [_function,2]}; -if (count hcArray == 1) exitWith {_params remoteExec [_function,hcArray select 0]}; -_return = 2; -_min = 1000; +//if (count hcArray == 1) exitWith {_params remoteExec [_function,hcArray select 0]}; + +private _targetID = 2; +private _min = ({local _x} count allUnits) * 2; // use server too when it's quiet { - _hcID = _x; - _num = {owner _x == _hcID} count allUnits; + private _hcID = _x; + private _num = {owner _x == _hcID} count allUnits; if (_num < _min) then { - _return = _hcID; + _targetID = _hcID; _min = _num; }; } forEach hcArray; -_params remoteExec [_function,_return]; +Info_2("Executing on machine ID %1, minimum units %2", _targetID, _min); +_params remoteExec [_function, _targetID]; diff --git a/A3A/addons/core/functions/Base/fn_sellVehicle.sqf b/A3A/addons/core/functions/Base/fn_sellVehicle.sqf index 470cae68b3..036e599390 100644 --- a/A3A/addons/core/functions/Base/fn_sellVehicle.sqf +++ b/A3A/addons/core/functions/Base/fn_sellVehicle.sqf @@ -61,7 +61,8 @@ private _costs = call { or (_typeX in [FactionGet(reb,"vehicleCivBoat"),FactionGet(reb,"vehicleCivCar"),FactionGet(reb,"vehicleCivTruck")]) ) exitWith {25}; if ( - _typeX in (OccAndInv("vehiclesLight") + _typeX in (FactionGet(all,"vehiclesLight") + + FactionGet(all,"vehiclesLightAPCs") + OccAndInv("vehiclesTrucks") + OccAndInv("vehiclesCargoTrucks") + OccAndInv("vehiclesAmmoTrucks") @@ -71,9 +72,11 @@ private _costs = call { ) or (_typeX in FactionGet(all,"vehiclesBoats")) ) exitWith {100}; - if (_typeX in (OccAndInv("vehiclesHelisLight") + [FactionGet(reb,"vehicleCivHeli")])) exitWith {500}; + if (_typeX in (FactionGet(all,"vehiclesHelisLight") + [FactionGet(reb,"vehicleCivHeli")])) exitWith {500}; if ( (_typeX in FactionGet(all,"vehiclesAPCs")) + || (_typeX in FactionGet(all,"vehiclesIFVs")) + || (_typeX in FactionGet(all,"vehiclesHelisLightAttack")) || (_typeX in FactionGet(all,"vehiclesTransportAir")) || (_typeX in FactionGet(all,"vehiclesUAVs")) ) exitWith {1000}; @@ -83,7 +86,7 @@ private _costs = call { or (_typeX in FactionGet(all,"vehiclesAA")) or (_typeX in FactionGet(all,"vehiclesArtillery")) ) exitWith {3000}; - if (_typeX in (OccAndInv("vehiclesPlanesCAS") + OccAndInv("vehiclesPlanesAA"))) exitWith {4000}; + if (_typeX in (FactionGet(all,"vehiclesPlanesCAS") + FactionGet(all,"vehiclesPlanesAA"))) exitWith {4000}; 0; }; @@ -97,7 +100,6 @@ _costs = round (_costs * (1-damage _veh)); [0,_costs] remoteExec ["A3A_fnc_resourcesFIA",2]; if (_veh in staticsToSave) then {staticsToSave = staticsToSave - [_veh]; publicVariable "staticsToSave"}; -if (_veh in reportedVehs) then {reportedVehs = reportedVehs - [_veh]; publicVariable "reportedVehs"}; [_veh,true] call A3A_fnc_empty; diff --git a/A3A/addons/core/functions/Base/fn_setPlaneLoadout.sqf b/A3A/addons/core/functions/Base/fn_setPlaneLoadout.sqf index 70276e104a..67fb7b9982 100644 --- a/A3A/addons/core/functions/Base/fn_setPlaneLoadout.sqf +++ b/A3A/addons/core/functions/Base/fn_setPlaneLoadout.sqf @@ -37,7 +37,11 @@ if (_type == "CAS") then //Vanilla IND CAS case "I_Plane_Fighter_03_dynamicLoadout_F": { - _loadout = ["PylonRack_1Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","","PylonRack_3Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","PylonRack_1Rnd_LG_scalpel"]; +// _loadout = ["PylonRack_1Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","","PylonRack_3Rnd_LG_scalpel","PylonRack_3Rnd_LG_scalpel","PylonRack_1Rnd_LG_scalpel"]; + _loadout = ["PylonRack_7Rnd_Rocket_04_AP_F","PylonRack_3Rnd_LG_scalpel","PylonRack_1Rnd_Missile_AGM_02_F","PylonWeapon_300Rnd_20mm_shells","PylonRack_1Rnd_Missile_AGM_02_F","PylonRack_3Rnd_LG_scalpel","PylonRack_7Rnd_Rocket_04_AP_F"]; + _plane setVariable ["mainGun", "Twin_Cannon_20mm"]; + _plane setVariable ["rocketLauncher", ["Rocket_04_AP_Plane_CAS_01_F"]]; + _plane setVariable ["missileLauncher", ["Missile_AGM_02_Plane_CAS_01_F", "missiles_SCALPEL"]]; }; //RHS US CAS (A-10) case "RHS_A10"; @@ -96,6 +100,7 @@ if (_type == "CAS") then _plane setVariable ["rocketLauncher", ["rhs_weap_FFARLauncher"]]; _plane setVariable ["missileLauncher", ["rhs_weap_AGM114K_Launcher", "RHS_weap_AGM114N_Launcher"]]; }; + case "UK3CB_B_Mystere_HIDF_CAS1"; case "UK3CB_MDF_B_Mystere_CAS1": { _loadout = ["PylonRack_3Rnd_Missile_AGM_02_F","PylonRack_12Rnd_missiles","PylonRack_12Rnd_missiles","PylonRack_3Rnd_Missile_AGM_02_F"]; @@ -167,8 +172,8 @@ if (_type == "CAS") then }; case "uns_A1J_CAS": { - _loadout = ["uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Bomb_MK82","uns_pylonRack_1Rnd_Bomb_MK82","uns_pylonRack_1Rnd_Bomb_MK82","uns_pylonRack_1Rnd_Bomb_MK82","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_1Rnd_fuel_A1"]; - _plane setVariable ["mainGun", "uns_Uns_M2_4x20mmNR30"]; + _loadout = ["uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_1Rnd_Rocket_HVAR_AT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_19Rnd_Rocket_FFAR_HEAT","uns_pylonRack_1Rnd_fuel_A1"]; + _plane setVariable ["mainGun", "uns_Uns_M2_4x20mm"]; _plane setVariable ["rocketLauncher", ["Uns_FFAR_HEAT_Launcher_dl", "Uns_HVARLauncher_dl"]]; }; case "uns_A7_CAS": @@ -244,7 +249,7 @@ if (_type == "AA") then case "UK3CB_KRG_B_L39_PYLON"; case "UK3CB_LDF_B_L39_PYLON": { - _loadout = ["PylonRack_1Rnd_Missile_AA_04_F","PylonRack_1Rnd_AAA_missiles","PylonRack_1Rnd_AAA_missiles","PylonWeapon_300Rnd_20mm_shells","PylonRack_1Rnd_AAA_missiles","PylonRack_1Rnd_AAA_missiles","PylonRack_1Rnd_Missile_AA_04_F"]; + _loadout = ["PylonRack_1Rnd_Missile_AA_04_F","PylonRack_1Rnd_AAA_missiles","PylonRack_1Rnd_GAA_missiles","PylonWeapon_300Rnd_20mm_shells","PylonRack_1Rnd_GAA_missiles","PylonRack_1Rnd_AAA_missiles","PylonRack_1Rnd_Missile_AA_04_F"]; }; case "UK3CB_LDF_B_MIG21_AA"; case "UK3CB_TKA_B_MIG21_AA": diff --git a/A3A/addons/core/functions/Base/fn_timingCA.sqf b/A3A/addons/core/functions/Base/fn_timingCA.sqf index 9082d04b28..8e5c84b8f9 100644 --- a/A3A/addons/core/functions/Base/fn_timingCA.sqf +++ b/A3A/addons/core/functions/Base/fn_timingCA.sqf @@ -14,44 +14,10 @@ params ["_timeToAdd", "_side"]; -if (isNil "_timeToAdd") exitWith {}; -if !(_timeToAdd isEqualType 0) exitWith {}; +// Function is obsolete but still used by mission rewards +// for now, fudge some effect on attack/defence resources -if (_timeToAdd < 0) then -{ - //Easy difficulty - if(skillMult == 1) then - { - _timeToAdd = round (_timeToAdd * 0.75); - }; - //Hard difficulty - if(skillMult == 3) then - { - _timeToAdd = round (_timeToAdd * 1.25); - }; -} -else -{ - //Easy difficulty - if(skillMult == 1) then - { - _timeToAdd = round (_timeToAdd * 1.25); - }; - //Hard difficulty - if(skillMult == 3) then - { - _timeToAdd = round (_timeToAdd * 0.75); - }; -}; - -if(_side == Occupants) then -{ - attackCountdownOccupants = attackCountdownOccupants + _timeToAdd; - publicVariable "attackCountdownOccupants"; -}; - -if(_side == Invaders) then -{ - attackCountdownInvaders = attackCountdownInvaders + _timeToAdd; - publicVariable "attackCountdownInvaders"; -}; +if (_timeToAdd < 0) exitWith {}; +[-_timeToAdd/10, _side, "defence"] call A3A_fnc_addEnemyResources; +[-_timeToAdd/10, _side, "attack"] call A3A_fnc_addEnemyResources; +if (true) exitWith {}; diff --git a/A3A/addons/core/functions/Base/fn_vehicleBoxHeal.sqf b/A3A/addons/core/functions/Base/fn_vehicleBoxHeal.sqf index 040184e8a2..9492f61f51 100644 --- a/A3A/addons/core/functions/Base/fn_vehicleBoxHeal.sqf +++ b/A3A/addons/core/functions/Base/fn_vehicleBoxHeal.sqf @@ -48,19 +48,11 @@ private _posHQ = getMarkerPos respawnTeamPlayer; }; } forEach allUnits; -//clear report from vehicles that are alive, at HQ, and reported -private _reportCleared = false; +//clear report from vehicles that are at HQ and reported { - if ( - alive _x - && {_x distance _posHQ < 150} - && {_x in reportedVehs} - ) then { - reportedVehs deleteAt (reportedVehs find _x); - _reportCleared = true; - }; -} forEach vehicles; -if (_reportCleared) then { publicVariable "reportedVehs" };//spare publicVariable for every vehicle at hq + if (isNil {_x getVariable "A3A_reported"}) then { continue }; + _x setVariable ["A3A_reported", nil, true]; +} forEach (vehicles inAreaArray [_posHQ, 150, 150]); ["vehicleBoxHeal", [_posHQ]] call EFUNC(Events,triggerEvent); [localize "STR_antistasi_singleWord_Heal", localize "STR_antistasi_Base_vehicleBoxHeal_Healed"] call A3A_fnc_customHint; diff --git a/A3A/addons/core/functions/CREATE/fn_AAFroadPatrol.sqf b/A3A/addons/core/functions/CREATE/fn_AAFroadPatrol.sqf index a73f954b99..5ec17bd8d1 100644 --- a/A3A/addons/core/functions/CREATE/fn_AAFroadPatrol.sqf +++ b/A3A/addons/core/functions/CREATE/fn_AAFroadPatrol.sqf @@ -11,46 +11,45 @@ _groups = []; _base = ""; _roads = []; -_arrayAirports = if (A3A_hasIFA) then {(airportsX + outposts) select {((spawner getVariable _x != 0)) and (sidesX getVariable [_x,sideUnknown] != teamPlayer)}} else {(seaports + airportsX + outposts) select {((spawner getVariable _x != 0)) and (sidesX getVariable [_x,sideUnknown] != teamPlayer)}}; -_arrayAirports1 = []; - -private _isValidPatrolOrigin = if (isMultiplayer) then { - {playableUnits findIf {(side (group _x) == teamPlayer) and (_x distance2d _this < distanceForLandAttack)} != -1}; -} else { - {[distanceForLandAttack,1,_this,teamPlayer] call A3A_fnc_distanceUnits}; +private _players = allPlayers - entities "HeadlessClient_F"; +private _bases = (seaports + airportsX + outposts) select { + call { + if (_players inAreaArray [markerPos _x, 2000, 2000] isEqualTo []) exitWith {false}; + private _side = sidesX getVariable [_x, sideUnknown]; + if (_side == teamPlayer) exitWith {false}; + if (_x in seaports and Faction(_side) get "vehiclesGunBoats" isEqualTo []) exitWith {false}; + if (_x call A3A_fnc_getMarkerNavPoint == -1) exitWith {false}; + true; + }; }; +if (_bases isEqualTo []) exitWith {}; -{ - _airportX = _x; - _pos = getMarkerPos _airportX; - if (_pos call _isValidPatrolOrigin) then {_arrayAirports1 pushBack _airportX}; -} forEach _arrayAirports; - -if (_arrayAirports1 isEqualTo []) exitWith {}; +Debug_1("Possible patrol bases %1", _bases); -_base = selectRandom _arrayAirports1; +_base = selectRandom _bases; _sideX = sidesX getVariable [_base,sideUnknown]; private _faction = Faction(_sideX); _typeCar = ""; _typePatrol = "LAND"; -private _boats = (_faction get "vehiclesGunBoats") select {[_x] call A3A_fnc_vehAvailable}; -if ((_base in seaports) && {count _boats > 0}) then { - _typeCar = selectRandom _boats; - _typePatrol = "SEA"; +if (_base in seaports) then { + _typeCar = selectRandom (_faction get "vehiclesGunBoats"); + _typePatrol = "SEA"; } else { - if ( _sideX isEqualTo Invaders || random 100 < aggressionOccupants ) then { - _typeCar = selectRandom ( - if (_base in airportsX) then { - (_faction get "vehiclesLightArmed") + (_faction get "vehiclesLightUnarmed") + (_faction get "vehiclesHelisLight") - } else {_faction get "vehiclesHelisLight"} - ); - if (_typeCar in (_faction get "vehiclesHelisLight")) then {_typePatrol = "AIR"}; - } else { - _typeCar = selectRandom ( (_faction get "vehiclesPolice") + (_faction get "vehiclesMilitiaLightArmed") ); - }; + if ( _sideX isEqualTo Invaders || random 10 < tierWar + aggressionOccupants/10) then { + private _lowAir = _faction getOrDefault ["attributeLowAir", false]; + if (!_lowAir and (_base in airportsX) and (random 1 < 0.5)) exitWith { + _typeCar = selectRandom (_faction get "vehiclesHelisLight"); + _typePatrol = "AIR"; + }; + _typeCar = selectRandom ((_faction get "vehiclesLightArmed") + (_faction get "vehiclesLightUnarmed")); + } else { + _typeCar = selectRandom ((_faction get "vehiclesPolice") + (_faction get "vehiclesMilitiaLightArmed")); + }; }; +Info_3("Sending patrol of type %1 vehicle %2 from %3", _typePatrol, _typeCar, _base); + _posbase = getMarkerPos _base; @@ -139,7 +138,8 @@ while {alive _veh} do _Vwp0 setWaypointSpeed "LIMITED"; _veh setFuel 1; - waitUntil {sleep 60; (_veh distance _posDestination < _distanceX) or ({[_x] call A3A_fnc_canFight} count _soldiers == 0) or (!canMove _veh)}; + private _timeout = time + (_veh distance2d _posDestination) / 6 + 300; // stuck detection + waitUntil {sleep 60; (_veh distance _posDestination < _distanceX) or (_timeout > time) or ({[_x] call A3A_fnc_canFight} count _soldiers == 0) or (!canMove _veh)}; if !(_veh distance _posDestination < _distanceX) exitWith {}; if (_typePatrol == "AIR") then { @@ -159,13 +159,7 @@ while {alive _veh} do }; }; -{ - private _wp = _x addWaypoint [getMarkerPos _base, 50]; - _wp setWaypointType "MOVE"; - _x setCurrentWaypoint _wp; - [_x] spawn A3A_fnc_groupDespawner; // this one did care about enemies. Not sure why. -} forEach _groups; - -{ [_x] spawn A3A_fnc_vehDespawner } forEach _vehiclesX; +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _vehiclesX; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach _groups; AAFpatrols = AAFpatrols - 1; diff --git a/A3A/addons/core/functions/CREATE/fn_AIVEHinit.sqf b/A3A/addons/core/functions/CREATE/fn_AIVEHinit.sqf index 73538d6f81..436346bb3c 100644 --- a/A3A/addons/core/functions/CREATE/fn_AIVEHinit.sqf +++ b/A3A/addons/core/functions/CREATE/fn_AIVEHinit.sqf @@ -6,12 +6,13 @@ Params: 1. Object: Vehicle object 2. Side: Side ownership for vehicle + 3. String: (Optional) Resource pool for vehicle */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -params ["_veh", "_side"]; + +params ["_veh", "_side", "_resPool"]; if (isNil "_veh") exitWith {}; -#define OccAndInv(VAR) (FactionGet(occ,VAR) + FactionGet(inv,VAR)) if !(isNil { _veh getVariable "ownerSide" }) exitWith { @@ -22,6 +23,9 @@ if !(isNil { _veh getVariable "ownerSide" }) exitWith _veh setVariable ["originalSide", _side, true]; _veh setVariable ["ownerSide", _side, true]; +if (isNil "_resPool") then { _resPool = "legacy" }; +_veh setVariable ["A3A_resPool", _resPool, true]; + // probably just shouldn't be called for these if ((_veh isKindOf "Building") or (_veh isKindOf "ReammoBox_F")) exitWith {}; //if (_veh isKindOf "ReammoBox_F") exitWith {[_veh] call A3A_fnc_NATOcrate}; @@ -39,34 +43,26 @@ if (_side == teamPlayer) then _veh call A3A_fnc_vehicleTextureSync; private _typeX = typeOf _veh; -if ( - _typeX in (OccAndInv("vehiclesLight") - + OccAndInv("vehiclesTrucks") - + OccAndInv("vehiclesAmmoTrucks") - + OccAndInv("vehiclesRepairTrucks") - + OccAndInv("vehiclesFuelTrucks") - + OccAndInv("vehiclesMedical") - ) - or (_typeX in FactionGet(all,"vehiclesArmor"))) then +if (_veh isKindOf "Car" or _veh isKindOf "Tank") then { - _veh call A3A_fnc_addActionBreachVehicle; + // isn't this section basically supposed to be all ground vehicles? + if (_side == teamPlayer or _side == civilian) exitWith {}; // arguable - if !(_typeX in FactionGet(all,"vehiclesAttack")) then + if (_typeX in FactionGet(all,"vehiclesArmor")) then { _veh call A3A_fnc_addActionBreachVehicle }; + + if (_veh isKindOf "Car") then { - if (_veh isKindOf "Car") then + _veh addEventHandler ["HandleDamage",{if (((_this select 1) find "wheel" != -1) and ((_this select 4=="") or (side (_this select 3) != teamPlayer)) and (!isPlayer driver (_this select 0))) then {0} else {(_this select 2)}}]; + if ({"SmokeLauncher" in (_veh weaponsTurret _x)} count (allTurrets _veh) > 0) then { - _veh addEventHandler ["HandleDamage",{if (((_this select 1) find "wheel" != -1) and ((_this select 4=="") or (side (_this select 3) != teamPlayer)) and (!isPlayer driver (_this select 0))) then {0} else {(_this select 2)}}]; - if ({"SmokeLauncher" in (_veh weaponsTurret _x)} count (allTurrets _veh) > 0) then - { - _veh setVariable ["within",true]; - _veh addEventHandler ["GetOut", {private ["_veh"]; _veh = _this select 0; if (side (_this select 2) != teamPlayer) then {if (_veh getVariable "within") then {_veh setVariable ["within",false]; [_veh] call A3A_fnc_smokeCoverAuto}}}]; - _veh addEventHandler ["GetIn", {private ["_veh"]; _veh = _this select 0; if (side (_this select 2) != teamPlayer) then {_veh setVariable ["within",true]}}]; - }; + _veh setVariable ["within",true]; + _veh addEventHandler ["GetOut", {private ["_veh"]; _veh = _this select 0; if (side (_this select 2) != teamPlayer) then {if (_veh getVariable "within") then {_veh setVariable ["within",false]; [_veh] call A3A_fnc_smokeCoverAuto}}}]; + _veh addEventHandler ["GetIn", {private ["_veh"]; _veh = _this select 0; if (side (_this select 2) != teamPlayer) then {_veh setVariable ["within",true]}}]; }; } else { - if (_typeX in FactionGet(all,"vehiclesAPCs")) then + if (_typeX in FactionGet(all,"vehiclesAPCs") + FactionGet(all,"vehiclesIFVs") + FactionGet(all,"vehiclesLightAPCs")) then { _veh addEventHandler ["HandleDamage",{private ["_veh"]; _veh = _this select 0; if (!canFire _veh) then {[_veh] call A3A_fnc_smokeCoverAuto; _veh removeEventHandler ["HandleDamage",_thisEventHandler]};if (((_this select 1) find "wheel" != -1) and (_this select 4=="") and (!isPlayer driver (_veh))) then {0;} else {(_this select 2);}}]; _veh setVariable ["within",true]; @@ -74,7 +70,7 @@ if ( _veh addEventHandler ["GetIn", {private ["_veh"];_veh = _this select 0; if (side (_this select 2) != teamPlayer) then {_veh setVariable ["within",true]}}]; } else - {//vehiclesAttack is occ&inv tank and apc, so this is for occ&inv tanks + { // tanks and AA _veh addEventHandler ["HandleDamage",{private ["_veh"]; _veh = _this select 0; if (!canFire _veh) then {[_veh] call A3A_fnc_smokeCoverAuto; _veh removeEventHandler ["HandleDamage",_thisEventHandler]}; _this select 2}]; }; }; @@ -132,10 +128,51 @@ if (_side == civilian) then }]; }; +// Handler for enemy responses to vehicle damage +if (_side == Invaders or _side == Occupants) then +{ + _veh addEventHandler ["HandleDamage", { + params ["_veh", "_part", "_damage", "_source"]; + if (_damage < 0.5) exitWith { nil }; // rough as hell, but whatever + if (isNil "_source" or {isNull _source or side _source == side _veh}) exitWith { nil }; + + _veh removeEventHandler ["HandleDamage", _thisEventHandler]; + if (_veh getVariable "ownerSide" != _veh getVariable "originalSide") exitWith { nil }; + + // Add 1/3 cost to recent casualties list on server + private _vehCost = A3A_vehicleResourceCosts getOrDefault [typeof _veh, 0]; + [_veh getVariable "ownerSide", getPos _veh, _vehCost/3] remoteExec ["A3A_fnc_addRecentDamage", 2]; + + // Attempt to call for support if there's a crew. Assume local, should be true + if !(isNull group _veh) then { [group _veh, _source] spawn A3A_fnc_callForSupport }; + nil; + }]; + + if (_veh isKindOf "Helicopter") then { + // Event handler to (usually) get the crew out after crippling damage + // Doesn't cover dead pilot / live co-pilot case, should eventually be handled by AI routines + _veh addEventHandler ["Dammaged", { + params ["_veh"]; + if (canMove _veh) exitWith {}; + Debug("Downed heli handler triggered"); + group _veh leaveVehicle _veh; + _veh removeEventHandler ["Dammaged", _thisEventHandler]; + }]; + }; + + _veh addEventHandler ["IncomingMissile", { + params ["_veh", "_ammo", "_source", "_instigator"]; + private _group = group _veh; + if (isNull _group or { side _group == teamPlayer }) exitWith { _veh removeEventHandler ["IncomingMissile", _thisEventHandler] }; + [_group, _source] spawn A3A_fnc_callForSupport; + }]; +}; + if(_typeX in (FactionGet(all, "vehiclesArtillery") + FactionGet(all, "staticMortars")) ) then { [_veh] call A3A_fnc_addArtilleryTrailEH; - [_veh] remoteExec ["A3A_fnc_addArtilleryDetectionEH", 2]; +// Redundant with support system? +// [_veh] remoteExec ["A3A_fnc_addArtilleryDetectionEH", 2]; }; // EH behaviour: @@ -166,44 +203,21 @@ if (_side != teamPlayer) then if(_veh isKindOf "Air") then { //Start airspace control script if rebel player enters - _veh addEventHandler - [ - "GetIn", - { - params ["_veh", "_role", "_unit"]; - if((side (group _unit) == teamPlayer) && {isPlayer _unit}) then - { - [_veh] spawn A3A_fnc_airspaceControl; - }; - } - ]; - - - _veh addEventHandler - [ - "IncomingMissile", - { - params ["_target", "_ammo", "_vehicle", "_instigator"]; - private _group = group driver _target; - private _supportTypes = [_group, _vehicle] call A3A_fnc_chooseSupport; - _supportTypes = _supportTypes - ["QRF"]; - private _reveal = [getPos _vehicle, side _group] call A3A_fnc_calculateSupportCallReveal; - [_vehicle, 4, _supportTypes, side _group, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - } - ] + _veh addEventHandler ["GetIn", { + params ["_veh", "_role", "_unit"]; + if((side (group _unit) == teamPlayer) && {isPlayer _unit}) then + { + // TODO: check this isn't spammed + [_veh] spawn A3A_fnc_airspaceControl; + }; + }]; }; -// Handler to prevent vehDespawner deleting vehicles for an hour after rebels exit them -_veh addEventHandler ["GetOut", { - params ["_veh", "_role", "_unit"]; - if !(_unit isEqualType objNull) exitWith { - ServerError_3("GetOut handler weird input: %1, %2, %3", _veh, _role, _unit); - }; - if (side group _unit == teamPlayer) then { - _veh setVariable ["despawnBlockTime", time + 3600]; // despawner always launched locally - }; -}]; +// Handler for refunding vehicles after cleanup +if (A3A_vehicleResourceCosts getOrDefault [typeof _veh, 0] > 0) then { + _veh addEventHandler ["Deleted", A3A_fnc_vehicleDeletedEH]; +}; //add logistics loading to loadable objects diff --git a/A3A/addons/core/functions/CREATE/fn_FIAinitBASES.sqf b/A3A/addons/core/functions/CREATE/fn_FIAinitBASES.sqf index f5b2decd5a..f98a029c9b 100644 --- a/A3A/addons/core/functions/CREATE/fn_FIAinitBASES.sqf +++ b/A3A/addons/core/functions/CREATE/fn_FIAinitBASES.sqf @@ -29,7 +29,7 @@ if (count _this > 1) then _unit allowFleeing 0; _typeX = _unit getVariable "unitType"; -_skill = (0.6 / skillMult + 0.015 * skillFIA); +_skill = (0.1 + 0.1*A3A_rebelSkillMul + 0.015 * skillFIA); _unit setSkill _skill; if (_typeX isEqualTo FactionGet(reb,"unitSL")) then { diff --git a/A3A/addons/core/functions/CREATE/fn_NATOinit.sqf b/A3A/addons/core/functions/CREATE/fn_NATOinit.sqf index df8937c54a..ecac0c889d 100644 --- a/A3A/addons/core/functions/CREATE/fn_NATOinit.sqf +++ b/A3A/addons/core/functions/CREATE/fn_NATOinit.sqf @@ -1,4 +1,4 @@ -params ["_unit", ["_marker", ""], "_isSpawner"]; +params ["_unit", ["_marker", ""], "_isSpawner", "_resPool"]; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() /* Inits the given unit with all needed data, flags and weapons @@ -6,7 +6,7 @@ FIX_LINE_NUMBERS() * _unit : OBJECT : The unit that needs to be initialized * _marker : STRING : The name of the marker (default "") * _isSpawner : BOOL : (Optional) Whether the unit should be made a spawner, otherwise automatic -* +* _resPool : STRING : (Optional) Resource pool name of unit (attack, defence, garrison, legacy?) * Returns: * Nothing */ @@ -20,6 +20,7 @@ if ((isNil "_unit") || (isNull _unit)) exitWith private _type = _unit getVariable "unitType"; private _side = side (group _unit); private _faction = Faction(_side); +_unit setVariable ["originalSide", _side]; // used for delete handler, which is local if (isNil "_type") then { Error_2("Unit does not have a type assigned: %1, vehicle: %2", typeOf _unit, typeOf vehicle _unit); @@ -28,13 +29,18 @@ if (isNil "_type") then { if (_type == "Fin_random_F") exitWith {}; -//Sets the EH for the unit -_unit addEventHandler ["HandleDamage", A3A_fnc_handleDamageAAF]; -_unit addEventHandler ["killed", A3A_fnc_occupantInvaderUnitKilledEH]; + +// Set source resource pool for unit +if (isNil "_resPool") then { + // Avoiding editing every garrison/mission file for now + _resPool = ["legacy", "garrison"] select (_marker != ""); +}; +_unit setVariable ["A3A_resPool", _resPool, true]; if !(isNil "_isSpawner") then { if (_isSpawner) then { _unit setVariable ["spawner",true,true] }; + if (_marker != "") then { _unit setVariable ["markerX",_marker,true] }; } else { @@ -55,16 +61,14 @@ else { // Cargo units aren't spawners until they leave the vehicle. // Assumes that they'll get out if the crew are murdered. - _unit addEventHandler - [ - "GetOutMan", - { - _unit = _this select 0; - if !(_unit getVariable ["surrendered", false]) then { - _unit setVariable ["spawner",true,true]; - }; - } - ]; + _unit setVariable ["spawner", false]; // local-only, use to distinguish when spawner status is removed + _unit addEventHandler ["GetOutMan", { + _unit = _this select 0; + if (!isNil {_unit getVariable "spawner"}) then { + _unit setVariable ["spawner",true,true]; + }; + _unit removeEventHandler [_thisEvent, _thisEventHandler]; + }]; }; // Fixed-wing aircraft spawn far too much with little effect. @@ -75,8 +79,15 @@ else _unit setVariable ["spawner",true,true] }; +// Install event handlers for the unit +_unit addEventHandler ["HandleDamage", A3A_fnc_handleDamageAAF]; +_unit addEventHandler ["Killed", A3A_fnc_enemyUnitKilledEH]; +_unit addEventHandler ["Deleted", A3A_fnc_enemyUnitDeletedEH]; + + //Calculates the skill of the given unit -private _skill = (0.15 * skillMult) + (0.04 * difficultyCoef) + (0.02 * tierWar); +//private _skill = (0.15 * skillMult) + (0.04 * difficultyCoef) + (0.02 * tierWar); +private _skill = (0.1 * A3A_enemySkillMul) + (0.15 * A3A_balancePlayerScale) + (0.01 * tierWar); private _regularFaces = (_faction get "faces"); private _regularVoices = (_faction get "voices"); private ["_face", "_voice"]; @@ -84,19 +95,19 @@ private ["_face", "_voice"]; switch (true) do { case ("militia_" in (_unit getVariable "unitType")): { - _skill = _skill min (0.2 * skillMult); + _skill = _skill * 0.7; _face = selectRandom (_faction getOrDefault ["milFaces", _regularFaces]); _voice = selectRandom (_faction getOrDefault ["milVoices", _regularVoices]); }; case ("police" in (_unit getVariable "unitType")): { - _skill = _skill min (0.12 * skillMult); + _skill = _skill * 0.5; _face = selectRandom (_faction getOrDefault ["polFaces", _regularFaces]); _voice = selectRandom (_faction getOrDefault ["polVoices", _regularVoices]); }; case ("SF" in (_unit getVariable "unitType")): { - _skill = _skill min (0.12 * skillMult); + _skill = _skill * 1.2; _face = selectRandom (_faction getOrDefault ["sfFaces", _regularFaces]); _voice = selectRandom (_faction getOrDefault ["sfVoices", _regularVoices]); }; @@ -112,6 +123,7 @@ default { }; [_unit, _face, _voice] call BIS_fnc_setIdentity; _unit setSkill _skill; + //Adjusts squadleaders with improved skill and adds intel action if (_type in FactionGet(all,"SquadLeaders")) then { diff --git a/A3A/addons/core/functions/CREATE/fn_VEHdespawner.sqf b/A3A/addons/core/functions/CREATE/fn_VEHdespawner.sqf index 23e6df4c13..a59c287ea9 100644 --- a/A3A/addons/core/functions/CREATE/fn_VEHdespawner.sqf +++ b/A3A/addons/core/functions/CREATE/fn_VEHdespawner.sqf @@ -3,19 +3,15 @@ params ["_veh", ["_checkNonRebel", false]]; if (!isNil {_veh getVariable "inDespawner"}) exitWith {}; _veh setVariable ["inDespawner", true, true]; +_veh setVariable ["A3A_despawnerHandle", _thisScript]; -// despawnBlockTime should be increased when a rebel exits a vehicle -private _blockTime = _veh getVariable ["despawnBlockTime", 0]; while {alive _veh} do { - sleep (60 max (_blockTime - time)); + sleep 60; if !(alive _veh) exitWith {}; - _blockTime = _veh getVariable ["despawnBlockTime", 0]; private _despawn = call { if ({ alive _x } count crew _veh > 0) exitWith {false}; - if (_veh distance getMarkerPos respawnTeamPlayer < 100) exitWith {false}; - if (_blockTime > time) exitWith {false}; if !(isNull attachedTo _veh) exitWith {false}; // don't despawn attached objects if ([distanceSPWN,1,_veh,teamPlayer] call A3A_fnc_distanceUnits) exitWith {false}; if !(_checkNonRebel) exitWith {true}; @@ -24,8 +20,5 @@ while {alive _veh} do true; }; - if (_despawn) exitWith { - if (_veh in reportedVehs) then {reportedVehs = reportedVehs - [_veh]; publicVariable "reportedVehs"}; - deleteVehicle _veh; - }; + if (_despawn) exitWith { deleteVehicle _veh }; }; diff --git a/A3A/addons/core/functions/CREATE/fn_WPCreate.sqf b/A3A/addons/core/functions/CREATE/fn_WPCreate.sqf index c079e477e2..704eba3396 100644 --- a/A3A/addons/core/functions/CREATE/fn_WPCreate.sqf +++ b/A3A/addons/core/functions/CREATE/fn_WPCreate.sqf @@ -3,8 +3,8 @@ Maintainer: Wurzel0701 Creates waypoints for spawned units to safely arrive at targets Arguments: - The start position OR The start marker - The end position OR The end marker + The start position OR The start marker + The end position OR The end marker The group for which the waypoints should be created Return Value: @@ -35,18 +35,33 @@ private _posOrigin = if(_origin isEqualType "") then {getMarkerPos _origin} else private _posDestination = if(_destination isEqualType "") then {getMarkerPos _destination} else {_destination}; private _path = [_posOrigin, _posDestination] call A3A_fnc_findPath; -_path = [_path] call A3A_fnc_trimPath; +_path = [_path] call A3A_fnc_trimPath; // some functionality here is questionable... -//Get rid of the first part of to avoid driving back -if(count _path > 0) then -{ - _path deleteAt 0; +// Pathfinding failed? Just make a waypoint on the destination +if(count _path < 2) exitWith { + private _wp = _group addWaypoint [_posDestination, 0]; + _wp setWaypointBehaviour "SAFE"; + _group setCurrentWaypoint _wp; }; -private _waypoints = _path apply {_group addWaypoint [_x, 0]}; -{_x setWaypointBehaviour "SAFE"} forEach _waypoints; +_path deleteAt 0; //Get rid of the first part of to avoid driving back -if (count _waypoints > 0) then +// Do some additional distance-based culling to improve travel speed +reverse _path; +private _prevPos = _path deleteAt 0; +private _culledPath = [_prevPos]; +private _distToPrev = 0; { - _group setCurrentWaypoint (_waypoints select 0); -}; + _distToPrev = _distToPrev + (_prevPos distance2d _x); + if (_distToPrev >= 400) then { + _culledPath pushBack _x; + _distToPrev = 0; + }; + _prevPos = _x; +} forEach _path; +_path = _culledPath; +reverse _path; + +private _waypoints = _path apply {_group addWaypoint [ATLtoASL _x, -1]}; +{_x setWaypointBehaviour "SAFE"} forEach _waypoints; +_group setCurrentWaypoint (_waypoints select 0); diff --git a/A3A/addons/core/functions/CREATE/fn_airportCanAttack.sqf b/A3A/addons/core/functions/CREATE/fn_airportCanAttack.sqf index 107775210a..6791272789 100644 --- a/A3A/addons/core/functions/CREATE/fn_airportCanAttack.sqf +++ b/A3A/addons/core/functions/CREATE/fn_airportCanAttack.sqf @@ -1,9 +1,9 @@ private _markerX = _this select 0; -if ((spawner getVariable _markerX) != 2) exitWith {false}; -if (!(_markerX in airportsX) and !(_markerX in outposts)) exitWith {false}; if !(dateToNumber date > server getVariable [_markerX,0]) exitWith {false}; -private _isQRF = _this select 1; -if (_isQRF and (count (garrison getVariable [_markerX,[]]) <= 8)) exitWith {false}; -if (!_isQRF and (count (garrison getVariable [_markerX,[]]) < 16)) exitWith {false}; +if (_markerX == "CSAT_Carrier" or _markerX == "NATO_Carrier") exitWith {true}; + +if ((spawner getVariable _markerX) == 0) exitWith {false}; +if (!(_markerX in airportsX) and !(_markerX in outposts)) exitWith {false}; +if (count (garrison getVariable [_markerX,[]]) < 16) exitWith {false}; if (_markerX in forcedSpawn) exitWith {false}; true diff --git a/A3A/addons/core/functions/CREATE/fn_ambientCivs.sqf b/A3A/addons/core/functions/CREATE/fn_ambientCivs.sqf index 46994725da..1a19ad148b 100644 --- a/A3A/addons/core/functions/CREATE/fn_ambientCivs.sqf +++ b/A3A/addons/core/functions/CREATE/fn_ambientCivs.sqf @@ -28,7 +28,7 @@ while {true} do { _civs = _civs - _abuse; }; _allCivs = allUnits select {(alive _x) and (side _x == civilian)}; - if ((count _allCivs < civPerc) and ({(local _x) and (simulationEnabled _x) and (alive _x)} count allUnits < maxUnits)) then { + if (count _allCivs < civPerc) then { if (_reset) then {_houses = (nearestTerrainObjects [player, ["House"], 300]) select {(count (_x buildingPos -1) > 0)}}; _houses = _houses select {!((typeOf _x) in listMilBld)}; _numhouses = count _houses; diff --git a/A3A/addons/core/functions/CREATE/fn_attackHQ.sqf b/A3A/addons/core/functions/CREATE/fn_attackHQ.sqf new file mode 100644 index 0000000000..77e88ab9ac --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_attackHQ.sqf @@ -0,0 +1,103 @@ +/* +Maintainer: John Jordan + Send a special forces air attack to kill Petros + +Scope: Server +Environment: Scheduled, should be spawned + +Arguments: + Side from which to send the attack (Occupants or Invaders) + Marker name of airport to send the attack from + Optional: Delay in seconds after creating the task (Default: Auto-calculated from balancePlayerScale) +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() +//Mission: HQ is under attack +if (!isServer) exitWith { Error("Server-only function miscalled") }; + +params ["_side", "_airbase", "_delay"]; // Side is now specified +private _targPos = markerPos "Synd_HQ"; +private _faction = Faction(_side); + +bigAttackInProgress = true; +publicVariable "bigAttackInProgress"; + +private _taskId = "DEF_HQ" + str A3A_taskCount; +[[teamPlayer,civilian],_taskId,[format ["The enemy has sent SpecOps to find %1. Stop them, or move the HQ before they get here.",name petros],format ["Defend %1",name petros],respawnTeamPlayer],_targPos,true,10,true,"Defend",true] call BIS_fnc_taskCreate; +[_taskId, "DEF_HQ", "CREATED"] remoteExecCall ["A3A_fnc_taskUpdate", 2]; + + +// Send in a UAV. Add half a vehicle if they're unavailable +// ["_type", "_side", "_caller", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; +private _uavSupp = ["UAV", _side, "attack", 500, objNull, _targPos, 0, 0] call A3A_fnc_createSupport; + +// Create the attacking force +private _vehCount = round (1 + random 1 + 2 * A3A_balancePlayerScale + ([0, 0.5] select (_uavSupp == ""))); + +// Give smaller player groups a bit more time to respond +if (isNil "_delay") then { _delay = 300 / A3A_balancePlayerScale }; + +//params ["_side", "_airbase", "_target", "_resPool", "_vehCount", "_delay", "_modifiers", "_attackType", "_reveal"]; +private _data = [_side, _airbase, _targPos, "attack", _vehCount, _delay, ["airboost", "specops"]] call A3A_fnc_createAttackForceMixed; +_data params ["_resources", "_vehicles", "_crewGroups", "_cargoGroups"]; + +// May as well do it properly here +A3A_supportStrikes pushBack [_side, "TROOPS", _targPos, time + 1800, 1800, _resources]; + + +// Call up some artillery +call { + // Choose target/pos. Aim for static weapon if known, or just somewhere around flag otherwise + private _target = _targPos getPos [random 100, random 360]; + private _vehicles = vehicles inAreaArray [_targPos, 100, 100]; + _vehicles = _vehicles select { canFire _x and _x isKindOf "StaticWeapon" }; + if !(_vehicles isEqualTo []) then { _target = selectRandom _vehicles }; + + // ["_side", "_target", "_pool", "_precision", "_reveal", "_delay"]; + [_side, _target, "attack", 2, 0, 0] call A3A_fnc_requestArtillery; +}; + +// TODO: Could add an extra timed "petros surrender" condition if there are too many enemies near him + +private _timeout = time + 900; // It's a lightning raid, don't string it out +private _soldiers = []; +{ _soldiers append units _x } forEach _cargoGroups; +private _origPetros = petros; + +while {true} do +{ + private _curSoldiers = { !fleeing _x and _x call A3A_fnc_canFight } count _soldiers; + if (_curSoldiers < count _soldiers * 0.33) exitWith { + ServerInfo("HQ attack has been defeated, starting retreat"); + }; + if (time > _timeOut) exitWith { + ServerInfo("HQ attack timed out, starting retreat"); + }; + if (!alive _origPetros) exitWith { + ServerInfo("HQ attack succeeded in killing petros, starting retreat"); + }; + sleep 30; +}; + +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _vehicles; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach (_crewGroups + _cargoGroups); + +sleep 60; + +if (!alive _origPetros) then { + [_taskId, "DEF_HQ", "FAILED"] call A3A_fnc_taskSetState; + // Other results handled by petros death code +} else { + [_taskId, "DEF_HQ", "SUCCEEDED"] call A3A_fnc_taskSetState; + if (_targPos distance markerPos respawnTeamPlayer < 500) then { // assume we fought it out? + [_side, 10, 60] remoteExec ["A3A_fnc_addAggression",2]; + // This is bullshit really + {if (isPlayer _x) then {[10,_x] call A3A_fnc_playerScoreAdd}} forEach ([500,0,_targPos,teamPlayer] call A3A_fnc_distanceUnits); + }; +}; + +bigAttackInProgress = false; +publicVariable "bigAttackInProgress"; + +[_taskId, "DEF_HQ", 1200] spawn A3A_fnc_taskDelete; diff --git a/A3A/addons/core/functions/CREATE/fn_availableBasesAir.sqf b/A3A/addons/core/functions/CREATE/fn_availableBasesAir.sqf new file mode 100644 index 0000000000..7afa50d097 --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_availableBasesAir.sqf @@ -0,0 +1,39 @@ +/* +Maintainer: John Jordan + Select from distance-weighted list of available enemy air bases or return full list + Checks idle, spawner, distance and garrison + Carrier is always available, so always returns something + +Scope: Anywhere? Only using on server atm +Environment: Scheduled or unscheduled + +Arguments: + Side of enemy faction + Target position to use + Optional, true to return all bases & weights (Default: false) + +Return value: + Marker name of airbase, or [airbases, weights] +*/ + +params ["_side", "_targPos", ["_returnAll", false]]; + +private _freeAirports = []; +private _weights = []; +{ + if (sidesX getVariable [_x,sideUnknown] != _side) then {continue}; + if (dateToNumber date < server getVariable [_x, 0]) then {continue}; + if (spawner getVariable _x == 0) then {continue}; // don't need spawn places, so this is fine + if (count (garrison getVariable [_x,[]]) < 16) then {continue}; + + _freeAirports pushBack _x; + _weights pushBack (1 / (markerPos _x distance2D _targPos)^2); +} forEach airportsX; + +// Carrier/air corridor is always available +private _carrier = ["CSAT_carrier", "NATO_carrier"] select (_side == Occupants); +_freeAirports pushBack _carrier; +_weights pushBack (1 / (markerPos _carrier distance2D _targPos)^2); + +if (_returnAll) exitWith { [_freeAirports, _weights] }; +_freeAirports selectRandomWeighted _weights; diff --git a/A3A/addons/core/functions/CREATE/fn_availableBasesLand.sqf b/A3A/addons/core/functions/CREATE/fn_availableBasesLand.sqf new file mode 100644 index 0000000000..16706ac95b --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_availableBasesLand.sqf @@ -0,0 +1,75 @@ +/* +Maintainer: John Jordan + Select from distance-weighted list of available enemy land bases or return full list + Checks idle, spawner, distance, garrison, spawn places and pathfinding connection + +Scope: Anywhere with navgrid? Only using on server atm +Environment: Scheduled or unscheduled + +Arguments: + Side of enemy faction + Target position or marker name to use + Optional, true to return all bases & weights (Default: false) + +Return value: + Marker name of landbase, or nil if none. Or [landbases, weights] +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_target", ["_returnAll", false]]; + +private _lowAir = Faction(_side) getOrDefault ["attributeLowAir", false]; +private _nearMarkers = [_target, _lowAir] call A3A_fnc_findLandSupportMarkers; + +private _freeBases = []; +private _weights = []; +{ + _x params ["_marker", "_navDist"]; + if (sidesX getVariable [_marker, sideUnknown] != _side) then {continue}; + if (dateToNumber date < server getVariable [_marker, 0]) then {continue}; // addTimeForIdle + if (spawner getVariable _marker != 2) then {continue}; // spawn places dangerous if spawned + if (count (garrison getVariable [_marker,[]]) < 16) then {continue}; + + _freeBases pushBack _marker; + _weights pushBack (1 / _navDist^2); +} forEach _nearMarkers; + +if (_returnAll) exitWith { [_freeBases, _weights] }; +_freeBases selectRandomWeighted _weights; + +// change this to return base, distance and count? +// or could just re-run findNavDistance + +/* +// Uncached version +params ["_side", "_targPos", ["_returnAll", false]]; + +private _targNavIndex = [_targPos] call A3A_fnc_getNearestNavPoint; +if (_targNavIndex == -1) exitWith { nil }; +private _lowAir = Faction(_side) getOrDefault ["attributeLowAir", false]; +private _maxLandDist = distanceForLandAttack + ([1000, 2000] select _lowAir); // Allow extra crow-flies distance, because it checks real distance later + +private _freeBases = []; +private _weights = []; +{ + if (sidesX getVariable [_x,sideUnknown] != _side) then {continue}; + if (dateToNumber date < server getVariable [_x, 0]) then {continue}; // addTimeForIdle + if (spawner getVariable _x != 2) then {continue}; // spawn places dangerous if spawned + if (markerPos _x distance2d _targPos > _maxLandDist) then {continue}; + if (count (garrison getVariable [_x,[]]) < 16) then {continue}; + if (spawner getVariable (_x + "_spawns") select 0 isEqualTo []) then {continue}; // any vehicle spawn places on base +// if !([_x, _targPos] call A3A_fnc_arePositionsConnected) then {continue}; // checked by findNavDistance + + private _navIndex = _x call A3A_fnc_getMarkerNavPoint; + private _navDist = [_targNavIndex, _navIndex, _maxLandDist+500] call A3A_fnc_findNavDistance; + if (_navDist < 0) then { continue }; // no path found within range + + _freeBases pushBack _x; + _weights pushBack (1 / _navDist^2); +} forEach (outposts + airportsX); + +if (_returnAll) exitWith { [_freeBases, _weights] }; +_freeBases selectRandomWeighted _weights; +*/ \ No newline at end of file diff --git a/A3A/addons/core/functions/CREATE/fn_cargoSeats.sqf b/A3A/addons/core/functions/CREATE/fn_cargoSeats.sqf index dcc0757d73..041dcab1b1 100644 --- a/A3A/addons/core/functions/CREATE/fn_cargoSeats.sqf +++ b/A3A/addons/core/functions/CREATE/fn_cargoSeats.sqf @@ -20,7 +20,7 @@ if (_cargoSeats < 4) exitWith _faction get "groupSentry"; }; -if (_cargoSeats < 7) exitWith // fudge for Warrior +if (_cargoSeats < 6 or { _cargoSeats == 6 and random 3 < 1}) exitWith // 6-man normally uses clipped full squad { if (_isMilitia) exitWith { selectRandom (_faction get "groupsMilitiaMedium") }; if (_veh in (_faction get "vehiclesPolice")) exitWith { (_faction get "groupPolice") + [_faction get "unitPoliceGrunt", _faction get "unitPoliceGrunt"] }; @@ -29,7 +29,9 @@ if (_cargoSeats < 7) exitWith // fudge for Warrior private _squad = call { if (_isMilitia) exitWith { selectRandom (_faction get "groupsMilitiaSquads") }; - selectRandom (_faction get "groupsSquads") + selectRandom (_faction get "groupsSquads"); +}; +while { count _squad > _cargoSeats } do { + _squad deleteAt (1 + floor random (count _squad - 1)); // don't remove the squad leader }; -if (_cargoSeats == 7) then { _squad deleteAt 7 }; _squad; diff --git a/A3A/addons/core/functions/CREATE/fn_cleanserVeh.sqf b/A3A/addons/core/functions/CREATE/fn_cleanserVeh.sqf index 976484758c..643bf0ed14 100644 --- a/A3A/addons/core/functions/CREATE/fn_cleanserVeh.sqf +++ b/A3A/addons/core/functions/CREATE/fn_cleanserVeh.sqf @@ -2,9 +2,6 @@ FIX_LINE_NUMBERS() params ["_veh"]; -private _vehpos = getpos _veh; -private _nearestMarker = ([markersX, _vehpos] call BIS_fnc_nearestPosition); - sleep 5; if (isNull _veh) exitWith { @@ -13,7 +10,7 @@ if (isNull _veh) exitWith { if (!alive _veh) then { - Debug_3("%1 destroyed on spawn at %2, near %3", typeof _veh, _vehpos, _nearestMarker); - _veh hideObjectGlobal true; + private _nearestMarker = [markersX, getPosATL _veh] call BIS_fnc_nearestPosition; + Debug_3("%1 destroyed on spawn at %2, near %3", typeof _veh, getPosATL _veh, _nearestMarker); deleteVehicle _veh; }; diff --git a/A3A/addons/core/functions/CREATE/fn_createAIAirplane.sqf b/A3A/addons/core/functions/CREATE/fn_createAIAirplane.sqf index d22ff0ed8f..7ee1d253cf 100644 --- a/A3A/addons/core/functions/CREATE/fn_createAIAirplane.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createAIAirplane.sqf @@ -271,7 +271,7 @@ if (!_busy) then }; }; -_arrayVehAAF = (_faction get "vehiclesLight") + (_faction get "vehiclesTrucks") + (_faction get "vehiclesAmmoTrucks") + (_faction get "vehiclesRepairTrucks") + (_faction get "vehiclesFuelTrucks") + (_faction get "vehiclesMedical"); +_arrayVehAAF = (_faction get "vehiclesLightArmed") + (_faction get "vehiclesLightUnarmed") + (_faction get "vehiclesTrucks") + (_faction get "vehiclesAmmoTrucks") + (_faction get "vehiclesRepairTrucks") + (_faction get "vehiclesFuelTrucks") + (_faction get "vehiclesMedical"); _countX = 0; while {_countX < _nVeh && {_countX < 3}} do diff --git a/A3A/addons/core/functions/CREATE/fn_createAIcontrols.sqf b/A3A/addons/core/functions/CREATE/fn_createAIcontrols.sqf index b68c8b770d..d2cae44985 100644 --- a/A3A/addons/core/functions/CREATE/fn_createAIcontrols.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createAIcontrols.sqf @@ -182,7 +182,7 @@ else {[_x] joinSilent _groupX; _pilots pushBack _x} forEach units _groupUAV; deleteGroup _groupUAV; }; - {[_x,""] call A3A_fnc_NATOinit} forEach units _groupX; + {[_x, "", false] call A3A_fnc_NATOinit} forEach units _groupX; } else { diff --git a/A3A/addons/core/functions/CREATE/fn_createAttackForceAir.sqf b/A3A/addons/core/functions/CREATE/fn_createAttackForceAir.sqf new file mode 100644 index 0000000000..09f3195ce6 --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_createAttackForceAir.sqf @@ -0,0 +1,77 @@ +/* +Maintainer: John Jordan + Create air attack force + +Scope: Server or HC +Environment: Scheduled (sleeps between unit spawns) + +Arguments: + Side to create force for + Marker name of source base to spawn at + Position or marker of target location for attack force + Resource pool to use + Total number of vehicles to create + Number of attack/support vehicles to create + Optional, tier modifier to apply to vehicle selection (Default: 0) + Optional, troop type to use (Default: "Normal") + +Return array: + Resources spent + Array of vehicle objects created + Array of crew groups created + Array of cargo groups created +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_base", "_target", "_resPool", "_vehCount", "_vehAttackCount", ["_tierMod", 0], ["_troopType", "Normal"]]; +private _targpos = if (_target isEqualType []) then { _target } else { markerPos _target }; +private _transportRatio = 1 - _vehAttackCount / _vehCount; + +private _resourcesSpent = 0; +private _vehicles = []; +private _crewGroups = []; +private _cargoGroups = []; + +private _faction = Faction(_side); +private _transportPlanes = _faction get "vehiclesPlanesTransport"; +private _transportHelis = _faction get "vehiclesHelisTransport"; +private _lightHelis = _faction get "vehiclesHelisTransport"; +private _lhFactor = 0 max (1 - (tierWar+_tierMod) / 10); // phase out light helis at higher war tiers + +private _transportPool = []; +{ _transportPool append [_x, 1 / count _transportPlanes] } forEach _transportPlanes; +{ _transportPool append [_x, 2 / count _transportHelis] } forEach _transportHelis; +{ _transportPool append [_x, 2 * _lhFactor / count _transportHelis] } forEach _lightHelis; + +private _supportPool = [_side, tierWar+_tierMod] call A3A_fnc_getVehiclesAirSupport; + +private _numTransports = 0; +private _isTransport = _vehAttackCount < _vehCount; // normal case, first vehicle should be a transport + +for "_i" from 1 to _vehCount do { + private _vehType = selectRandomWeighted ([_supportPool, _transportPool] select _isTransport); + + if (_vehType == "CAS") then { + // no reveal because it's a sub-support, delay because it's faster than the helis + [_vehType, _side, _resPool, 500, false, _targPos, 0, 60] remoteExec ["A3A_fnc_createSupport", 2]; + } else { + private _vehData = [_vehType, _troopType, _resPool, [], _side, _base, _targPos] call A3A_fnc_createAttackVehicle; + if !(_vehData isEqualType []) exitWith {}; // couldn't create for some reason. Not sure why for air vehicles. + + _vehicles pushBack (_vehData#0); + _crewGroups pushBack (_vehData#1); + if !(isNull (_vehData#2)) then { _cargoGroups pushBack (_vehData#2) }; + _landPosBlacklist = (_vehData#3); + + private _vehCost = A3A_vehicleResourceCosts getOrDefault [_vehType, 0]; + private _crewCost = 10 * (count units (_vehData#1) + count units (_vehData#2)); + _resourcesSpent = _resourcesSpent + _vehCost + _crewCost; + sleep 5; + }; + + if (_isTransport) then { _numTransports = _numTransports + 1 }; + _isTransport = _vehAttackCount == 0 or (_numTransports / _i) < _transportRatio; +}; + +[_resourcesSpent, _vehicles, _crewGroups, _cargoGroups]; diff --git a/A3A/addons/core/functions/CREATE/fn_createAttackForceLand.sqf b/A3A/addons/core/functions/CREATE/fn_createAttackForceLand.sqf new file mode 100644 index 0000000000..c6e4e61454 --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_createAttackForceLand.sqf @@ -0,0 +1,71 @@ +/* +Maintainer: John Jordan + Create land attack force + +Scope: Server or HC +Environment: Scheduled (sleeps between unit spawns) + +Arguments: + Side to create force for + Marker name of source base to spawn at + Position or marker of target location for attack force + Resource pool to use + Total number of vehicles to create + Number of attack/support vehicles to create + Optional, tier modifier to apply to vehicle selection (Default: 0) + Optional, troop type to use (Default: "Normal") + +Return array: + Resources spent + Array of vehicle objects created + Array of crew groups created + Array of cargo groups created +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_base", "_target", "_resPool", "_vehCount", "_vehAttackCount", ["_tierMod", 0]]; +private _targpos = if (_target isEqualType []) then { _target } else { markerPos _target }; +private _transportRatio = 1 - _vehAttackCount / _vehCount; + +private _resourcesSpent = 0; +private _vehicles = []; +private _crewGroups = []; +private _cargoGroups = []; + +private _transportPool = [_side, tierWar+_tierMod] call A3A_fnc_getVehiclesGroundTransport; +private _supportPool = [_side, tierWar+_tierMod] call A3A_fnc_getVehiclesGroundSupport; + +private _numTransports = 0; +private _isTransport = _vehAttackCount < _vehCount; // normal case, first vehicle should be a transport +private _landPosBlacklist = []; + +for "_i" from 1 to _vehCount do { + private _vehType = selectRandomWeighted ([_supportPool, _transportPool] select _isTransport); + + private _vehData = [_vehType, "Normal", _resPool, _landPosBlacklist, _side, _base, _targPos] call A3A_fnc_createAttackVehicle; + if !(_vehData isEqualType []) exitWith {}; // couldn't create for some reason, assume we're out of spawn places? + + _vehicles pushBack (_vehData#0); + if (!isNull (_vehData#1)) then { _crewGroups pushBack (_vehData#1) }; + if (!isNull (_vehData#2)) then { _cargoGroups pushBack (_vehData#2) }; + _landPosBlacklist = (_vehData#3); + + private _vehCost = A3A_vehicleResourceCosts getOrDefault [_vehType, 0]; + private _crewCost = 10 * (count units (_vehData#1) + count units (_vehData#2)); + _resourcesSpent = _resourcesSpent + _vehCost + _crewCost; + + if (_isTransport) then { _numTransports = _numTransports + 1 }; + _isTransport = _vehAttackCount == 0 or (_numTransports / _i) < _transportRatio; + + sleep 10; +}; + + +// TODO: Sort out the spawn positions API or don't use it +_base spawn { + sleep 60; + if (spawner getVariable _this == 2) then { [_this] call A3A_fnc_freeSpawnPositions }; +}; + +[_resourcesSpent, _vehicles, _crewGroups, _cargoGroups]; diff --git a/A3A/addons/core/functions/CREATE/fn_createAttackForceMixed.sqf b/A3A/addons/core/functions/CREATE/fn_createAttackForceMixed.sqf new file mode 100644 index 0000000000..49ddc07fdc --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_createAttackForceMixed.sqf @@ -0,0 +1,127 @@ +/* +Maintainer: John Jordan + Create mixed air/land attack force + +Scope: Server or HC +Environment: Scheduled (potential long sleeps, returns after last vehicle spawned) + +Arguments: + Side to create force for + Marker name of source airbase + Position or marker of target location for attack force + Resource pool to use + Total number of vehicles to create + Minimum arrival delay in seconds. -1 will force immediate spawn, otherwise will attempt to sync air/ground arrival + Array of modifier strings: ["tierboost", "specops", "airboost", "noairsupport"] + Optional: Attack type for showInterceptedSetupCall. Won't show anything if missing + Optional: Reveal value for showInterceptedSetupCall + +Return array: + Resources spent + Array of vehicle objects created + Array of crew groups created + Array of cargo groups created +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_airbase", "_target", "_resPool", "_vehCount", "_delay", "_modifiers", "_attackType", "_reveal"]; +private _targPos = if (_target isEqualType []) then { _target } else { markerPos _target }; +// _modifiers ["tierboost", "specops", "airboost", "noairsupport"] + +private _lowAir = Faction(_side) getOrDefault ["attributeLowAir", false]; +private _tier = [tierWar, tierWar+2] select ("tierboost" in _modifiers); + +private _resourcesSpent = 0; +private _vehicles = []; +private _crewGroups = []; +private _cargoGroups = []; + +private _landRatio = if ("airboost" in _modifiers) then { // punishment, HQ attack + if (_lowAir) exitWith { 0.5 + random 0.5 }; + random 0.4; +} else { // non-airboost cases + if ("noairsupport" in _modifiers) then { // waved attack case, handles air supports itself + if (_lowAir) exitWith { 0.8 + random 0.2 }; + 0.5 + random 0.4; + } else { // counterAttack + if (_lowAir) exitWith { 0.7 + random 0.3 }; + 0.4 + random 0.4; + }; +}; +ServerDebug_4("Land ratio %1 out of vehicle count %2 due to lowAir %3 and modifiers %4", _landRatio, _vehCount, _lowAir, _modifiers); +private _landCount = round (_landRatio * _vehCount); + +if (_landCount > 0) then +{ + private _landBase = [_side, _targPos] call A3A_fnc_availableBasesLand; + if (_delay >= 0 and !isNil "_landBase") then { + private _navIndex = _landBase call A3A_fnc_getMarkerNavPoint; + private _landTime = ([_targPos, _navIndex] call A3A_fnc_findNavDistance) / 15; + ServerDebug_2("Minimum delay %1 and land travel time %2", _delay, _landTime); + if (_landTime < _delay) then { sleep (_delay - _landTime) }; + _delay = _landTime; + }; + + while { !isNil "_landBase" } do + { + [_landBase, 5] call A3A_fnc_addTimeForIdle; + private _attackCount = round (_landCount * (0.25 + random 0.2)); + private _troops = ["Normal", "SpecOps"] select ("specops" in _modifiers and random 1 > 0.5); + ServerDebug_3("Attempting to spawn %1 land vehicles including %2 attack from %3", _landCount, _attackCount, _landBase); + + private _data = [_side, _landBase, _targPos, _resPool, _landCount, _attackCount, _tier, _troops] call A3A_fnc_createAttackForceLand; + if (_data#1 isEqualTo []) exitWith { Error_1("Land base %1 passed checks but failed vehicle spawning", _landBase) }; + _resourcesSpent = _resourcesSpent + _data#0; + _vehicles append _data#1; + _crewGroups append _data#2; + _cargoGroups append _data#3; + + [-(_data#0), _side, _resPool] remoteExec ["A3A_fnc_addEnemyResources", 2]; + + ServerInfo_2("Spawn performed: Ground vehicles %1 from %2", _data#1 apply {typeOf _x}, _landBase); + + // If we didn't manage to spawn enough land vehicles, try another base + _landCount = _landCount - count (_data#1); + if (_landCount <= 0) exitWith {}; + _landBase = [_side, _targPos] call A3A_fnc_availableBasesLand; + }; +}; + +// Show setup call now that we know the delay time +if (!isNil "_attackType") then { + [_reveal, _side, _attackType, _targPos, _delay] remoteExec ["A3A_fnc_showInterceptedSetupCall", 2]; +}; + +// Now we delay to synchronize with ground vehicle arrival +if (_delay > 0) then { + private _airTime = (markerPos _airbase distance2d _targPos) / 70; + ServerDebug_2("Remaining delay %1 and air travel time %2", _delay, _airTime); + sleep (0 max (_delay - _airTime)); +}; + +if (_airBase != "") then // uh, is that a thing +{ + private _airCount = _vehCount - count (_vehicles); + if (_airCount <= 0) exitWith {}; + + private _attackCount = if ("noairsupport" in _modifiers) then { 0 } else { + private _AHratio = 0.02 * (6 + tierWar) + random 0.1; + _AHratio = _AHratio + 0.2 * count (_vehicles) / _vehCount; + round (random 0.3 + _airCount * _AHratio); + }; + private _troops = ["Normal", "SpecOps"] select ("specops" in _modifiers); + ServerDebug_3("Attempting to spawn %1 air vehicles including %2 attack from %3", _airCount, _attackCount, _airbase); + + private _data = [_side, _airBase, _targPos, _resPool, _airCount, _attackCount, _tier, _troops] call A3A_fnc_createAttackForceAir; + _resourcesSpent = _resourcesSpent + _data#0; + _vehicles append _data#1; + _crewGroups append _data#2; + _cargoGroups append _data#3; + + [-(_data#0), _side, _resPool] remoteExec ["A3A_fnc_addEnemyResources", 2]; + + ServerInfo_1("Spawn performed: Air vehicles %1", _data#1 apply {typeOf _x}); +}; + +[_resourcesSpent, _vehicles, _crewGroups, _cargoGroups]; diff --git a/A3A/addons/core/functions/CREATE/fn_createAttackVehicle.sqf b/A3A/addons/core/functions/CREATE/fn_createAttackVehicle.sqf index 622fc48102..dc0998c542 100644 --- a/A3A/addons/core/functions/CREATE/fn_createAttackVehicle.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createAttackVehicle.sqf @@ -1,6 +1,3 @@ -params ["_vehicleType", "_typeOfAttack", "_landPosBlacklist", "_side", "_markerOrigin", "_posDestination"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() /* Creates a vehicle for a QRF or small attack, including crew and cargo Execution on: HC or Server @@ -9,7 +6,8 @@ FIX_LINE_NUMBERS() Parameters: _vehicleType: STRING : The name of the vehicle to spawn - _typeOfAttack: STRING : The type of the attack + _troopType: STRING : Type of cargo units to use + _resPool: STRING : Resource pool name for vehicle/troops, probably "attack" or "defence" _landPosBlacklist: ARRAY : List of blacklisted position _side: SIDE : The side of the attacker _markerOrigin: STRING : The name of the marker marking the origin @@ -20,6 +18,10 @@ FIX_LINE_NUMBERS() or OBJECT : objNull if the spawning did not worked */ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_vehicleType", "_troopType", "_resPool", "_landPosBlacklist", "_side", "_markerOrigin", "_posDestination"]; private _faction = Faction(_side); private _vehicle = [_markerOrigin, _vehicleType] call A3A_fnc_spawnVehicleAtMarker; @@ -28,49 +30,35 @@ if(isNull _vehicle) exitWith {objNull}; private _crewGroup = [_side, _vehicle] call A3A_fnc_createVehicleCrew; { - [_x] call A3A_fnc_NATOinit + [_x, nil, nil, _resPool] call A3A_fnc_NATOinit } forEach (units _crewGroup); -[_vehicle, _side] call A3A_fnc_AIVEHinit; +[_vehicle, _side, _resPool] call A3A_fnc_AIVEHinit; private _cargoGroup = grpNull; private _expectedCargo = ([_vehicleType, true] call BIS_fnc_crewCount) - ([_vehicleType, false] call BIS_fnc_crewCount); -if (_expectedCargo > 0) then +if (_expectedCargo >= 2) then { + // These types won't let the cargo group disembark, so they're a waste of units even if they have spare seats + if (_vehicleType in FactionGet(all, "vehiclesHelisAttack") + FactionGet(all, "vehiclesHelisLightAttack")) exitWith {}; + //Vehicle is able to transport units - private _groupType = if (_typeOfAttack == "Normal") then - { - [_vehicleType, _side] call A3A_fnc_cargoSeats; - } - else - { - if (_typeOfAttack == "Air") then - { - _faction get "groupAA"; - } - else - { - _faction get "groupAT"; - }; + private _groupType = call { + if (_troopType == "Normal") exitWith { [_vehicleType, _side] call A3A_fnc_cargoSeats }; + if (_troopType == "Specops") exitWith { _faction get "groupSpecOps" }; + if (_troopType == "Air") exitWith { _faction get "groupAA" }; + if (_troopType == "Tank") exitWith { _faction get "groupAT" }; }; - + + if (_expectedCargo < count _groupType) then { _groupType resize _expectedCargo }; // trim to cargo seat count _cargoGroup = [getMarkerPos _markerOrigin, _side, _groupType, true, false] call A3A_fnc_spawnGroup; // force spawn, should be pre-checked { _x assignAsCargo _vehicle; _x moveInCargo _vehicle; - if !(isNull objectParent _x) then - { - [_x] call A3A_fnc_NATOinit; - _x setVariable ["originX", _markerOrigin]; - } - else - { - deleteVehicle _x; - }; + [_x, nil, nil, _resPool] call A3A_fnc_NATOinit; } forEach units _cargoGroup; }; _landPosBlacklist = [_vehicle, _crewGroup, _cargoGroup, _posDestination, _markerOrigin, _landPosBlacklist] call A3A_fnc_createVehicleQRFBehaviour; -ServerDebug_2("Spawn Performed: Created vehicle %1 with %2 soldiers", typeof _vehicle, count crew _vehicle); +ServerDebug_5("Spawn Performed: Created vehicle %1 with %2 crew (%3) and %4 cargo (%5)", typeof _vehicle, count units _crewGroup, _crewGroup, count units _cargoGroup, _cargoGroup); -private _vehicleData = [_vehicle, _crewGroup, _cargoGroup, _landPosBlacklist]; -_vehicleData; +[_vehicle, _crewGroup, _cargoGroup, _landPosBlacklist]; diff --git a/A3A/addons/core/functions/CREATE/fn_createCIV.sqf b/A3A/addons/core/functions/CREATE/fn_createCIV.sqf index 66a06366a5..6f5997e30b 100644 --- a/A3A/addons/core/functions/CREATE/fn_createCIV.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createCIV.sqf @@ -15,6 +15,7 @@ _numCiv = _dataX select 0; _numVeh = _dataX select 1; private _roads = nearestTerrainObjects [getMarkerPos _markerX, ["MAIN ROAD", "ROAD", "TRACK"], 250, false, true]; +_roads = _roads select { !(getRoadInfo _x # 8) and (count roadsConnectedTo [_x, true] <= 2) and (count (_x nearRoads 10) < 2)}; // no bridges or junctions if (count _roads == 0) exitWith { Error_1("Roads not found for marker %1", _markerX); @@ -42,7 +43,8 @@ _area = [_markerX] call A3A_fnc_sizeMarker; _roads = _roads call BIS_fnc_arrayShuffle; private _maxRoads = count _roads; -private _numParked = _numCiv * (1/60) * civTraffic; // civTraffic is 0,1,2(default),4 +_numCiv = 15 * sqrt _numCiv * (1 - tierWar / 20); // reduce civ activity with war level +private _numParked = _numCiv * (1/60) * civTraffic; // civTraffic is 0,1,2(default),4 private _numTraffic = _numCiv * (1/300) * civTraffic; if ((daytime < 8) or (daytime > 21)) then {_numParked = _numParked * 1.5; _numTraffic = _numTraffic / 4 }; @@ -69,7 +71,8 @@ while {(spawner getVariable _spawnKey != 2) and (_countParked < _numParked)} do _dirveh = _p1 getDir _p2; }; - _pos = [_p1, 3, _dirveh + 90] call BIS_Fnc_relPos; + private _width = 3 max (getRoadInfo _road # 1 / 2 - 1); + _pos = [_p1, _width, _dirveh + 90] call BIS_Fnc_relPos; _typeVehX = selectRandomWeighted civVehiclesWeighted; /* _mrk = createmarker [format ["%1", count vehicles], _p1]; @@ -79,7 +82,8 @@ while {(spawner getVariable _spawnKey != 2) and (_countParked < _numParked)} do _mrk setMarkerColor colorTeamPlayer; //_mrk setMarkerText _nameX; */ - _veh = _typeVehX createVehicle _pos; + _veh = createVehicle [_typeVehX, _pos, [], 0, "CAN_COLLIDE"]; + _veh setVariable ["originalPos", _pos]; _veh setDir _dirveh; _veh setFuel random [0.10, 0.30, 0.50]; clearMagazineCargoGlobal _veh; @@ -87,11 +91,10 @@ while {(spawner getVariable _spawnKey != 2) and (_countParked < _numParked)} do clearItemCargoGlobal _veh; clearBackpackCargoGlobal _veh; _vehiclesX pushBack _veh; - [_veh, civilian] spawn A3A_fnc_AIVEHinit; - _veh setVariable ["originalPos", getPos _veh]; + [_veh, civilian] spawn A3A_fnc_AIVEHinit; // should cleanup if destroyed... + sleep 0.5; }; }; - sleep 0.5; _countParked = _countParked + 1; }; diff --git a/A3A/addons/core/functions/CREATE/fn_createVehicleCrew.sqf b/A3A/addons/core/functions/CREATE/fn_createVehicleCrew.sqf index 6031792555..e52ceecbb9 100644 --- a/A3A/addons/core/functions/CREATE/fn_createVehicleCrew.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createVehicleCrew.sqf @@ -28,6 +28,12 @@ if (_group isEqualType sideUnknown) then { _newGroup = true; }; +// Hack. Moving UAV AIs into gunner/turret manually does not work for some reason +if (unitIsUAV _vehicle) then { + createVehicleCrew _vehicle; + crew _vehicle joinSilent _group; +}; + if (isNil "_unitType") then { _unitType = [side _group, _vehicle] call A3A_fnc_crewTypeForVehicle; }; @@ -37,7 +43,7 @@ private _config = configFile >> "CfgVehicles" >> _type; if (getNumber (_config >> "hasDriver") > 0 && isNull driver _vehicle) then { private _driver = [_group, _unitType, getPos _vehicle, [], 10] call A3A_fnc_createUnit; _driver assignAsDriver _vehicle; - _driver moveInAny _vehicle; + _driver moveInDriver _vehicle; }; private _fnc_addCrewToTurrets = { @@ -50,6 +56,7 @@ private _fnc_addCrewToTurrets = { [_turretConfig, _turretPath] call _fnc_addCrewToTurrets; if (getNumber (_turretConfig >> "hasGunner") == 0 || getNumber (_turretConfig >> "dontCreateAI") != 0) then { continue }; + if (getNumber (_turretConfig >> "showAsCargo") > 0) then { continue }; if (isNull (_vehicle turretUnit _turretPath)) then { private _gunner = [_group, _unitType, getPos _vehicle, [], 10] call A3A_fnc_createUnit; _gunner assignAsTurret [_vehicle, _turretPath]; diff --git a/A3A/addons/core/functions/CREATE/fn_createVehicleQRFBehaviour.sqf b/A3A/addons/core/functions/CREATE/fn_createVehicleQRFBehaviour.sqf index b4c4d1f6ae..572549d162 100644 --- a/A3A/addons/core/functions/CREATE/fn_createVehicleQRFBehaviour.sqf +++ b/A3A/addons/core/functions/CREATE/fn_createVehicleQRFBehaviour.sqf @@ -1,7 +1,3 @@ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -params ["_vehicle", "_crewGroup", "_cargoGroup", "_posDestination", "_markerOrigin", "_landPosBlacklist"]; - /* Create the logic for attacking units, how different units should attack and behave Execution on: HC or Server @@ -20,184 +16,166 @@ params ["_vehicle", "_crewGroup", "_cargoGroup", "_posDestination", "_markerOrig _landPosBlacklist: ARRAY : The updated list of blocked positions */ -private _landPos = [_posDestination, getPos _vehicle, false, _landPosBlacklist] call A3A_fnc_findSafeRoadToUnload; -private _posOrigin = getMarkerPos _markerOrigin; -_posOrigin set [2, 50]; - -switch (true) do -{ - case (typeof _vehicle in FactionGet(all,"vehiclesTrucks")): - { - //Move cargo group into crew group - (units _cargoGroup) joinSilent _crewGroup; - deleteGroup _cargoGroup; - - _crewGroup spawn A3A_fnc_attackDrillAI; - - //Unassign driver from being the group leader - if (count units _crewGroup > 1) then - { - _crewGroup selectLeader (units _crewGroup select 1) - }; - - //Assign the waypoints - [getPos _vehicle, _landPos, _crewGroup] call A3A_fnc_WPCreate; - private _vehWP0 = (wayPoints _crewGroup) select 0; - _vehWP0 setWaypointBehaviour "SAFE"; - - private _vehWP1 = _crewGroup addWaypoint [_landPos, 0]; - _vehWP1 setWaypointType "GETOUT"; - - private _vehWP2 = _crewGroup addWaypoint [_posDestination, 0]; - //Ever wondered why AI have instant pinpoint accuracy? - //_vehWP2 setWaypointStatements ["true","{if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - //We could add the UPSMON routines here - _vehWP2 setWaypointType "SAD"; - _vehWP2 setWaypointBehaviour "COMBAT"; - [_vehicle, "Inf Truck."] spawn A3A_fnc_inmuneConvoy; - }; - case ((typeof _vehicle in FactionGet(all,"vehiclesTanks")) or (typeof _vehicle in FactionGet(all,"vehiclesAA"))): - { - {_x disableAI "MINEDETECTION"} forEach (units _crewGroup); +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() +params ["_vehicle", "_crewGroup", "_cargoGroup", "_posDestination", "_markerOrigin", "_landPosBlacklist"]; - //Assing the waypoints - [getPos _vehicle, _posDestination, _crewGroup] call A3A_fnc_WPCreate; - private _vehWP0 = (wayPoints _crewGroup) select 0; - _vehWP0 setWaypointBehaviour "SAFE"; - private _vehWP1 = _crewGroup addWaypoint [_posDestination, 0]; - _vehWP1 setWaypointType "SAD"; - _vehWP1 setWaypointBehaviour "COMBAT"; - //God AI - //_vehWP1 setWaypointStatements ["true","{if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - - //This keeps units from moving out of tanks if disabled, do we want that? - _vehicle allowCrewInImmobile true; - private _typeName = if (typeof _vehicle in FactionGet(all,"vehiclesTanks")) then {"Tank"} else {"AA"}; - [_vehicle, _typeName] spawn A3A_fnc_inmuneConvoy; - }; - case (_vehicle isKindOf "Helicopter" && {(typeof _vehicle) in FactionGet(all,"vehiclesTransportAir")}): +private _vehType = typeof _vehicle; +if (_vehicle isKindOf "Air") then +{ + if (_vehType in FactionGet(all,"vehiclesHelisTransport") + FactionGet(all,"vehiclesHelisLight")) exitWith { //Transport helicopter - _landPos = [_posDestination, 100, 150, 10, 0, 0.12, 0, [], [[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos; + _landPos = [_posDestination, 200, 400, 10, 0, 0.12, 0, [], [[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos; + private _posOrigin = getMarkerPos _markerOrigin; + _posOrigin set [2, 50]; { - if(_x distance2D _landPos < 20) exitWith - { - _landPos = [0, 0, 0]; - }; + if(_x distance2D _landPos < 20) exitWith { _landPos = [0, 0, 0] }; } forEach _landPosBlacklist; if !(_landPos isEqualTo [0,0,0]) then { _landPos set [2, 0]; - private _pad = createVehicle ["Land_HelipadEmpty_F", _landpos, [], 0, "NONE"]; - //Create despawn routine for heli pad - [_pad, _vehicle] spawn - { - params ["_pad", "_heli"]; - waitUntil {sleep 60; (isNull _heli) || !(alive _heli)}; - deleteVehicle _pad; - }; - _vehicle setVariable ["LandingPad", _pad, true]; - _vehicle setVariable ["PosDestination", _posDestination, true]; - _vehicle setVariable ["PosOrigin", _posOrigin, true]; - - //Create the waypoints for the crewGroup - private _vehWP0 = _crewGroup addWaypoint [_landpos, 0]; - _vehWP0 setWaypointType "MOVE"; - _vehWP0 setWaypointSpeed "FULL"; - _vehWP0 setWaypointCompletionRadius 150; - _vehWP0 setWaypointBehaviour "CARELESS"; - - if(A3A_climate isEqualTo "tropical") then - { - _vehicle flyInHeight 250; - }; - - [_vehicle, _landPos] spawn - { - params ["_vehicle", "_landPos"]; - waitUntil {sleep 1; (_vehicle distance2D _landPos) < 600}; - [_vehicle] spawn A3A_fnc_combatLanding - }; - _landPosBlacklist pushBack _landPos; + [_vehicle, _crewGroup, _cargoGroup, _posDestination, _posOrigin, _landPos] spawn A3A_fnc_combatLanding; } else { - if ((typeOf _vehicle) in vehFastRope) then - { + if ((typeOf _vehicle) in vehFastRope) then { [_vehicle, _cargoGroup, _posDestination, _posOrigin, _crewGroup] spawn A3A_fnc_fastrope; - } - else - { + } else { [_vehicle, _cargoGroup, _posDestination, _markerOrigin] spawn A3A_fnc_paradrop; }; }; }; - case (_vehicle isKindOf "Helicopter" && {!((typeof _vehicle) in FactionGet(all,"vehiclesTransportAir"))}): + if (_vehType in FactionGet(all,"vehiclesHelisAttack") + FactionGet(all,"vehiclesHelisLightAttack")) exitWith { //Attack helicopter - private _vehWP0 = _crewGroup addWaypoint [_posDestination, 0]; - _vehWP0 setWaypointBehaviour "AWARE"; - _vehWP0 setWaypointType "SAD"; + [_vehicle, _crewGroup, _posDestination] spawn A3A_fnc_attackHeli; }; - case ((typeof _vehicle) in FactionGet(all,"vehiclesTransportAir") && {!(_vehicle isKindOf "Helicopter")}): + if (_vehType in FactionGet(all,"vehiclesTransportAir")) exitWith { //Dropship with para units [_vehicle, _cargoGroup, _posDestination, _markerOrigin] spawn A3A_fnc_paradrop; }; - case (_vehicle isKindOf "Plane"): - { - //Attack plane or drone - private _vehWP0 = _crewGroup addWaypoint [_posDestination, 0]; - _vehWP0 setWaypointBehaviour "COMBAT"; - _vehWP0 setWaypointType "SAD"; - _crewGroup setCombatMode "RED"; + + Error_1("Obsolete/unidentified vehicle type %1", _vehType); + //Attack plane or drone - should be unused now? + private _vehWP0 = _crewGroup addWaypoint [_posDestination, 0]; + _vehWP0 setWaypointBehaviour "COMBAT"; + _vehWP0 setWaypointType "SAD"; + _crewGroup setCombatMode "RED"; + +} +else // ground vehicle +{ + private _typeName = call { + if (_vehType in FactionGet(all,"vehiclesTanks")) exitWith {"Tank"}; + if (_vehType in FactionGet(all,"vehiclesAA")) exitWith {"AA"}; + if (_vehType in FactionGet(all,"vehiclesArmor")) exitWith {"APC"}; + if (_vehType in FactionGet(all,"vehiclesTrucks")) exitWith {"Truck"}; + "MRAP"; }; - default + + if (isNull _cargoGroup) exitWith { - // APC or MRAP + // Vehicle has no passengers, just kill stuff {_x disableAI "MINEDETECTION"} forEach (units _crewGroup); + _vehicle allowCrewInImmobile true; + + //Adding the waypoints + [getPosATL _vehicle, _posDestination, _crewGroup] call A3A_fnc_WPCreate; + + // Turn final waypoint into SAD + private _attackWP = [_crewGroup, count waypoints _crewGroup - 1]; + _attackWP setWaypointType "SAD"; + _attackWP setWaypointBehaviour "COMBAT"; + + [_vehicle, _typeName] spawn A3A_fnc_inmuneConvoy; + }; + + if (isNull gunner _vehicle and count units _cargoGroup < 4) exitWith + { + // Vehicle has no weapons(?) and small cargo, merge crew group into cargo group + (units _crewGroup) joinSilent _cargoGroup; + deleteGroup _crewGroup; - //(units _groupX) joinSilent _crewGroup; - //deleteGroup _groupX; - //Dont unify these two groups, so the vehicle and the group can attack different targets - _crewGroup spawn A3A_fnc_attackDrillAI; + //Create the path waypoints + private _landPos = [_posDestination, getPosATL _vehicle, false, _landPosBlacklist] call A3A_fnc_findSafeRoadToUnload; + _landPosBlacklist pushBack _landPos; + [getPosATL _vehicle, _landPos, _cargoGroup] call A3A_fnc_WPCreate; + + //Turn final waypoint into disembark. Should still be behaviour SAFE... + private _dismountWP = [_cargoGroup, count waypoints _cargoGroup - 1]; + //_dismountWP setWaypointType "GETOUT"; // better to leave it as move? GETOUT is pretty busted + _dismountWP setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) leaveVehicle (assignedVehicle this); (group this) spawn A3A_fnc_attackDrillAI"]; + + private _attackWP = _cargoGroup addWaypoint [_posDestination, 0]; + _attackWP setWaypointBehaviour "AWARE"; + + [_vehicle, _typeName] spawn A3A_fnc_inmuneConvoy; + }; + + if (count units _crewGroup == 1) exitWith + { + // driver + large cargo. Unload and RTB //Set up vehicle waypoints - [getPos _vehicle, _landPos, _crewGroup] call A3A_fnc_WPCreate; - private _vehWP0 = (wayPoints _crewGroup) select 0; - _vehWP0 setWaypointBehaviour "SAFE"; - private _vehWP1 = _crewGroup addWaypoint [_landPos, 0]; - _vehWP1 setWaypointType "TR UNLOAD"; - _vehWP1 setWaypointBehaviour "AWARE"; - _vehWP1 setWaypointStatements ["true", "if !(local this) exitWith {}; [vehicle this] call A3A_fnc_smokeCoverAuto"]; - private _vehWP2 = _crewGroup addWaypoint [_posDestination, 0]; - _vehWP2 setWaypointType "SAD"; - _vehWP2 setWaypointBehaviour "COMBAT"; - //God AI - //_vehWP2 setWaypointStatements ["true","{if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; + private _landPos = [_posDestination, getPosATL _vehicle, false, _landPosBlacklist] call A3A_fnc_findSafeRoadToUnload; + _landPosBlacklist pushBack _landPos; + [getPosATL _vehicle, _landPos, _crewGroup] call A3A_fnc_WPCreate; + + //Turn final waypoint into disembark. Should still be behaviour SAFE... + private _vehWP0 = [_crewGroup, count waypoints _crewGroup - 1]; + _vehWP0 setWaypointType "TR UNLOAD"; + _vehWP0 setWaypointBehaviour "AWARE"; + _vehWP0 setWaypointStatements ["true", "if !(local this) exitWith {}; [group this] spawn A3A_fnc_enemyReturnToBase"]; //Set the waypoints for cargoGroup private _cargoWP0 = _cargoGroup addWaypoint [_landpos, 0]; _cargoWP0 setWaypointType "GETOUT"; - _cargoWP0 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; + _cargoWP0 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) leaveVehicle (assignedVehicle this); (group this) spawn A3A_fnc_attackDrillAI"]; private _cargoWP1 = _cargoGroup addWaypoint [_posDestination, 0]; - _cargoWP1 setWaypointType "SAD"; - _cargoWP1 setWaypointBehaviour "COMBAT"; - _cargoWP1 setWaypointSpeed "FULL"; + _cargoWP1 setWaypointBehaviour "AWARE"; + //Link the dismount waypoints + _vehWP0 synchronizeWaypoint [_cargoWP0]; - //Link the waypoints - _vehWP1 synchronizeWaypoint [_cargoWP0]; + [_vehicle, _typeName] spawn A3A_fnc_inmuneConvoy; + }; + + if (true) exitWith + { + // weapons + separate cargo units + {_x disableAI "MINEDETECTION"} forEach (units _crewGroup); + if (_vehType in FactionGet(all,"vehiclesArmor")) then { _vehicle allowCrewInImmobile true }; + + //Set up vehicle waypoints + private _landPos = [_posDestination, getPosATL _vehicle, false, _landPosBlacklist] call A3A_fnc_findSafeRoadToUnload; + _landPosBlacklist pushBack _landPos; + [getPosATL _vehicle, _landPos, _crewGroup] call A3A_fnc_WPCreate; + + //Turn final waypoint into disembark. Should still be behaviour SAFE... + private _vehWP0 = [_crewGroup, count waypoints _crewGroup - 1]; + _vehWP0 setWaypointType "TR UNLOAD"; + _vehWP0 setWaypointBehaviour "AWARE"; + _vehWP0 setWaypointStatements ["true", "if !(local this) exitWith {}; [vehicle this] call A3A_fnc_smokeCoverAuto"]; + private _vehWP1 = _crewGroup addWaypoint [_posDestination, 0]; + _vehWP1 setWaypointType "SAD"; + _vehWP1 setWaypointBehaviour "COMBAT"; + + //Set the waypoints for cargoGroup + private _cargoWP0 = _cargoGroup addWaypoint [_landpos, 0]; + _cargoWP0 setWaypointType "GETOUT"; + _cargoWP0 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) leaveVehicle (assignedVehicle this); (group this) spawn A3A_fnc_attackDrillAI"]; + private _cargoWP1 = _cargoGroup addWaypoint [_posDestination, 0]; + _cargoWP1 setWaypointBehaviour "AWARE"; + //Link the dismount waypoints + _vehWP0 synchronizeWaypoint [_cargoWP0]; - //This keeps units from moving out of APC if disabled, do we want that? - _vehicle allowCrewInImmobile true; - private _typeName = if (typeof _vehicle in FactionGet(all,"vehiclesAPCs")) then {"APC"} else {"MRAP"}; [_vehicle, _typeName] spawn A3A_fnc_inmuneConvoy; }; }; -_landPosBlacklist pushBack _landPos; _landPosBlacklist; diff --git a/A3A/addons/core/functions/CREATE/fn_groupDespawner.sqf b/A3A/addons/core/functions/CREATE/fn_groupDespawner.sqf index 6ece70fb4c..02a3a086c3 100644 --- a/A3A/addons/core/functions/CREATE/fn_groupDespawner.sqf +++ b/A3A/addons/core/functions/CREATE/fn_groupDespawner.sqf @@ -1,11 +1,13 @@ -_filename = "fn_groupDespawner"; params ["_group", ["_checkNonRebel", false]]; +if (!isNil { _group getVariable "A3A_despawnerHandle" }) exitWith {}; +_group setVariable ["A3A_despawnerHandle", _thisScript]; // only meaningful locally + if (count units _group == 0) exitWith { deleteGroup _group }; // Strip spawner status. If the group is waiting to despawn then it's no longer active { - if (_x getVariable ["spawner", false]) then { _x setVariable ["spawner", false, true] }; + if (_x getVariable ["spawner", false]) then { _x setVariable ["spawner", nil, true] }; } forEach units _group; private _eny1 = Occupants; diff --git a/A3A/addons/core/functions/CREATE/fn_invaderPunish.sqf b/A3A/addons/core/functions/CREATE/fn_invaderPunish.sqf index 5dc3aec998..18b0754d38 100644 --- a/A3A/addons/core/functions/CREATE/fn_invaderPunish.sqf +++ b/A3A/addons/core/functions/CREATE/fn_invaderPunish.sqf @@ -1,125 +1,72 @@ +/* +Maintainer: John Jordan + Create invader city punishment attack + +Scope: Server, although written to work on HCs +Environment: Scheduled, should be spawned + +Arguments: + Destination marker (should be town) + Origin marker (should be airbase) + Optional, delay in seconds before sending vehicles (Default: Auto-calculated) +*/ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() + if (!isServer) exitWith { Error("Server-only function miscalled") }; -params ["_attackDestination", "_attackOrigin"]; -Info_2("Launching CSAT Punish Against %1 from %2", _attackDestination, _attackOrigin); +params ["_mrkDest", "_mrkOrigin", "_delay"]; + +ServerInfo_2("Launching CSAT Punishment Against %1 from %2", _mrkDest, _mrkOrigin); bigAttackInProgress = true; publicVariable "bigAttackInProgress"; -private _posDestination = getMarkerPos _attackDestination; -private _posOrigin = getMarkerPos _attackOrigin; -private _attackDir = _posOrigin getDir _posDestination; -private _size = [_attackDestination] call A3A_fnc_sizeMarker; -private _groups = []; -private _soldiers = []; -private _pilots = []; -private _vehiclesX = []; -private _civilians = []; -private _civGroups = []; -private _landingPads = []; +private _posDest = getMarkerPos _mrkDest; +private _posOrigin = getMarkerPos _mrkOrigin; +private _size = [_mrkDest] call A3A_fnc_sizeMarker; -private _nameDestination = [_attackDestination] call A3A_fnc_localizar; +private _nameDest = [_mrkDest] call A3A_fnc_localizar; private _taskId = "invaderPunish" + str A3A_taskCount; -[[teamPlayer,civilian,Occupants],_taskId,[format ["%2 is attacking critical positions within %1! Defend the city at all costs",_nameDestination,FactionGet(inv,"name")],format ["%1 Punishment",FactionGet(inv,"name")],_attackDestination],getMarkerPos _attackDestination,false,0,true,"Defend",true] call BIS_fnc_taskCreate; +[[teamPlayer,civilian,Occupants],_taskId,[format ["%2 is attacking critical positions within %1! Defend the city at all costs",_nameDest,FactionGet(inv,"name")],format ["%1 Punishment",FactionGet(inv,"name")],_mrkDest],_posDest,false,0,true,"Defend",true] call BIS_fnc_taskCreate; [_taskId, "invaderPunish", "CREATED"] remoteExecCall ["A3A_fnc_taskUpdate", 2]; -// give smaller player groups a bit more time to respond -private _playerScale = call A3A_fnc_getPlayerScale; -[_attackOrigin, (5 / _playerScale) + 10] call A3A_fnc_addTimeForIdle; // Reserve airbase for this attack -sleep (60*5 / _playerScale); -private _reveal = [_posDestination, Invaders] call A3A_fnc_calculateSupportCallReveal; -[_posDestination, 4, ["MORTAR"], Invaders, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; -private _missionExpireTime = time + 3600; -private _missionMinTime = time + 600; - -private _invaderAirTransport = (FactionGet(inv, "vehiclesHelisLight") + FactionGet(inv, "vehiclesHelisTransport") + FactionGet(inv, "vehiclesPlanesTransport")) select {[_x] call A3A_fnc_vehAvailable}; -private _invaderAttackHelis = FactionGet(inv, "vehiclesHelisAttack") select {[_x] call A3A_fnc_vehAvailable}; +// Give smaller player groups a bit more time to respond +if (isNil "_delay") then { _delay = 420 / A3A_balancePlayerScale }; +// Create the attacking force // probably doesn't make much sense to aggro-scale this one as it's not a response -private _numVehicles = round (2 + random 1 + _playerScale); -private _numAttackHelis = if (count _invaderAttackHelis != 0) then { round (_numVehicles / 3) } else { 0 }; +private _vehCount = round (2 + random 1 + A3A_balancePlayerScale); + +//params ["_side", "_airbase", "_target", "_resPool", "_vehCount", "_delay", "_modifiers", "_attackType", "_reveal"]; +private _data = [Invaders, _mrkOrigin, _mrkDest, "attack", _vehCount, _delay, ["airboost", "specops"]] call A3A_fnc_createAttackForceMixed; +_data params ["_resources", "_vehicles", "_crewGroups", "_cargoGroups"]; + +// May as well do it properly here +A3A_supportStrikes pushBack [Invaders, "TROOPS", markerPos _mrkDest, time + 1800, 1800, _resources]; -for "_i" from 1 to _numVehicles do -{ - if (_i > 3 and { [Invaders] call A3A_fnc_remUnitCount < 8 }) exitWith {}; - private _typeAirVehicle = if (_i <= _numAttackHelis) then {selectRandom _invaderAttackHelis} else {selectRandom _invaderAirTransport}; - private _spawnResult = [_posOrigin, _attackDir, _typeAirVehicle, Invaders] call A3A_fnc_spawnVehicle; - private _veh = _spawnResult select 0; - private _vehCrew = _spawnResult select 1; - {[_x] call A3A_fnc_NATOinit} forEach _vehCrew; - [_veh, Invaders] call A3A_fnc_AIVEHinit; - private _crewGroup = _spawnResult select 2; - _pilots append _vehCrew; - _groups pushBack _crewGroup; - _vehiclesX pushBack _veh; - - //If we're an attack vehicle. - if (_typeAirVehicle in _invaderAttackHelis) then { - _wp1 = _crewGroup addWaypoint [_posDestination, 0]; - _wp1 setWaypointType "SAD"; - //[_veh,"Air Attack"] spawn A3A_fnc_inmuneConvoy; - } else { - {_x setBehaviour "CARELESS";} forEach units _crewGroup; - _typeGroup = [_typeAirVehicle,Invaders] call A3A_fnc_cargoSeats; - _groupX = [_posOrigin, Invaders, _typeGroup, true, false] call A3A_fnc_spawnGroup; // forced spawn - {_x assignAsCargo _veh;_x moveInCargo _veh; _soldiers pushBack _x; [_x] call A3A_fnc_NATOinit; _x setVariable ["originX",_attackOrigin]} forEach units _groupX; - _groups pushBack _groupX; - //[_veh,"CSAT Air Transport"] spawn A3A_fnc_inmuneConvoy; - - if (_typeAirVehicle isKindOf "Plane") exitWith { - [_veh,_groupX,_attackDestination,_attackOrigin] spawn A3A_fnc_paradrop; - }; - - private _landPos = _posDestination getPos [random (_size/2) + _size/2, random 360]; - _landPos = [_landPos, 0, _size/4, 10, 0, 0.20, 0,[],[[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos; - - if (_landPos isEqualTo [0,0,0]) exitWith { - {_x disableAI "TARGET"; _x disableAI "AUTOTARGET"} foreach units _crewGroup; - [_veh,_groupX,_posDestination,_posOrigin,_crewGroup] spawn A3A_fnc_fastrope; - }; - - _landPos set [2, 0]; - private _pad = createVehicle ["Land_HelipadEmpty_F", _landPos, [], 0, "NONE"]; - _landingPads pushBack _pad; - - // Combat landing setup - _veh setVariable ["LandingPad", _pad, true]; - _veh setVariable ["PosDestination", _posDestination, true]; - _veh setVariable ["PosOrigin", _posOrigin, true]; - - //Create the waypoints for the crewGroup - private _vehWP0 = _crewGroup addWaypoint [_landPos, 0]; - _vehWP0 setWaypointType "MOVE"; - _vehWP0 setWaypointSpeed "FULL"; - _vehWP0 setWaypointCompletionRadius 150; - _vehWP0 setWaypointBehaviour "CARELESS"; - - // Hack for tree-dodging on landing path - if(A3A_climate isEqualTo "tropical") then { _veh flyInHeight 250 }; - - [_veh, _landPos] spawn - { - params ["_vehicle", "_landPos"]; - waitUntil {sleep 1; (_vehicle distance2D _landPos) < 600}; - [_vehicle] spawn A3A_fnc_combatLanding; - }; - }; - sleep 20; -}; -private _numCiv = (server getVariable _attackDestination) select 0; +// Call up some artillery +private _artyTargPos = _posDest getPos [_size/3, random 360]; +// ["_side", "_target", "_resPool", "_precision", "_reveal", "_delay"]; +[Invaders, _artyTargPos, "attack", 0, 0, 0] call A3A_fnc_requestArtillery; + + +// Spawn in the "civilians" (rebel defenders) +private _numCiv = (server getVariable _mrkDest) select 0; _numCiv = 4 + round sqrt (_numCiv); if (_numCiv > 30) then {_numCiv = 30}; +private _civilians = []; +private _civGroups = []; +private _civWeapons = unlockedsniperrifles + unlockedmachineguns + unlockedshotguns + unlockedrifles + unlockedsmgs + unlockedhandguns; while {count _civilians < _numCiv} do { private _groupCivil = createGroup teamPlayer; _civGroups pushBack _groupCivil; private _pos = while {true} do { - private _pos = _posDestination getPos [random _size / 2,random 360]; + private _pos = _posDest getPos [random _size / 2,random 360]; if (!surfaceIsWater _pos) exitWith { _pos }; }; for "_i" from 1 to (4 min (_numCiv - count _civilians)) do @@ -128,26 +75,23 @@ while {count _civilians < _numCiv} do [_civ, selectRandom (A3A_faction_civ get "faces"), "NoVoice"] call BIS_fnc_setIdentity; _civ forceAddUniform selectRandom (A3A_faction_civ get "uniforms"); _civ addHeadgear selectRandom (A3A_faction_civ get "headgear"); - [_civ, selectRandom (unlockedsniperrifles + unlockedmachineguns + unlockedshotguns + unlockedrifles + unlockedsmgs + unlockedhandguns), 5, 0] call BIS_fnc_addWeapon; + [_civ, selectRandom _civWeapons, 5, 0] call BIS_fnc_addWeapon; _civ setSkill 0.5; _civilians pushBack _civ; }; - [leader _groupCivil, _attackDestination, "AWARE","SPAWNED","NOVEH2"] execVM QPATHTOFOLDER(scripts\UPSMON.sqf);//TODO need delete UPSMON link + [leader _groupCivil, _mrkDest, "AWARE","SPAWNED","NOVEH2"] execVM QPATHTOFOLDER(scripts\UPSMON.sqf);//TODO need delete UPSMON link }; -if (tierWar >= 5) then { - for "_i" from 0 to round random 1 do { - if (FactionGet(inv,"vehiclesPlanesCAS") findIf { [_x] call A3A_fnc_vehAvailable } > -1) then { - private _reveal = [_posDestination, Invaders] call A3A_fnc_calculateSupportCallReveal; - [_posDestination, 4, ["AIRSTRIKE"], Invaders, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - sleep 30; - }; - }; -}; +// Termination conditions +private _missionExpireTime = time + 3600; +private _missionMinTime = time + 600; +private _soldiers = []; +{ _soldiers append units _x } forEach _cargoGroups; waitUntil { sleep 10; +// Debug_4("Soldiers %1 initial, %2 active. Civs %3 initial, %4 active", count _soldiers, {_x call A3A_fnc_canFight} count _soldiers, count _civilians, {alive _x} count _civilians); ({_x call A3A_fnc_canFight} count _soldiers < count _soldiers / 3) or (time > _missionMinTime and ({alive _x} count _civilians < count _civilians / 4)) or (time > _missionExpireTime) @@ -164,52 +108,48 @@ private _fnc_adjustNearCities = { }; if (({_x call A3A_fnc_canFight} count _soldiers < count _soldiers / 3) or (time > _missionExpireTime)) then { - Info_1("Rebels defeated a punishment attack against %1", _attackDestination); + Info_1("Rebels defeated a punishment attack against %1", _mrkDest); [_taskId, "invaderPunish", "SUCCEEDED"] call A3A_fnc_taskSetState; - [_posDestination, 30, 3000] call _fnc_adjustNearCities; + [_posDest, 30, 3000] call _fnc_adjustNearCities; [Occupants, -10, 90] remoteExec ["A3A_fnc_addAggression",2]; - {if (isPlayer _x) then {[10,_x] call A3A_fnc_playerScoreAdd}} forEach ([500,0,_posDestination,teamPlayer] call A3A_fnc_distanceUnits); + {if (isPlayer _x) then {[10,_x] call A3A_fnc_playerScoreAdd}} forEach ([500,0,_posDest,teamPlayer] call A3A_fnc_distanceUnits); [10,theBoss] call A3A_fnc_playerScoreAdd; } else { - Info_1("Rebels lost a punishment attack against %1", _attackDestination); + Info_1("Rebels lost a punishment attack against %1", _mrkDest); [_taskId, "invaderPunish", "FAILED"] call A3A_fnc_taskSetState; - [_posDestination, -30, 3000] call _fnc_adjustNearCities; + [_posDest, -30, 3000] call _fnc_adjustNearCities; - destroyedSites = destroyedSites + [_attackDestination]; + // Invaders pay extra to destroy a city + private _citypop = (server getVariable _mrkDest) select 0; + [-4 * _citypop, Invaders, "attack"] remoteExec ["A3A_fnc_addEnemyResources", 2]; + + destroyedSites = destroyedSites + [_mrkDest]; publicVariable "destroyedSites"; private _mineTypes = A3A_faction_inv get "minefieldAPERS"; for "_i" from 1 to 60 do { - private _mineX = createMine [selectRandom _mineTypes,_posDestination,[],_size]; + private _mineX = createMine [selectRandom _mineTypes,_posDest,[],_size]; Invaders revealMine _mineX; }; - [_attackDestination] call A3A_fnc_destroyCity; + [_mrkDest] call A3A_fnc_destroyCity; // Putting this stuff here is a bit gross, but currently there's no cityFlip function. Usually done by resourceCheck. - sidesX setVariable [_attackDestination, Invaders, true]; - garrison setVariable [_attackDestination, [], true]; - [_attackDestination] call A3A_fnc_mrkUpdate; + sidesX setVariable [_mrkDest, Invaders, true]; + garrison setVariable [_mrkDest, [], true]; + [_mrkDest] call A3A_fnc_mrkUpdate; }; sleep 15; [_taskId, "invaderPunish", 0] spawn A3A_fnc_taskDelete; -[3600, Invaders] remoteExec ["A3A_fnc_timingCA", 2]; bigAttackInProgress = false; publicVariable "bigAttackInProgress"; // Order remaining aggressor units back to base, hand them to the group despawner -{ - private _wp = _x addWaypoint [_posOrigin, 50]; - _wp setWaypointType "MOVE"; - _x setCurrentWaypoint _wp; - [_x] spawn A3A_fnc_groupDespawner; -} forEach _groups; - -{ [_x] spawn A3A_fnc_VEHdespawner } forEach _vehiclesX; -{ deleteVehicle _x } forEach _landingPads; +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _vehicles; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach _crewGroups + _cargoGroups; // When the city marker is despawned, get rid of the civilians -waitUntil {sleep 5; (spawner getVariable _attackDestination == 2)}; +waitUntil {sleep 5; (spawner getVariable _mrkDest == 2)}; {deleteVehicle _x} forEach _civilians; {deleteGroup _x} forEach _civGroups; diff --git a/A3A/addons/core/functions/CREATE/fn_patrolReinf.sqf b/A3A/addons/core/functions/CREATE/fn_patrolReinf.sqf index e6206f75db..1f40b3efe0 100644 --- a/A3A/addons/core/functions/CREATE/fn_patrolReinf.sqf +++ b/A3A/addons/core/functions/CREATE/fn_patrolReinf.sqf @@ -1,203 +1,147 @@ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private ["_mrkDestination","_mrkOrigin","_numberX","_sideX","_typeGroup","_typeVehX","_indexX","_spawnPoint","_pos","_timeOut","_veh","_groupX","_landPos","_Vwp0","_posOrigin","_land","_pos1","_pos2"]; - -_mrkDestination = _this select 0; -_mrkOrigin = _this select 1; -_numberX = _this select 2; -_sideX = _this select 3; -private _faction = Faction(_sideX); -ServerInfo_4("Spawning PatrolReinf. Dest:%1, Orig:%2, Size:%3, Side: %4",_mrkDestination,_mrkOrigin,_numberX,_sideX); -_posDestination = getMarkerPos _mrkDestination; -_posOrigin = getMarkerPos _mrkOrigin; - -if ([_sideX] call A3A_fnc_remUnitCount < _numberX) exitWith { - Info("Cancelling because maxUnits exceeded"); + +params ["_mrkDest", "_mrkOrigin", "_numTroops", "_side"]; +private _faction = Faction(_side); +private _lowAir = _faction getOrDefault ["attributeLowAir", false]; +private _posDest = getMarkerPos _mrkDest; +private _posOrigin = getMarkerPos _mrkOrigin; +private _groupType = selectRandom (_faction get (if (_numTroops == 4) then {"groupsMedium"} else {"groupsSquads"})); + +private _isLand = if (_lowAir) then { true } else { // land markers guaranteed by reinforcementsAI for low air + private _targNavIndex = _mrkDest call A3A_fnc_getMarkerNavPoint; + private _suppMarkers = [_targNavIndex, _lowAir] call A3A_fnc_findLandSupportMarkers apply { _x#0 }; + _mrkOrigin in _suppMarkers; }; -_land = if (_posOrigin distance _posDestination > distanceForLandAttack) then {false} else {true}; -_typeGroup = selectRandom (_faction get (if (_numberX == 4) then {"groupsMedium"} else {"groupsSquads"})); -_typeVehX = ""; -if (_land) then -{ - _typeVehX = selectRandom (_faction get "vehiclesTrucks"); -} -else -{ - _vehPool = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport") + (_faction get "vehiclesPlanesTransport"); - _vehPool = _vehPool arrayIntersect _vehPool; //ensure unique classnames - _vehPool = _vehPool select { [_x] call A3A_fnc_vehAvailable }; - if ((_numberX > 4) and (count _vehPool > 1) and !A3A_hasIFA) then {_vehPool = _vehPool - (_faction get "vehiclesHelisLight")}; - //_vehPool = _vehPool select {(_x isKindOf "Helicopter") and (_x in vehFastRope)}; - _typeVehX = selectRandom _vehPool; +ServerInfo_5("Spawning PatrolReinf. Dest:%1 Orig:%2 Size:%3 Side:%4 Land:%5",_mrkDest,_mrkOrigin,_numTroops,_side,_isLand); + +private _vehicleType = if (_isLand) then { + selectRandom (_faction get "vehiclesTrucks"); +} else { + private _transportPlanes = _faction get "vehiclesPlanesTransport"; + private _transportHelis = _faction get "vehiclesHelisTransport"; + if (count _groupType <= 4) then { _transportHelis append (_faction get "vehiclesHelisLight") }; + + private _transportsWeighted = []; + { _transportsWeighted append [_x, 1 / count _transportPlanes] } forEach _transportPlanes; + { _transportsWeighted append [_x, 2 / count _transportHelis] } forEach _transportHelis; + selectRandomWeighted _transportsWeighted; }; -_pos = []; -_veh = objNull; -_groupX = grpNull; -private _groupVeh = grpNull; -private _landpad = objNull; +private _vehicle = [_mrkOrigin, _vehicleType] call A3A_fnc_spawnVehicleAtMarker; +if (isNull _vehicle) exitWith { + Error_2("Failed to spawn vehicle type %1 at %2", _vehicleType, _mrkOrigin); +}; +private _crewGroup = [_side, _vehicle] call A3A_fnc_createVehicleCrew; +{ [_x, nil, false, "legacy"] call A3A_fnc_NATOinit } forEach (units _crewGroup); +[_vehicle, _side, "legacy"] call A3A_fnc_AIVEHinit; // don't pay up-front for reinf vehicles/crew, assumed to return -if (_land) then +private _expectedCargo = ([_vehicleType, true] call BIS_fnc_crewCount) - ([_vehicleType, false] call BIS_fnc_crewCount); +if (_expectedCargo < count _groupType) then { _groupType resize _expectedCargo }; // trim to cargo seat count +private _cargoGroup = [_posOrigin, _side, _groupType, true, false] call A3A_fnc_spawnGroup; // force spawn, should be pre-checked { - _indexX = airportsX find _mrkOrigin; - _spawnPoint = server getVariable (format ["spawn_%1", _mrkOrigin]); - _pos = getMarkerPos _spawnPoint; - _timeOut = 0; - _pos = _pos findEmptyPosition [0,100,_typeVehX]; - while {_timeOut < 60} do - { - if (count _pos > 0) exitWith {}; - _timeOut = _timeOut + 1; - _pos = _pos findEmptyPosition [0,100,_typeVehX]; - sleep 1; - }; - if (count _pos == 0) then {_pos = getMarkerPos _spawnPoint}; - _veh = _typeVehX createVehicle _pos; - _veh setDir (markerDir _spawnPoint); - _groupX = [_pos,_sideX, _typeGroup,true,false] call A3A_fnc_spawnGroup; - _groupX addVehicle _veh; - { - if (_x == leader _x) then {_x assignAsDriver _veh;_x moveInDriver _veh} else {_x assignAsCargo _veh;_x moveInCargo _veh}; - - if (vehicle _x == _x) then - { - deleteVehicle _x; - } - else - { - [_x] call A3A_fnc_NATOinit; - }; - } forEach units _groupX; - [_veh, _sideX] call A3A_fnc_AIVEHinit; - [_veh,"Inf Truck."] spawn A3A_fnc_inmuneConvoy; -// _groupX spawn A3A_fnc_attackDrillAI; - [_mrkOrigin,_posDestination,_groupX] call A3A_fnc_WPCreate; - _Vwp0 = _groupX addWaypoint [_posDestination, 50]; - _Vwp0 setWaypointCompletionRadius 50; - _Vwp0 setWaypointType "GETOUT"; - _Vwp1 = _groupX addWaypoint [_posDestination, 5]; - _Vwp1 setWaypointType "MOVE"; - } + _x assignAsCargo _vehicle; // unnecessary, done by moveInXXX anyway? + if (_vehicleType == "uns_an2_transport") then { _x moveInAny _vehicle} else { _x moveInCargo _vehicle }; // moveInCargo busted for unsung an2? + [_x, nil, false, "defence"] call A3A_fnc_NATOinit; +} forEach units _cargoGroup; + +[-10*count units _cargoGroup, _side, "defence"] remoteExec ["A3A_fnc_addEnemyResources", 2]; + +private _landPad = objNull; +if (_isLand) then { + private _landPos = [_posDest, getPosATL _vehicle, true, []] call A3A_fnc_findSafeRoadToUnload; // should actually be safe... + Debug_1("Landpos veh = %1", _landPos); + [getPosATL _vehicle, _landPos, _crewGroup] call A3A_fnc_WPCreate; + + //Turn final waypoint into disembark. Should still be behaviour SAFE... + private _dismountWP = [_crewGroup, count waypoints _crewGroup - 1]; + _dismountWP setWaypointType "TR UNLOAD"; + private _returnWP = _crewGroup addWaypoint [_posOrigin, 50]; + _returnWP setWaypointType "MOVE"; + + private _reinfWP = _cargoGroup addWaypoint [_posDest, 0]; + _reinfWP setWaypointBehaviour "AWARE"; +} else { - _pos = _posOrigin; - _ang = 0; - _size = [_mrkOrigin] call A3A_fnc_sizeMarker; - _buildings = nearestObjects [_posOrigin, ["Land_LandMark_F","Land_runway_edgelight"], _size / 2]; - if (count _buildings > 1) then - { - _pos1 = getPos (_buildings select 0); - _pos2 = getPos (_buildings select 1); - _ang = [_pos1, _pos2] call BIS_fnc_DirTo; - _pos = [_pos1, 5,_ang] call BIS_fnc_relPos; - }; - if (count _pos == 0) then {_pos = _posOrigin}; - - _vehicle=[_pos, _ang + 90,_typeVehX, _sideX] call A3A_fnc_spawnVehicle; - _veh = _vehicle select 0; - _vehCrew = _vehicle select 1; - _groupVeh = _vehicle select 2; - { [_x] call A3A_fnc_NATOinit } forEach units _groupVeh; - [_veh, _sideX] call A3A_fnc_AIVEHinit; - - _groupX = [_posOrigin,_sideX,_typeGroup,true,false] call A3A_fnc_spawnGroup; - { - _x assignAsCargo _veh; - _x moveInCargo _veh; - if (vehicle _x == _x) then - { - deleteVehicle _x; - } - else - { - [_x] call A3A_fnc_NATOinit; - }; - } forEach units _groupX; - _landPos = if (_typeVehX isKindOf "Helicopter") then {[_posDestination, 0, 300, 10, 0, 0.20, 0,[],[[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos} else {[0,0,0]}; + _landPos = if (_vehicleType isKindOf "Helicopter") then {[_posDest, 0, 300, 10, 0, 0.20, 0,[],[[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos} else {[0,0,0]}; + Debug_1("Landpos air = %1", _landPos); if !(_landPos isEqualTo [0,0,0]) then { _landPos set [2, 0]; _landpad = createVehicle ["Land_HelipadEmpty_F", _landpos, [], 0, "NONE"]; - _wp0 = _groupVeh addWaypoint [_landpos, 0]; - _wp0 setWaypointType "TR UNLOAD"; - _wp0 setWaypointStatements ["true", "if !(local this) exitWith {}; (vehicle this) land 'GET OUT'"]; - _wp0 setWaypointBehaviour "CARELESS"; - _wp3 = _groupX addWaypoint [_landpos, 0]; - _wp3 setWaypointType "GETOUT"; -// _wp3 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; - _wp0 synchronizeWaypoint [_wp3]; - _wp4 = _groupX addWaypoint [_posDestination, 5]; - _wp4 setWaypointType "MOVE"; - _wp2 = _groupVeh addWaypoint [_posOrigin, 1]; - _wp2 setWaypointType "MOVE"; - _wp2 setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; - [_groupVeh,1] setWaypointBehaviour "AWARE"; + _landWP = _crewGroup addWaypoint [_landpos, 0]; + _landWP setWaypointType "TR UNLOAD"; + _landWP setWaypointStatements ["true", "if !(local this) exitWith {}; (vehicle this) land 'GET OUT'"]; + _landWP setWaypointBehaviour "CARELESS"; + _returnWP = _crewGroup addWaypoint [_posOrigin, 50]; + _returnWP setWaypointStatements ["true", "if (!local this or !alive this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; + + _getoutWP = _cargoGroup addWaypoint [_landpos, 0]; + _getoutWP setWaypointType "GETOUT"; + _reinfWP = _cargoGroup addWaypoint [_posDest, 0]; + _reinfWP setWaypointBehaviour "AWARE"; + _landWP synchronizeWaypoint [_getoutWP]; } else { - if (_typeVehX in vehFastRope) then + if (_vehicleType in vehFastRope) then { - [_veh,_groupX,_posDestination,_posOrigin,_groupVeh,true] spawn A3A_fnc_fastrope; + [_vehicle, _cargoGroup, _posDest, _posOrigin, _crewGroup, true] spawn A3A_fnc_fastrope; } else { - [_veh,_groupX,_posDestination,_mrkOrigin,true] spawn A3A_fnc_paradrop; + [_vehicle, _cargoGroup, _posDest, _mrkOrigin, true] spawn A3A_fnc_paradrop; }; }; }; -ServerInfo_2("Spawn performed: Vehicle type %1 with %2 troops", _typeVehX, count units _groupX); +ServerInfo_2("Spawn performed: Vehicle type %1 with %2 troops", _vehicleType, count units _cargoGroup); // Allow the convoy a generous time to arrive -private _dist = _posOrigin distance _posDestination; -private _timeout = time + (if (_land) then { _dist / 3 + 300 } else { _dist / 15 + 600 }); +private _timeout = if (_isLand) then { + time + ([_mrkDest, _mrkOrigin] call A3A_fnc_findNavDistance) / 6 + 300; +} else { + time + (_posOrigin distance2d _posDest) / 30 + 600; +}; // termination conditions: // - everyone dead or timeout exceeded -// - group leader out of vehicle and within 50m of target +// - group leader out of vehicle and within 200m of target waituntil { sleep 10; - private _leader = leader _groupX; - { alive _x } count (units _groupX) == 0 || time > _timeout - || { _leader == vehicle _leader && { _leader distance _posDestination < 50 } } + private _leader = leader _cargoGroup; + { alive _x } count (units _cargoGroup) == 0 || time > _timeout + || { _leader == vehicle _leader && { _leader distance _posDest < 200 } } }; // Clean up this stuff regardless of success if !(isNull _landpad) then { deleteVehicle _landpad }; -[_veh] spawn A3A_fnc_VEHdespawner; -[_groupVeh] spawn A3A_fnc_groupDespawner; +[_vehicle] spawn A3A_fnc_VEHdespawner; +[_crewGroup] spawn A3A_fnc_enemyReturnToBase; -private _units = (units _groupX) select { alive _x }; -if (count _units == 0 || time > _timeout || _sideX != (sidesX getVariable _mrkDestination)) exitWith +private _units = (units _cargoGroup) select { alive _x }; +if (count _units == 0 || time > _timeout || _side != (sidesX getVariable _mrkDest)) exitWith { - // Failure case, RTB and add to killzones + Debug_2("patrolReinf failure: time %1, units %2", _timeout - time, count _units); - private _wp = _groupX addWaypoint [_posOrigin, 50]; - _wp setWaypointType "MOVE"; - _groupX setCurrentWaypoint _wp; - [_groupX] spawn A3A_fnc_groupDespawner; + // Failure case, RTB and add to killzones + [_cargoGroup] spawn A3A_fnc_enemyReturnToBase; - if (_sideX == (sidesX getVariable _mrkOrigin)) then { + // TODO: Only care about actual pathfinding (timeout) for killzones maybe? + if (_isLand and _side == (sidesX getVariable _mrkOrigin)) then { private _killzones = killZones getVariable [_mrkOrigin,[]]; - _killzones pushBack _mrkDestination; + _killzones pushBack _mrkDest; killZones setVariable [_mrkOrigin,_killzones,true]; }; - ServerInfo_2("Reinf on %1 failed, returning with %2 units", _mrkDestination, count units _groupX); + ServerInfo_2("Reinf on %1 failed, returning with %2 units", _mrkDest, count units _cargoGroup); }; -ServerInfo_2("Reinf on %1 successful, adding %2 units", _mrkDestination, count units _groupX); - -// Arrived successfully, add units to garrison and despawn with it -[_units, _sideX, _mrkDestination, 0] remoteExec ["A3A_fnc_garrisonUpdate", 2]; -{ - _x setVariable ["markerX", _mrkDestination, true]; - _x setVariable ["spawner", nil, true]; -} forEach _units; +ServerInfo_2("Reinf on %1 successful, adding %2 units", _mrkDest, count units _cargoGroup); -waitUntil {sleep 5; (spawner getVariable _mrkDestination == 2)}; -{ deleteVehicle _x } forEach _units; +[_cargoGroup, _mrkDest] call A3A_fnc_enemyGarrison; diff --git a/A3A/addons/core/functions/CREATE/fn_reinforcementsAI.sqf b/A3A/addons/core/functions/CREATE/fn_reinforcementsAI.sqf index 728ef63bde..907ee33e7c 100644 --- a/A3A/addons/core/functions/CREATE/fn_reinforcementsAI.sqf +++ b/A3A/addons/core/functions/CREATE/fn_reinforcementsAI.sqf @@ -25,103 +25,129 @@ while {killZoneRemove >= 1} do killZoneRemove = killZoneRemove - 1; }; -// Handle the old reinforcements - -private _playerScale = call A3A_fnc_getPlayerScale; -private _totalReinf = 4 * round (3 * (1 + tierWar/10) * _playerScale * (0.5 + random 1)); -Debug_1("Sending %1 total troops to reinforce", _totalReinf); - -private _airportsX = airportsX select {(sidesX getVariable [_x,sideUnknown] != teamPlayer) and (spawner getVariable _x != 0)}; -if (gameMode == 3) then { _airportsX pushBack "NATO_carrier" } else { _airportsX append ["NATO_carrier", "CSAT_carrier"] }; - -// build list of markers that need reinforcement -private _reinfTargets = []; // elements are [troopsNeeded, marker] -{ - private _site = _x; - private _troopsNeeded = ([_site] call A3A_fnc_garrisonSize) - count (garrison getVariable [_site, []]); - if (_troopsNeeded <= 0) then { continue }; - if (_site in forcedSpawn) then { continue }; +// Do killzones do anything anymore? +// actually want two things: +// 1. Routes where ground vehicles got stuck +// 2. Dangerous locations +// Point 1 needs handling maybe +// Point 2 can be replaced with a recentDamage check for the moment - // Don't reinforce if marker has enemy-controlled airfields within spawn distance - private _siteSide = sidesX getVariable [_site, sideUnknown]; - if (-1 != airportsX findIf {(markerPos _x distance2d markerPos _site < distanceSPWN) and (sidesX getVariable [_x,sideUnknown] != _siteSide)}) then { continue }; - - _reinfTargets pushBack [_troopsNeeded, _site]; -} forEach (outposts + seaports + resourcesX + factories); - -// prioritize bases with most troops needed -_reinfTargets sort false; +// Handle the old reinforcements private _fnc_pickSquadType = { - params ["_count", "_side"]; - private _faction = Faction(_side); + params ["_count", "_faction"]; if (_numTroops == 8) exitWith { selectRandom (_faction get "groupsSquads")}; selectRandom (_faction get "groupsMedium"); }; -while {_totalReinf > 0} do { - if (_airportsX isEqualTo [] or _reinfTargets isEqualTo []) exitWith {}; - private _airport = selectRandom _airportsX; - private _side = sidesX getVariable [_airport, sideUnknown]; + private _side = _x; + if (gamemode == 3 and _side == Invaders) exitWith {}; + + private _faction = Faction(_side); + private _lowAir = _faction getOrDefault ["attributeLowAir", false]; + private _defRes = [A3A_resourcesDefenceOcc, A3A_resourcesDefenceInv] select (_side == Invaders); + private _totalReinf = 4 * round (0.1 * _defRes / 40); + Debug_3("%1 sending %2 total troops to reinforce due to %3 resources", _side, _totalReinf, _defRes); + if (_totalReinf == 0) then {continue}; + + private _sourceAirports = airportsX select {(sidesX getVariable [_x,sideUnknown] == _side) and (spawner getVariable _x == 2)}; + _sourceAirports pushBack (["NATO_carrier", "CSAT_carrier"] select (_side == Invaders)); + + // build list of markers that need reinforcement + private _reinfTargets = []; // elements are [troopsNeeded, marker] + private _enemyAirfieldPositions = airportsX select {sidesX getVariable _x != _side} apply { markerPos _x }; + { + private _site = _x; + if (sidesX getVariable _site != _side) then { continue }; + if (_site in forcedSpawn) then { continue }; - //Self reinforce the airport if needed - if !("carrier" in _airport) then { - private _numNeeded = ([_airport] call A3A_fnc_garrisonSize) - count (garrison getVariable [_airport, []]); - if (_numNeeded <= 0) exitWith {}; + // Don't reinforce (by air?) if marker has enemy-controlled airfields within spawn distance + if (_enemyAirfieldPositions inAreaArray [markerPos _x, 1000, 1000] isNotEqualTo []) then { continue }; + // Don't reinforce places with significant recent violence (use QRFs instead) + if ([_side, markerPos _site, 300] call A3A_fnc_getRecentDamage > 50) then { continue }; + + private _maxTroops = [_site] call A3A_fnc_garrisonSize; + private _troopsNeeded = _maxTroops - count (garrison getVariable [_site, []]); + if (_troopsNeeded <= 0) then { continue }; + _reinfTargets pushBack [_troopsNeeded/_maxTroops, _troopsNeeded, _site]; + } forEach (airportsX + outposts + seaports + resourcesX + factories); + + // prioritize bases with highest proportion of troops needed + _reinfTargets sort false; + + while {_totalReinf > 0} do + { + if (_sourceAirports isEqualTo [] or _reinfTargets isEqualTo []) exitWith {}; + + //Find a suitable site to reinforce + private ["_source", "_targIndex"]; + if (_lowAir) then { + // Bias towards the highest-weight target and then find a suitable source base. Might be self. + _targIndex = floor (count _reinfTargets * (random 1)^2); + _source = [_side, _reinfTargets#_targIndex#2] call A3A_fnc_availableBasesLand; + if (isNil "_source") then { + // No possible reinforcements for this location, remove it from the list + _reinfTargets deleteAt _targIndex; + continue; + }; + } else { + // Look for best target around a random airfield + _source = selectRandom _sourceAirports; + private _killZones = killzones getVariable [_source, []]; + _targIndex = _reinfTargets findIf { + (markerPos (_x#2) distance2d markerPos _source < distanceForAirAttack) + and !((_x#2) in _killZones) + }; + if (_targIndex == -1) then { + // Airport has nothing to do, remove it from the list + _sourceAirports deleteAt (_sourceAirports find _source); + continue; + }; + }; + + (_reinfTargets deleteAt _targIndex) params ["_weight", "_numNeeded", "_target"]; private _numTroops = [4, 8] select (_numNeeded > 4 and _totalReinf >= 8 and random 1 > 0.3); - [[_numTroops, _side] call _fnc_pickSquadType, _side, _airport, 0] remoteExec ["A3A_fnc_garrisonUpdate",2]; - Debug_2("Airport %1 self-reinforced with %2 troops", _airport, _numTroops); _totalReinf = _totalReinf - _numTroops; - continue; - }; - //Find a suitable site to reinforce - private _killZones = killzones getVariable [_airport, []]; - private _targIndex = _reinfTargets findIf { - (getMarkerPos (_x#1) distance2d getMarkerPos _airport < distanceForAirAttack) - and (sidesX getVariable [_x#1, sideUnknown] == _side) - and !((_x#1) in _killZones) - }; - if (_targIndex == -1) then { - // Airport has nothing to do, remove it from the list - _airportsX deleteAt (_airportsX find _airport); - continue; + Debug_3("Reinforcing garrison %1 from %2 with %3 troops", _target, _source, _numTroops); + if (_source == _target) then { + // Self-reinforce. Already know that we're not spawned, so this is fine + [[_numTroops, _faction] call _fnc_pickSquadType, _side, _target, 0] remoteExec ["A3A_fnc_garrisonUpdate",2]; + continue; + }; + if ([distanceSPWN1, 1, getMarkerPos _target, teamPlayer] call A3A_fnc_distanceUnits) then { + // If rebels are near the target, send a real reinforcement + [[_target, _source, _numTroops, _side], "A3A_fnc_patrolReinf"] call A3A_fnc_scheduler; + sleep 10; // Might re-use this marker shortly, avoid collisions + } else { + // Otherwise just add troops directly + [[_numTroops, _faction] call _fnc_pickSquadType, _side, _target, 2] remoteExec ["A3A_fnc_garrisonUpdate", 2]; + }; }; +} forEach [Occupants, Invaders]; - (_reinfTargets deleteAt _targIndex) params ["_numNeeded", "_target"]; - private _numTroops = [4, 8] select (_numNeeded > 4 and _totalReinf >= 8 and random 1 > 0.3); - _totalReinf = _totalReinf - _numTroops; - - Debug_3("Reinforcing garrison %1 from %2 with %3 troops", _target, _airport, _numTroops); - if ([distanceSPWN1, 1, getMarkerPos _target, teamPlayer] call A3A_fnc_distanceUnits) then { - // If rebels are near the target, send a real reinforcement - [[_target, _airport, _numTroops, _side], "A3A_fnc_patrolReinf"] call A3A_fnc_scheduler; - sleep 10; // Might re-use this marker shortly, avoid collisions - } else { - // Otherwise just add troops directly - [[_numTroops, _side] call _fnc_pickSquadType, _side, _target, 2] remoteExec ["A3A_fnc_garrisonUpdate", 2]; - }; -}; // If there aren't too many road patrols around already, generate about 1.5 * playerScale per hour -if (AAFpatrols < round (3 * _playerScale) and (random 4 < _playerScale)) then { +if (AAFpatrols < round (3 * A3A_balancePlayerScale) and (random 4 < A3A_balancePlayerScale)) then { [] spawn A3A_fnc_AAFroadPatrol; }; -// Reduce loot crate cooldown if garrison is complete +// Reduce loot crate cooldown if garrison is reasonably full { call { private _lootCD = garrison getVariable [_x + "_lootCD", 0]; if (_lootCD == 0) exitWith {}; // don't update unless changed private _realSize = count (garrison getVariable [_x, []]); - if (_realSize < [_x] call A3A_fnc_garrisonSize) exitWith {}; + private _maxSize = [_x, true] call A3A_fnc_garrisonSize; // use non-frontline size + if (_realSize / _maxSize < 0.75) exitWith {}; garrison setVariable [_x + "_lootCD", 0 max (_lootCD - 10), true]; }; } forEach (airportsX + outposts + seaports); +/* { //Setting the number of recruitable units per ticks per airport garrison setVariable [format ["%1_recruit", _x], 12, true]; @@ -152,3 +178,4 @@ if (AAFpatrols < round (3 * _playerScale) and (random 4 < _playerScale)) then { { [_x] call A3A_fnc_replenishGarrison; } forEach airportsX; +*/ diff --git a/A3A/addons/core/functions/CREATE/fn_removeVehFromPool.sqf b/A3A/addons/core/functions/CREATE/fn_removeVehFromPool.sqf deleted file mode 100644 index d38c8f66fc..0000000000 --- a/A3A/addons/core/functions/CREATE/fn_removeVehFromPool.sqf +++ /dev/null @@ -1,12 +0,0 @@ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -if (_this in FactionGet(all,"vehiclesUnlimited")) exitWith {}; - -private _number = timer getVariable _this; - -if (isNil "_number") then { - timer setVariable [_this, 0, true]; -} else { - if (!(_number isEqualType 0)) then { _number = 1; }; - timer setVariable [_this, _number - 1, true]; -}; diff --git a/A3A/addons/core/functions/CREATE/fn_singleAttack.sqf b/A3A/addons/core/functions/CREATE/fn_singleAttack.sqf index ea6fa812dc..027c3b4d0c 100644 --- a/A3A/addons/core/functions/CREATE/fn_singleAttack.sqf +++ b/A3A/addons/core/functions/CREATE/fn_singleAttack.sqf @@ -1,15 +1,13 @@ -params ["_markerDestination", "_side", "_super"]; -/* Sends an attack force towards the given marker +/* Sends a combined attack force to capture the given marker - Execution on: Server - - Scope: External + Environment: Server or HC, scheduled Params: - _markerDestination: MARKER : The target position where the attack will be send to - _side: SIDE or MARKER : The start parameter of the attack - _super: BOOLEAN : Determine if the attack should be super strong + _mrkDest: MARKER : The target position where the attack will be send to + _side: SIDE : The side to send the attack + _vehCount: NUMBER : Number of vehicles to use in the attack + _reveal: NUMBER : Amount of info to reveal to rebels, 0 low, 1 high Returns: Nothing @@ -17,164 +15,47 @@ params ["_markerDestination", "_side", "_super"]; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -ServerInfo_1("Starting single attack with parameters %1", _this); - -private _markerOrigin = ""; -private _posOrigin = []; - -private _posDestination = getMarkerPos _markerDestination; - -//Don't attempt unless we have enough units spare on this machine to make a worthwhile attack -if ([_side] call A3A_fnc_remUnitCount < 16) exitWith -{ - ServerInfo_1("SingleAttack to %1 cancelled because maximum unit count reached", _markerDestination); -}; - -if ([_posDestination,false] call A3A_fnc_fogCheck < 0.3) exitWith -{ - ServerInfo_1("SingleAttack to %1 cancelled due to heavy fog", _markerDestination); -}; - -//Parameter is the starting base -if(_side isEqualType "") then -{ - _markerOrigin = _side; - _posOrigin = getMarkerPos _markerOrigin; - _side = sidesX getVariable [_markerOrigin, sideUnknown]; - ServerInfo_2("Adapting attack params, side is %1, start base is %2", _side, _markerOrigin); -}; - -if(_side == sideUnknown) exitWith -{ - ServerError_1("Could not retrieve side for %1", _markerOrigin); -}; -private _faction = Faction(_side); - -private _typeOfAttack = [_posDestination, _side] call A3A_fnc_chooseAttackType; -if(_typeOfAttack == "") exitWith {}; - -//No start based selected by now -if(_markerOrigin == "") then -{ - _markerOrigin = [_posDestination, _side] call A3A_fnc_findBaseForQRF; - _posOrigin = getMarkerPos _markerOrigin; -}; - -if (_markerOrigin == "") exitWith -{ - ServerInfo_1("Small attack to %1 cancelled because no usable bases in vicinity",_markerDestination); -}; +params ["_mrkDest", "_side", "_vehCount", "_reveal"]; +private _targPos = markerPos _mrkDest; -//Base selected, select units now -private _vehicles = []; -private _groups = []; -private _landPosBlacklist = []; +ServerInfo_1("Starting attack with parameters %1", _this); -private _aggression = if (_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; -private _playerScale = call A3A_fnc_getPlayerScale; -if (sidesX getVariable [_markerDestination, sideUnknown] != teamPlayer) then { _aggression = 100 - _aggression; _playerScale = 1; }; -private _vehicleCount = random 1 + 2*_playerScale + _aggression/33 + ([0, 2] select _super); -_vehicleCount = (round (_vehicleCount)) max 1; +private _airbase = [_side, markerPos _mrkDest] call A3A_fnc_availableBasesAir; -ServerDebug_3("Due to %1 aggression and %2 player scale, sending %3 vehicles", _aggression, _playerScale, _vehicleCount); +//params ["_side", "_airbase", "_target", "_resPool", "_vehCount", "_delay", "_modifiers", "_attackType", "_reveal"]; +private _data = [_side, _airbase, _mrkDest, "defence", _vehCount, 0, [], "CounterAttack", _reveal] call A3A_fnc_createAttackForceMixed; +_data params ["", "_vehicles", "_crewGroups", "_cargoGroups"]; -//Set idle times for marker -if (_markerOrigin in airportsX) then -{ - [_markerOrigin, 20] call A3A_fnc_addTimeForIdle; -} -else -{ - [_markerOrigin, 40] call A3A_fnc_addTimeForIdle; -}; - -private _vehPool = []; -private _replacement = []; - -if ((_posOrigin distance2D _posDestination < distanceForLandAttack) && {[_posOrigin, _posDestination] call A3A_fnc_arePositionsConnected}) then -{ - //The attack will be carried out by land and air vehicles - _vehPool = [_side] call A3A_fnc_getVehiclePoolForAttacks; - _replacement = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesTrucks") + (_faction get "vehiclesLightArmed"); -} -else -{ - //The attack will be carried out by air vehicles only - _vehPool = [_side, ["LandVehicle"]] call A3A_fnc_getVehiclePoolForAttacks; - _replacement = (_faction get "vehiclesHelisLight"); -}; - -//If vehicle pool is empty, fill it up -if(_vehPool isEqualTo []) then -{ - {_vehPool append [_x, 1]} forEach _replacement; -}; - -//Spawn in the vehicles -for "_i" from 1 to _vehicleCount do -{ - if ([_side] call A3A_fnc_remUnitCount < 4) exitWith { - ServerInfo("Cancelling because maxUnits exceeded"); - }; - - private _vehicleType = selectRandomWeighted _vehPool; - private _vehicleData = [_vehicleType, _typeOfAttack, _landPosBlacklist, _side, _markerOrigin, _posDestination] call A3A_fnc_createAttackVehicle; - if (_vehicleData isEqualType []) then - { - _vehicles pushBack (_vehicleData select 0); - _groups pushBack (_vehicleData select 1); - if !(isNull (_vehicleData select 2)) then - { - _groups pushBack (_vehicleData select 2); - }; - _landPosBlacklist = (_vehicleData select 3); - sleep 5; - }; -}; -ServerInfo_2("Spawn Performed: Small %1 attack sent with %2 vehicles", _typeOfAttack, count _vehicles); - -//Prepare despawn conditions +// Prepare despawn conditions private _endTime = time + 2700; -private _qrfHasArrived = false; -private _qrfHasWon = false; +private _victory = false; +private _soldiers = []; +{ _soldiers append units _x } forEach _cargoGroups; while {true} do { - private _markerSide = sidesX getVariable [_markerDestination, sideUnknown]; - - if(_markerSide == _side) exitWith - { - ServerInfo_1("Small attack to %1 captured the marker, starting despawn routines", _markerDestination); + private _markerSide = sidesX getVariable _mrkDest; + if(_markerSide == _side) exitWith { + ServerInfo_1("Small attack to %1 captured the marker, starting despawn routines", _mrkDest); + _victory = true; }; - //Trying to flip marker - [_markerDestination, _markerSide] remoteExec ["A3A_fnc_zoneCheck", 2]; - - private _groupAlive = false; - { - private _index = (units _x) findIf {[_x] call A3A_fnc_canFight}; - if(_index != -1) exitWith - { - _groupAlive = true; - }; - } forEach _groups; - - if !(_groupAlive) exitWith - { - ServerInfo_1("Small attack to %1 has been eliminated, starting despawn routines", _markerDestination); + private _curSoldiers = { !fleeing _x and _x call A3A_fnc_canFight } count _soldiers; + if (_curSoldiers < count _soldiers * 0.25) exitWith { + ServerInfo_1("Small attack to %1 has been defeated, starting despawn routines", _mrkDest); }; - - sleep 60; - if(_endTime < time) exitWith - { - ServerInfo_1("Small attack to %1 timed out without winning or loosing, starting despawn routines", _markerDestination); + if(_endTime < time) exitWith { + ServerInfo_1("Small attack to %1 timed out, starting despawn routines", _mrkDest); }; -}; -{ - [_x] spawn A3A_fnc_VEHDespawner; -} forEach _vehicles; + // Attempt to flip marker + [_mrkDest, _markerSide] remoteExec ["A3A_fnc_zoneCheck", 2]; + sleep 30; +}; +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _vehicles; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach _crewGroups; { - [_x] spawn A3A_fnc_groupDespawner; -} forEach _groups; + [_x, [nil, _mrkDest] select _victory] spawn A3A_fnc_enemyReturnToBase; + sleep 10; +} forEach _cargoGroups; diff --git a/A3A/addons/core/functions/CREATE/fn_spawnGroup.sqf b/A3A/addons/core/functions/CREATE/fn_spawnGroup.sqf index ed95837f7e..c29ed33468 100644 --- a/A3A/addons/core/functions/CREATE/fn_spawnGroup.sqf +++ b/A3A/addons/core/functions/CREATE/fn_spawnGroup.sqf @@ -10,19 +10,6 @@ _typesX = _this select 2; _override = if (count _this >3) then {_this select 3} else {false}; _canBypass = if (count _this > 4) then {_this select 4} else {false};*/ -_allUnits = {(local _x) and (alive _x)} count allUnits; -_allUnitsSide = 0; -_maxUnitsSide = maxUnits; -if (gameMode <3) then - { - _allUnitsSide = {(local _x) and (alive _x) and (side group _x == _sideX)} count allUnits; - _maxUnitsSide = round (maxUnits * 0.7); - }; -if (_canBypass) then - { - if ((_allUnits + 1 <= maxUnits) or (_allUnitsSide + 1 <= _maxUnitsSide)) then {_canBypass = false}; - }; -if (_canBypass) exitWith {grpNull}; _groupX = createGroup _sideX; _ranks = ["LIEUTENANT","SERGEANT","CORPORAL"]; _countX = count _typesX; @@ -37,20 +24,12 @@ else _countRanks = (count _ranks - 1); Debug_2("Side: %1 spawning group composition: %2", _sideX, _typesX); for "_i" from 0 to (_countX - 1) do - { - if ((_i == 0) or (((_allUnits + 1) < maxUnits) and ((_allUnitsSide + 1) < _maxUnitsSide)) or _override) then - { - _unit = [_groupX, (_typesX select _i), _positionX, [], 0, "NONE"] call A3A_fnc_createUnit; - _unit allowDamage false; - _allUnits = _allUnits + 1; - _allUnitsSide = _allUnitsSide + 1; - if (_i <= _countRanks) then - { - _unit setRank (_ranks select _i); - }; - if ((_typesX select _i) in FactionGet(all,"SquadLeaders")) then {_groupX selectLeader _unit}; - sleep 0.25; - }; - }; +{ + _unit = [_groupX, (_typesX select _i), _positionX, [], 0, "NONE"] call A3A_fnc_createUnit; + _unit allowDamage false; + if (_i <= _countRanks) then { _unit setRank (_ranks select _i) }; + if ((_typesX select _i) in FactionGet(all,"SquadLeaders")) then {_groupX selectLeader _unit}; + sleep 0.25; +}; {_x allowDamage true} forEach units _groupX; _groupX diff --git a/A3A/addons/core/functions/CREATE/fn_vehAvailable.sqf b/A3A/addons/core/functions/CREATE/fn_vehAvailable.sqf index 34b1a739e6..8c04fd783c 100644 --- a/A3A/addons/core/functions/CREATE/fn_vehAvailable.sqf +++ b/A3A/addons/core/functions/CREATE/fn_vehAvailable.sqf @@ -3,6 +3,10 @@ FIX_LINE_NUMBERS() private ["_typeX","_cant"]; _typeX = _this select 0; if (_typeX == "") exitWith {false}; + +// Function is obsolete, just leave this as a temp stub for garrison code +if (true) exitWith {true}; + if ( _typeX in FactionGet(all,"vehiclesUnlimited") ) exitWith {true}; _cant = timer getVariable _typeX; if (isNil "_cant") exitWith {true}; diff --git a/A3A/addons/core/functions/CREATE/fn_vehKilledOrCaptured.sqf b/A3A/addons/core/functions/CREATE/fn_vehKilledOrCaptured.sqf index 28aec9d3f3..a67d774843 100644 --- a/A3A/addons/core/functions/CREATE/fn_vehKilledOrCaptured.sqf +++ b/A3A/addons/core/functions/CREATE/fn_vehKilledOrCaptured.sqf @@ -19,25 +19,32 @@ if (_captured && (_side == _sideEnemy)) exitWith {}; private _act = if (_captured) then {"captured"} else {"destroyed"}; ServerDebug_4("%1 of %2 %3 by %4", _type, _side, _act, _sideEnemy); -if (_side == Occupants or _side == Invaders) then -{ - _type remoteExecCall ["A3A_fnc_removeVehFromPool", 2]; - if (_sideEnemy != teamPlayer) exitWith {}; +// Kick units out of vehicles when destroyed & touching ground +if (!_captured and count crew _veh > 0) then { + _veh spawn { + private _timeout = time + 30; // sometimes destroyed vehicles return isTouchingGround false + waitUntil { sleep 2; time > _timeout or isTouchingGround _this }; + while {count crew _this > 0} do { + moveOut (crew _this # 0); + sleep 0.5; + }; + }; +}; - private _value = call { - if (_type in FactionGet(all,"vehiclesAPCs")) exitWith {5}; - if (_type in FactionGet(all,"vehiclesTanks")) exitWith {10}; - if (_type in FactionGet(all,"vehiclesAA") or _type in FactionGet(all,"vehiclesArtillery")) exitWith {10}; - if (_type in FactionGet(all,"vehiclesHelisAttack")) exitWith {10}; - if (_type in FactionGet(all,"vehiclesTransportAir")) exitWith {4}; - if (_type in FactionGet(all,"vehiclesFixedWing")) exitWith {10}; // transportAir must be before this - if (_type isKindOf "StaticWeapon") exitWith {1}; - 2; // trucks, light attack, boats, UAV etc +private _vehCost = A3A_vehicleResourceCosts getOrDefault [_type, 0]; +if ((_side == Occupants or _side == Invaders) and _vehCost > 0) then +{ + if (_veh getVariable ["A3A_resPool", "legacy"] == "legacy") then { + // Vehicle not pre-resourced, deplete both pools + [-_vehCost, _side, "legacy"] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; }; + [_side, getPos _veh, 2*_vehCost/3] remoteExec ["A3A_fnc_addRecentDamage", 2]; // other third applied in HandleDamage - [_side, _value, 45] remoteExec ["A3A_fnc_addAggression", 2]; + if (_sideEnemy != teamPlayer) exitWith {}; + + [_side, round (_vehCost / 50), 45] remoteExec ["A3A_fnc_addAggression", 2]; if (_side == Occupants) then { - [-_value/3, _value/3, position _veh] remoteExec ["A3A_fnc_citySupportChange", 2]; + [-_vehCost / 100, _vehCost / 100, position _veh] remoteExec ["A3A_fnc_citySupportChange", 2]; }; }; @@ -67,9 +74,11 @@ if (_side == civilian) then if (_captured) then { - // Do the actual side-switch - _veh setVariable ["ownerSide", _sideEnemy, true]; if (_sideEnemy == teamPlayer) then { - if !(_veh isKindOf "StaticWeapon") then { [_veh] spawn A3A_fnc_VEHdespawner }; + // Remove from vehicle despawner. Should work because this function is called locally to original vehicle creator + private _despawnerHandle = _veh getVariable "A3A_despawnerHandle"; + if (!isNil "_despawnerHandle") then { terminate _despawnerHandle; _veh setVariable ["A3A_despawnerHandle", nil]; }; }; + // Do the actual side-switch + _veh setVariable ["ownerSide", _sideEnemy, true]; }; diff --git a/A3A/addons/core/functions/CREATE/fn_wavedAttack.sqf b/A3A/addons/core/functions/CREATE/fn_wavedAttack.sqf new file mode 100644 index 0000000000..b957b658b8 --- /dev/null +++ b/A3A/addons/core/functions/CREATE/fn_wavedAttack.sqf @@ -0,0 +1,206 @@ +/* +Maintainer: John Jordan + Sends a combined attack force to capture the given marker + +Scope: Server +Environment: Scheduled, should be spawned + +Arguments: + Destination marker (enemy-owned airport, outpost, seaport, factory or resource) + Origin marker (should be airbase) + Maximum number of attack waves to send +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_mrkDest", "_mrkOrigin", "_maxWaves"]; + +Info_3("Creating waved attack against %1 from %2 with %3 waves", _mrkDest, _mrkOrigin, _maxWaves); + +// TODO: move this to chooseAttack? +bigAttackInProgress = true; publicVariable "bigAttackInProgress"; +forcedSpawn pushBack _mrkDest; publicVariable "forcedSpawn"; + +private _targpos = markerPos _mrkDest; +private _side = sidesX getVariable _mrkOrigin; +private _targside = sidesX getVariable _mrkDest; +private _faction = Faction(_side); +private _lowAir = _faction getOrDefault ["attributeLowAir", false]; + +// Create a task for enemy vs rebel, notification only for enemy vs enemy +private _nameDest = [_mrkDest] call A3A_fnc_localizar; +private _nameEnemy = _faction get "name"; +private _taskId = "wavedAttack" + str A3A_taskCount; +if (_targside == teamPlayer) then { + private _taskStr = format ["%1 is attacking our garrison at %2. Stop them if you can, or live to fight another day.", _nameEnemy, _nameDest]; + [true,_taskId,[_taskStr,format ["%1 Attack",_nameEnemy],_mrkDest],markerPos _mrkDest,false,0,true,"Defend",true] call BIS_fnc_taskCreate; + [_taskId, "wavedAttack", "CREATED"] remoteExecCall ["A3A_fnc_taskUpdate", 2]; +} else { + private _text = format ["%1 is attacking the %2 garrison at %3.", _nameEnemy, Faction(_targside) get "name", _nameDest]; + ["RadioIntercepted", [_text]] remoteExec ["BIS_fnc_showNotification", 0]; +}; + +// Generate reveal value for the attack wave notifications +private _reveal = call { + if (_targside != teamPlayer) exitWith {0}; + private _reveal = [_targPos] call A3A_fnc_calculateSupportCallReveal; + [_side, _targPos, _reveal] call A3A_fnc_useRadioKey; +}; + + +// These mostly used for cleanup? +private _allCargoGroups = []; +private _allCrewGroups = []; +private _allVehicles = []; +private _attackHelis = []; + +private _wave = 1; +private _victory = false; +while {_wave <= _maxWaves and !_victory} do +{ + // Somewhat flattened because a lot of the work is done by garrisons + private _vehCount = round (2 + random 1 + 3*A3A_balancePlayerScale); + if (_targside != teamPlayer) then { _vehCount = 5 + round (random 2) }; + if (_wave == 1) then { _vehCount = _vehCount + 2 }; + + // Check what air supports & attack helis we have left from previous waves + // Check active air supports for UAV/CAS/ASF + private _countNewSupport = 0; + private _airSupports = []; // support type strings + call { + { + _x params ["_supportName", "_suppSide", "_suppType", "_suppCenter", "_suppRadius", "_suppTarget"]; + if (_suppSide != _side or _suppCenter distance2d _targpos > _suppRadius) then { continue }; + if (_suppType in ["UAV", "CAS", "ASF"]) then { _airSupports pushBack _suppType }; + } forEach A3A_activeSupports; + + // Not ideal because it might have a dead gunner. Might need some proper vehicleCanFight function + _attackHelis = _attackHelis select { canMove _x and canFire _x }; + + private _remSupports = (count _airSupports + count _attackHelis); + private _reqSupports = round (_vehCount * (0.1 + random 0.1 + (5 + tierWar) * 0.025) * ([1, 0.4] select _lowAir)); + _countNewSupport = 1 max (_reqSupports - _remSupports); + + ServerDebug_3("Remaining air supports %1, plus %2 attack helis. Adding %3 air supports", _airSupports, count _attackHelis, _countNewSupport); + }; + _vehCount = _vehCount - _countNewSupport; + + // Approx, just to prevent sending QRFs on top + A3A_supportStrikes pushBack [_side, "TROOPS", _targPos, time + 1800, 1800, _vehCount * A3A_balanceVehicleCost]; + + + // Send the land units and air transports. Returns once air sent + private _minDelay = [0, 300 / A3A_balancePlayerScale] select (_wave == 1 and _targSide == teamPlayer); + //params ["_side", "_airbase", "_target", "_resPool", "_vehCount", "_delay", "_modifiers", "_attackType", "_reveal"]; + private _data = [_side, _mrkOrigin, _mrkDest, "attack", _vehCount, _minDelay, ["noairsupport"], "MajorAttack", _reveal] call A3A_fnc_createAttackForceMixed; + _data params ["", "_newVehicles", "_crewGroups", "_cargoGroups"]; + + + // Now add air supports up to the requirement + private _newAttackHelis = 0; + for "_i" from 1 to _countNewSupport do + { + private _possibles = ["AH", 1]; + if !("UAV" in _airSupports) then { _possibles append ["UAV", 1] }; + if !("CAS" in _airSupports) then { _possibles append ["CAS", 0.6] }; + if !("ASF" in _airSupports) then { _possibles append ["ASF", 0.3] }; + + private _support = selectRandomWeighted _possibles; + if (_support == "AH") then { _newAttackHelis = _newAttackHelis + 1 } + else { + // ["_type", "_side", "_caller", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + private _suppName = [_support, _side, "attack", 500, objNull, _targPos, 0, 0] call A3A_fnc_createSupport; + if (_suppName == "") exitWith { _newAttackHelis = _newAttackHelis + 1 }; + _airSupports pushBack _support; + }; + }; + + // Spawn the attack helis + if (_newAttackHelis > 0) then { + // ["_side", "_originMrk", "_destMrk", "_resPool", "_vehCount", "_attackVehCount", "_tierMod"] + private _data = [_side, _mrkOrigin, _mrkDest, "attack", _newAttackHelis, _newAttackHelis, 2] call A3A_fnc_createAttackForceAir; + _newVehicles append _data#1; + _attackHelis append _data#1; + _crewGroups append _data#2; + + [-(_data#0), _side, "attack"] remoteExec ["A3A_fnc_addEnemyResources", 2]; + + ServerInfo_1("Spawn performed: Attack helis %1", (_data#1) apply {typeof _x}); + }; + + // Request some artillery + call { + // Choose target/pos. Aim for static weapon if known, or just somewhere around flag otherwise + private _target = markerPos _mrkDest getPos [random 100, random 360]; + private _vehicles = vehicles inAreaArray _mrkDest; + _vehicles = _vehicles select { canFire _x and _x isKindOf "StaticWeapon" }; + if !(_vehicles isEqualTo []) then { _target = selectRandom _vehicles }; + + // ["_side", "_target", "_caller", "_precision", "_reveal", "_delay"]; + [_side, _target, "attack", _wave min 4, 0, 0] call A3A_fnc_requestArtillery; + }; + + private _timeout = time + 900; // wave timeout, 15 mins after the wave has finished spawning + private _soldiers = []; + { _soldiers append units _x } forEach _cargoGroups; // only new troops count, in case old troops are just stuck somewhere + + _allCargoGroups append _cargoGroups; + _allCrewGroups append _crewGroups; + _allVehicles append _newVehicles; + + // Wave termination monitor + while {true} do + { +// if (sidesX getVariable [_mrkDestination,sideUnknown] != teamPlayer) then {_soldiers spawn A3A_fnc_remoteBattle}; + private _markerSide = sidesX getVariable _mrkDest; + if(_markerSide == _side) exitWith { + ServerInfo_2("Wave %1 has captured %2", _wave, _mrkDest); + _victory = true; + }; + + private _curSoldiers = { !fleeing _x and _x call A3A_fnc_canFight } count _soldiers; + Debug_2("%1 soldiers remaining out of %2", _curSoldiers, count _soldiers); + if (_curSoldiers < count _soldiers * 0.25) exitWith { + ServerInfo_2("Wave %1 against %2 has been defeated", _wave, _mrkDest); + }; + if(_timeout < time) exitWith { + ServerInfo_2("Wave %1 against %2 has timed out", _wave, _mrkDest); + }; + + // Attempt to flip marker + [_mrkDest, _markerSide] remoteExec ["A3A_fnc_zoneCheck", 2]; + sleep 10; + }; + _wave = _wave + 1; +}; + +if (_victory) then { + if (_targSide != teamPlayer) exitWith {}; + [_taskId, "rebelAttack", "FAILED"] call A3A_fnc_taskSetState; + [_taskId, "rebelAttack", 30] spawn A3A_fnc_taskDelete; + if (_targside == teamPlayer) then { [-10,theBoss] call A3A_fnc_playerScoreAdd }; +} else { + [_mrkDest, _mrkOrigin] call A3A_fnc_minefieldAAF; + + if (_targSide != teamPlayer) exitWith {}; + [_taskId, "rebelAttack", "SUCCEEDED"] call A3A_fnc_taskSetState; + [_taskId, "rebelAttack", 30] spawn A3A_fnc_taskDelete; + private _nearRebels = [500, 0, markerPos _mrkDest, teamPlayer] call A3A_fnc_distanceUnits; + { if (isPlayer _x) then { [10, _x] call A3A_fnc_playerScoreAdd } } forEach _nearRebels; + [10, theBoss] call A3A_fnc_playerScoreAdd; +}; + +ServerInfo("Reached end of winning conditions. Starting despawn"); +sleep 30; + +bigAttackInProgress = false; publicVariable "bigAttackInProgress"; +forcedSpawn = forcedSpawn - [_mrkDest]; publicVariable "forcedSpawn"; + + +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _allVehicles; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach _allCrewGroups; +{ + [_x, [nil, _mrkDest] select _victory] spawn A3A_fnc_enemyReturnToBase; + sleep 10; +} forEach _allCargoGroups; diff --git a/A3A/addons/core/functions/CREATE/fn_wavedCA.sqf b/A3A/addons/core/functions/CREATE/fn_wavedCA.sqf deleted file mode 100644 index de51108414..0000000000 --- a/A3A/addons/core/functions/CREATE/fn_wavedCA.sqf +++ /dev/null @@ -1,818 +0,0 @@ -if (!isServer and hasInterface) exitWith {}; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private ["_posOrigin","_typeGroup","_nameOrigin","_markTsk","_wp1","_soldiers","_landpos","_pad","_vehiclesX","_wp0","_wp3","_wp4","_wp2","_groupX","_groups","_typeVehX","_vehicle","_heli","_heliCrew","_groupHeli","_pilots","_rnd","_resourcesAAF","_nVeh","_radiusX","_roads","_Vwp1","_road","_veh","_vehCrew","_groupVeh","_Vwp0","_size","_Hwp0","_groupX1","_uwp0","_tsk","_vehicle","_soldierX","_pilot","_posDestination","_prestigeCSAT","_airportX","_nameDest","_timeX","_solMax","_nul","_costs","_typeX","_threatEvalAir","_threatEvalLand","_pos","_timeOut","_sideX","_countX","_tsk1","_spawnPoint","_vehPool", "_airportIndex"]; - -bigAttackInProgress = true; -publicVariable "bigAttackInProgress"; - -//_mrkOrigin can be an Airport or Carrier -//_originalSide is optional, side that should have their attack counter incremented -params ["_mrkDestination", "_mrkOrigin", "_waves", "_originalSide"]; - -_firstWave = true; -if (_waves <= 0) then {_waves = -1}; -_size = [_mrkDestination] call A3A_fnc_sizeMarker; -_tsk = ""; -_tsk1 = ""; -_posDestination = getMarkerPos _mrkDestination; -_posOrigin = getMarkerPos _mrkOrigin; - -Debug_3("Spawning Waved Attack Against %1 from %2 with %3 waves", _mrkDestination, _mrkOrigin, _waves); - -_groups = []; -_soldiersTotal = []; -_pilots = []; -_vehiclesX = []; -_forced = []; - -_nameDest = [_mrkDestination] call A3A_fnc_localizar; -_nameOrigin = [_mrkOrigin] call A3A_fnc_localizar; - -_sideX = sidesX getVariable [_mrkOrigin,sideUnknown]; -private _faction = Faction(_sideX); -if (isNil "_originalSide") then { _originalSide = _sideX }; -_sideTsk = [teamPlayer,civilian,Invaders]; -_sideTsk1 = [Occupants]; -_nameENY = _faction get "name"; -//_config = cfgNATOInf; -if (_sideX == Invaders) then - { - //_config = cfgCSATInf; - _sideTsk = [teamPlayer,civilian,Occupants]; - _sideTsk1 = [Invaders]; - }; -_isSDK = if (sidesX getVariable [_mrkDestination,sideUnknown] == teamPlayer) then {true} else {false}; -_SDKShown = false; -if (_isSDK) then - { - _sideTsk = [teamPlayer,civilian,Occupants,Invaders] - [_sideX]; - } -else - { - if (not(_mrkDestination in _forced)) then {_forced pushBack _mrkDestination}; - }; - -//forcedSpawn = forcedSpawn + _forced; publicVariable "forcedSpawn"; -forcedSpawn pushBack _mrkDestination; publicVariable "forcedSpawn"; -Info_2("Side Attacker:%1, Side Defender: %2",_sideX,_isSDK); -_nameDest = [_mrkDestination] call A3A_fnc_localizar; - -private _taskId = "rebelAttack" + str A3A_taskCount; -[_sideTsk,_taskId,[format ["%2 Is attacking from the %1. Intercept them or we may loose a sector",_nameOrigin,_nameENY],format ["%1 Attack",_nameENY],_mrkOrigin],getMarkerPos _mrkOrigin,false,0,true,"Defend",true] call BIS_fnc_taskCreate; -[_sideTsk1,_taskId+"B",[format ["We are attacking %2 from the %1. Help the operation if you can",_nameOrigin,_nameDest],format ["%1 Attack",_nameENY],_mrkDestination],getMarkerPos _mrkDestination,false,0,true,"Attack",true] call BIS_fnc_taskCreate; -[_taskId, "rebelAttack", "CREATED"] remoteExecCall ["A3A_fnc_taskUpdate", 2]; - - -private _vehPoolLand = []; -private _vehPoolAirSupport = []; -private _vehPoolAirTransport = []; - -// unlimited vehicle types, for later use -private _typesPatrolHelis = _faction get "vehiclesHelisLight"; -private _typesTruck = _faction get "vehiclesTrucks"; -private _typesMRAP = _faction get "vehiclesLightArmed"; - -// Just getting the variables out of scope -call { - private _typesAPC = _faction get "vehiclesAPCs"; - private _typesTank = _faction get "vehiclesTanks"; - private _typesAA = _faction get "vehiclesAA"; - - // Add up to 4 + tierWar APCs, selected randomly from available vehicles - { - private _vcount = floor (timer getVariable [_x, 0]); - for "_i" from 1 to (_vcount) do { _vehPoolLand pushBack _x }; - } forEach _typesAPC; - _vehPoolLand = _vehPoolLand call BIS_fnc_arrayShuffle; - _vehPoolLand resize ((4 + tierWar) min (count _vehPoolLand)); - - // Add in war-tier capped tanks and AA vehicles - private _available = 0; - _typesTank = _typesTank select {timer getVariable [_x, 0] > 0}; - { _available = _available + (timer getVariable [_x, 0]) } forEach _typesTank; - private _tankCount = tierWar min _available; - for "_i" from 1 to (_tankCount) do { _vehPoolLand pushBack (selectRandom _typesTank) }; - - private _available = 0; - _typesAA = _typesAA select {timer getVariable [_x, 0] > 0}; - { _available = _available + (timer getVariable [_x, 0]) } forEach _typesAA; - private _aaCount = (ceil (tierWar / 3)) min _available; - for "_i" from 1 to (_aaCount) do { _vehPoolLand pushBack (selectRandom _typesAA) }; - - // Add some trucks and MRAPs depending on war tier - private _truckCount = 8 - ceil (tierWar / 2); - for "_i" from 1 to (_truckCount) do { _vehPoolLand pushBack (selectRandom _typesTruck) }; - private _mrapCount = 8 - ceil (tierWar / 2); - for "_i" from 1 to (_mrapCount) do { _vehPoolLand pushBack (selectRandom _typesMRAP) }; - - - // Separate air support from transports because air support can't conquer - - private _typesPlane = _faction get "vehiclesPlanesCAS"; - private _typesPlaneAA = _faction get "vehiclesPlanesAA"; - private _typesAttackHelis = _faction get "vehiclesHelisAttack"; - private _typesTransportPlanes = _faction get "vehiclesPlanesTransport"; - private _typesTransportHelis = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"); - - // Add up to 2 + tierWar attack helis, selected randomly from available vehicles - { - private _vcount = floor (timer getVariable [_x, 0]); - for "_i" from 1 to (_vcount) do { _vehPoolAirSupport pushBack _x }; - } forEach _typesAttackHelis; - _vehPoolAirSupport = _vehPoolAirSupport call BIS_fnc_arrayShuffle; - _vehPoolAirSupport resize ((2 + tierWar) min (count _vehPoolAirSupport)); - - // Plus a handful of fixed-wing aircraft - private _planeCount = ceil (tierWar / 3); - for "_i" from 1 to (_planeCount) do { _vehPoolAirSupport pushBack (selectRandom _typesPlane) }; - for "_i" from 1 to (_planeCount) do { _vehPoolAirSupport pushBack (selectRandom _typesPlaneAA) }; - - // Use up to 8 + tierWar/2 air transports, randomly selected from available vehicles - { - private _vcount = floor (timer getVariable [_x, 0]); - for "_i" from 1 to (_vcount) do { _vehPoolAirTransport pushBack _x }; - } forEach (_typesTransportPlanes + _typesTransportHelis); - _vehPoolAirTransport = _vehPoolAirTransport call BIS_fnc_arrayShuffle; - _vehPoolAirTransport resize ((8 + tierWar/2) min (count _vehPoolAirTransport)); - - // Fill out with patrol helis - private _patrolHeliCount = 8 - ceil (tierWar / 2); - for "_i" from 1 to (_patrolHeliCount) do { _vehPoolAirTransport pushBack (selectRandom _typesPatrolHelis) }; -}; - -Debug_1("Land vehicle pool: %1", _vehPoolLand); -Debug_1("Air transport pool: %1", _vehPoolAirTransport); -Debug_1("Air support pool: %1", _vehPoolAirSupport); - -private _airSupport = []; -private _uav = objNull; - -// First wave: half air support, half either air transports or ground vehicles. -// Subsequent waves: if live air support < half, top up. Otherwise, +1 air support. Fill out with transports/ground. -// Only one UAV at a time, rebuild if destroyed instead of one vehicle. -// Builds minimum 10 soldiers (air cargo or ground units) per wave. - -while {(_waves > 0)} do -{ - _soldiers = []; - private _playerScale = if (_isSDK) then { call A3A_fnc_getPlayerScale } else { 1 }; // occ vs inv attacks shouldn't depend on player count - _nVeh = round (1.5 + random 1 + 3*_playerScale); - if (_firstWave) then { _nVeh = _nVeh + 2 }; - - Debug_2("Due to %1 player scale, wave will contain %2 vehicles", _playerScale, _nVeh); - - _posOriginLand = []; - _pos = []; - _dir = 0; - _spawnPoint = ""; - if !(_mrkDestination in blackListDest) then - { - //Attempt land attack if origin is an airport in range - _airportIndex = airportsX find _mrkOrigin; - if (_airportIndex >= 0 and (_posOrigin distance _posDestination < distanceForLandAttack) - and ([_posOrigin, _posDestination] call A3A_fnc_arePositionsConnected)) then - { - _spawnPoint = server getVariable (format ["spawn_%1", _mrkOrigin]); - _pos = getMarkerPos _spawnPoint; - _posOriginLand = _posOrigin; - _dir = markerDir _spawnPoint; - } - else - //Find an outpost we can attack from - { - _outposts = outposts select { - (sidesX getVariable [_x,sideUnknown] == _sideX) - and (getMarkerPos _x distance _posDestination < distanceForLandAttack) - and {[_posDestination, getMarkerPos _x] call A3A_fnc_arePositionsConnected} - and {[_x,false] call A3A_fnc_airportCanAttack} // checks idle, garrison size, spawndist2 - }; - if !(_outposts isEqualTo []) then - { - _outpost = selectRandom _outposts; - _posOriginLand = getMarkerPos _outpost; - //[_outpost,60] call A3A_fnc_addTimeForIdle; - _spawnPoint = [_posOriginLand] call A3A_fnc_findNearestGoodRoad; - _pos = position _spawnPoint; - _dir = getDir _spawnPoint; - }; - }; - }; - private _nVehLand = 0; - if !(_posOriginLand isEqualTo []) then - { - _nVehLand = ceil (_nVeh / 2); // spawn >half ground, 0) exitWith {}; - _timeOut = _timeOut + 1; - _pos = _pos findEmptyPosition [0,100,_typeVehX]; - sleep 1; - }; - if (count _pos == 0) then {_pos = getMarkerPos _spawnPoint}; - _vehicle=[_pos, _dir,_typeVehX, _sideX] call A3A_fnc_spawnVehicle; - - _veh = _vehicle select 0; - _vehCrew = _vehicle select 1; - {[_x] call A3A_fnc_NATOinit} forEach _vehCrew; - [_veh, _sideX] call A3A_fnc_AIVEHinit; - _groupVeh = _vehicle select 2; - _soldiers append _vehCrew; - _soldiersTotal append _vehCrew; - _groups pushBack _groupVeh; - _vehiclesX pushBack _veh; - _landPos = [_posDestination,_pos,false,_landPosBlacklist] call A3A_fnc_findSafeRoadToUnload; - if (not(_typeVehX in FactionGet(all,"vehiclesTanks"))) then - { - _landPosBlacklist pushBack _landPos; - _typeGroup = [_typeVehX,_sideX] call A3A_fnc_cargoSeats; - _grupo = grpNull; - _grupo = [_posOrigin,_sideX, _typeGroup,true,false] call A3A_fnc_spawnGroup; - { - _x assignAsCargo _veh; - _x moveInCargo _veh; - if (vehicle _x == _veh) then - { - _soldiers pushBack _x; - _soldiersTotal pushBack _x; - [_x] call A3A_fnc_NATOinit; - _x setVariable ["originX",_mrkOrigin]; - } - else - { - deleteVehicle _x; - }; - } forEach units _grupo; - if (not(_typeVehX in FactionGet(all,"vehiclesTrucks"))) then - { - {_x disableAI "MINEDETECTION"} forEach (units _groupVeh); - (units _grupo) joinSilent _groupVeh; - deleteGroup _grupo; - _groupVeh spawn A3A_fnc_attackDrillAI; - [_posOriginLand,_landPos,_groupVeh] call A3A_fnc_WPCreate; - _Vwp0 = _groupVeh addWaypoint [_landPos, count (wayPoints _groupVeh)]; - _Vwp0 setWaypointType "TR UNLOAD"; - _Vwp0 setWayPointCompletionRadius (10*_countX); - _Vwp1 = _groupVeh addWaypoint [_posDestination, 1]; - _Vwp1 setWaypointType "SAD"; - _Vwp1 setWaypointStatements ["true","if !(local this) exitWith {}; {if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - _Vwp1 setWaypointBehaviour "COMBAT"; - _veh allowCrewInImmobile true; - private _typeName = if (_typeVehX in FactionGet(all,"vehiclesAPCs")) then {"APC"} else {"MRAP"}; - [_veh,"APC"] spawn A3A_fnc_inmuneConvoy; - } - else - { - (units _grupo) joinSilent _groupVeh; - deleteGroup _grupo; - _groupVeh selectLeader (units _groupVeh select 1); - _groupVeh spawn A3A_fnc_attackDrillAI; - [_posOriginLand,_landPos,_groupVeh] call A3A_fnc_WPCreate; - _Vwp0 = _groupVeh addWaypoint [_landPos, count (wayPoints _groupVeh)]; - _Vwp0 setWaypointType "GETOUT"; - _Vwp1 = _groupVeh addWaypoint [_posDestination, count (wayPoints _groupVeh)]; - _Vwp1 setWaypointType "SAD"; - [_veh,"Truck"] spawn A3A_fnc_inmuneConvoy; - }; - } - else - { - {_x disableAI "MINEDETECTION"} forEach (units _groupVeh); - [_posOriginLand,_posDestination,_groupVeh] call A3A_fnc_WPCreate; - _Vwp0 = _groupVeh addWaypoint [_posDestination, count (wayPoints _groupVeh)]; - _Vwp0 setWaypointType "MOVE"; - _Vwp0 setWaypointStatements ["true","if !(local this) exitWith {}; {if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - _Vwp0 = _groupVeh addWaypoint [_posDestination, count (wayPoints _groupVeh)]; - _Vwp0 setWaypointType "SAD"; - private _typeName = if (_typeVehX in FactionGet(all,"vehiclesTanks")) then {"Tank"} else {"AA"}; - [_veh, _typeName] spawn A3A_fnc_inmuneConvoy; - _veh allowCrewInImmobile true; - }; - }; - - if ((count _soldiers >= 10) && ([_sideX] call A3A_fnc_remUnitCount < 5)) exitWith { - Info_1("Ground wave reached maximum units count after %1 vehicles", _countX); - }; - sleep 15; - _countX = _countX + 1; - }; - }; - - _isSea = false; - if (!A3A_hasIFA && (count seaAttackSpawn != 0)) then - { - for "_i" from 0 to 3 do - { - _pos = _posDestination getPos [1000,(_i*90)]; - if (surfaceIsWater _pos) exitWith - { - if ({sidesX getVariable [_x,sideUnknown] == _sideX} count seaports > 1) then - { - _isSea = true; - }; - }; - }; - }; - - if ((_isSea) and (_firstWave)) then - { - _pos = getMarkerPos ([seaAttackSpawn,_posDestination] call BIS_fnc_nearestPosition); - if (count _pos > 0) then - { - _vehPool = (_faction get "vehiclesGunBoats") + (_faction get "vehiclesTransportBoats") + (_faction get "vehiclesAmphibious"); - _vehPool = _vehPool select {[_x] call A3A_fnc_vehAvailable}; - _countX = 0; - _spawnedSquad = false; - while {(_countX < 3) and (count _soldiers <= 80)} do - { - _typeVehX = if (_vehPool isEqualTo []) then {selectRandom (_faction get "vehiclesTransportBoats")} else {selectRandom _vehPool}; - _proceed = true; - if (_typeVehX in (_faction get "vehiclesGunBoats")) then - { - _landPos = [_posDestination, 10, 1000, 10, 2, 0.3, 0] call BIS_Fnc_findSafePos; - } - else - { - _allUnits = {(local _x) and (alive _x)} count allUnits; - _allUnitsSide = 0; - _maxUnitsSide = maxUnits; - if (gameMode <3) then - { - _allUnitsSide = {(local _x) and (alive _x) and (side group _x == _sideX)} count allUnits; - _maxUnitsSide = round (maxUnits * 0.7); - }; - if (((_allUnits + 4 > maxUnits) or (_allUnitsSide + 4 > _maxUnitsSide)) and _spawnedSquad) then - { - _proceed = false - } - else - { - _typeGroup = [_typeVehX,_sideX] call A3A_fnc_cargoSeats; - _landPos = [_posDestination, 10, 1000, 10, 2, 0.3, 1] call BIS_Fnc_findSafePos; - }; - }; - if ((count _landPos > 0) and _proceed) then - { - _vehicle=[_pos, random 360,_typeVehX, _sideX] call A3A_fnc_spawnVehicle; - - _veh = _vehicle select 0; - _vehCrew = _vehicle select 1; - _groupVeh = _vehicle select 2; - _pilots append _vehCrew; - _groups pushBack _groupVeh; - _vehiclesX pushBack _veh; - {[_x] call A3A_fnc_NATOinit} forEach units _groupVeh; - [_veh, _sideX] call A3A_fnc_AIVEHinit; - if (_typeVehX in (_faction get "vehiclesGunBoats")) then - { - _wp0 = _groupVeh addWaypoint [_landpos, 0]; - _wp0 setWaypointType "SAD"; - //[_veh,"Boat"] spawn A3A_fnc_inmuneConvoy; - } - else - { - _grupo = grpNull; - if !(_spawnedSquad) then {_grupo = [_posOrigin,_sideX, _typeGroup,true,false] call A3A_fnc_spawnGroup;_spawnedSquad = true} else {_grupo = [_posOrigin,_sideX, _typeGroup,false,true] call A3A_fnc_spawnGroup}; - { - _x assignAsCargo _veh; - _x moveInCargo _veh; - if (vehicle _x == _veh) then - { - _soldiers pushBack _x; - _soldiersTotal pushBack _x; - [_x] call A3A_fnc_NATOinit; - _x setVariable ["originX",_mrkOrigin]; - } - else - { - deleteVehicle _x; - }; - } forEach units _grupo; - if (_typeVehX in FactionGet(all,"vehiclesAPCs")) then - { - _groups pushBack _grupo; - _Vwp = _groupVeh addWaypoint [_landPos, 0]; - _Vwp setWaypointBehaviour "SAFE"; - _Vwp setWaypointType "TR UNLOAD"; - _Vwp setWaypointSpeed "FULL"; - _Vwp1 = _groupVeh addWaypoint [_posDestination, 1]; - _Vwp1 setWaypointType "SAD"; - _Vwp1 setWaypointStatements ["true","if !(local this) exitWith {}; {if (side _x != side this) then {this reveal [_x,4]}} forEach allUnits"]; - _Vwp1 setWaypointBehaviour "COMBAT"; - _Vwp2 = _grupo addWaypoint [_landPos, 0]; - _Vwp2 setWaypointType "GETOUT"; - _Vwp2 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; - //_grupo setVariable ["mrkAttack",_mrkDestination]; - _Vwp synchronizeWaypoint [_Vwp2]; - _Vwp3 = _grupo addWaypoint [_posDestination, 1]; - _Vwp3 setWaypointType "SAD"; - _veh allowCrewInImmobile true; - //[_veh,"APC"] spawn A3A_fnc_inmuneConvoy; - } - else - { - (units _grupo) joinSilent _groupVeh; - deleteGroup _grupo; - _groupVeh selectLeader (units _groupVeh select 1); - _Vwp = _groupVeh addWaypoint [_landPos, 0]; - _Vwp setWaypointBehaviour "SAFE"; - _Vwp setWaypointSpeed "FULL"; - _Vwp setWaypointType "GETOUT"; - _Vwp setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; - _Vwp1 = _groupVeh addWaypoint [_posDestination, 1]; - _Vwp1 setWaypointType "SAD"; - _Vwp1 setWaypointBehaviour "COMBAT"; - //[_veh,"Boat"] spawn A3A_fnc_inmuneConvoy; - }; - }; - }; - sleep 15; - _countX = _countX + 1; - _vehPool = _vehPool select {[_x] call A3A_fnc_vehAvailable}; - }; - }; - }; - - private _nVehAir = _nVeh; - if !(_posOriginLand isEqualTo []) then { - sleep ((_posOrigin distance _posDestination)/15); // give land vehicles a head start - _nVehAir = floor (_nVeh / 2); // fill out with air vehicles - }; - _posGround = [_posOrigin select 0,_posOrigin select 1,0]; - _posOrigin set [2,300]; - - _countX = 1; - _pos = _posOrigin; - _ang = 0; - _size = [_mrkOrigin] call A3A_fnc_sizeMarker; - private _runwayTakeoff = [_mrkOrigin] call A3A_fnc_getRunwayTakeoffForAirportMarker; - if (count _runwayTakeoff > 0) then { - _pos = _runwayTakeoff select 0; - _ang = _runwayTakeoff select 1; - }; - - // Remove disabled air supports from active list - _airSupport = _airSupport select { canMove _x }; - - // Fill air supports up to half wave size, minimum +1 - private _countNewSupport = 1 max (floor (_nVeh / 2) - count _airSupport); - Debug_1("Spawning %1 new support aircraft", _countNewSupport); - - if (_countNewSupport > count _vehPoolAirSupport) then { - _countNewSupport = count _vehPoolAirSupport; - Info("Attack ran out of air supports"); - _waves = 0; - }; - - if !(canMove _uav) then - { - //75% chance to spawn a UAV, to give some variety. - if (random 1 < 0.25) exitWith {}; - _typeVehX = selectRandom (_faction get "uavsAttack"); - if (isNil "_typeVehX") exitWith {}; - _uav = createVehicle [_typeVehX, _posOrigin, [], 0, "FLY"]; - _vehiclesX pushBack _uav; - _airSupport pushBack _uav; - //[_uav,"UAV"] spawn A3A_fnc_inmuneConvoy; - [_uav,_mrkDestination,_sideX] spawn A3A_fnc_VANTinfo; - [_sideX, _uav] call A3A_fnc_createVehicleCrew; - _pilots append (crew _uav); - _groupVeh = group driver _uav; - _groups pushBack _groupVeh; - _uwp0 = _groupVeh addWayPoint [_posDestination,0]; - _uwp0 setWaypointBehaviour "AWARE"; - _uwp0 setWaypointType "SAD"; - {[_x] call A3A_fnc_NATOinit} forEach (crew _uav); - [_uav, _sideX] call A3A_fnc_AIVEHinit; - if (not(_mrkDestination in airportsX)) then {_uav removeMagazines "6Rnd_LG_scalpel"}; - Debug_1("Spawning vehicle type %1", _typeVehX); - sleep 5; - _countX = _countX + 1; - }; - - while {_countX <= _nVehAir} do - { - private _typeVehX = ""; - if (_countX <= _countNewSupport) then { - _typeVehX = selectRandom _vehPoolAirSupport; - _vehPoolAirSupport deleteAt (_vehPoolAirSupport find _typeVehX); - } - else { - if (count _vehPoolAirTransport == 0) then { - for "_i" from 1 to 10 do { _vehPoolAirTransport pushBack (selectRandom _typesPatrolHelis) }; - Info("Attack ran out of air transports"); - _waves = 0; - }; - _typeVehX = selectRandom _vehPoolAirTransport; - _vehPoolAirTransport deleteAt (_vehPoolAirTransport find _typeVehX); - }; - Debug_1("Spawning vehicle type %1", _typeVehX); - - if (true) then - { - _vehicle=[_pos, _ang + 90,_typeVehX, _sideX] call A3A_fnc_spawnVehicle; - _veh = _vehicle select 0; - if (_veh isKindOf "Plane") then { - _veh setVelocityModelSpace (velocityModelSpace _veh vectorAdd [0, 150, 50]); - }; - _vehCrew = _vehicle select 1; - _groupVeh = _vehicle select 2; - _pilots append _vehCrew; - _vehiclesX pushBack _veh; - {[_x] call A3A_fnc_NATOinit} forEach units _groupVeh; - [_veh, _sideX] call A3A_fnc_AIVEHinit; - if (not (_typeVehX in FactionGet(all,"vehiclesTransportAir"))) then - { - _airSupport pushBack _veh; - _groups pushBack _groupVeh; - _uwp0 = _groupVeh addWayPoint [_posDestination,0]; - _uwp0 setWaypointBehaviour "AWARE"; - _uwp0 setWaypointType "SAD"; - //[_veh,"Air Attack"] spawn A3A_fnc_inmuneConvoy; - } - else - { - _groups pushBack _groupVeh; - _typeGroup = [_typeVehX,_sideX] call A3A_fnc_cargoSeats; - _grupo = grpNull; - _grupo = [_posGround,_sideX, _typeGroup,true,false] call A3A_fnc_spawnGroup; - _groups pushBack _grupo; - { - _x assignAsCargo _veh; - _x moveInCargo _veh; - if (vehicle _x == _veh) then - { - _soldiers pushBack _x; - _soldiersTotal pushBack _x; - [_x] call A3A_fnc_NATOinit; - _x setVariable ["originX",_mrkOrigin]; - } - else - { - deleteVehicle _x; - }; - } forEach units _grupo; - if (!(_veh isKindOf "Helicopter") or (_mrkDestination in airportsX)) then - { - [_veh,_grupo,_mrkDestination,_mrkOrigin] spawn A3A_fnc_paradrop; - } - else - { - _landPos = _posDestination getPos [150, random 360]; - _landPos = [_landPos, 0, 550, 10, 0, 0.20, 0,[],[[0,0,0],[0,0,0]]] call BIS_fnc_findSafePos; - if !(_landPos isEqualTo [0,0,0]) then - { - _landPos set [2, 0]; - _pad = createVehicle ["Land_HelipadEmpty_F", _landPos, [], 0, "NONE"]; - _vehiclesX pushBack _pad; - _wp0 = _groupVeh addWaypoint [_landpos, 0]; - _wp0 setWaypointType "TR UNLOAD"; - _wp0 setWaypointStatements ["true", "if !(local this) exitWith {}; (vehicle this) land 'GET OUT';[vehicle this] call A3A_fnc_smokeCoverAuto"]; - _wp0 setWaypointBehaviour "CARELESS"; - _wp3 = _grupo addWaypoint [_landpos, 0]; - _wp3 setWaypointType "GETOUT"; - _wp3 setWaypointStatements ["true", "if !(local this) exitWith {}; (group this) spawn A3A_fnc_attackDrillAI"]; - _wp0 synchronizeWaypoint [_wp3]; - _wp4 = _grupo addWaypoint [_posDestination, 1]; - _wp4 setWaypointType "SAD"; - _wp4 = _grupo addWaypoint [_posDestination, 1]; - _wp2 = _groupVeh addWaypoint [_posOrigin, 1]; - _wp2 setWaypointType "MOVE"; - _wp2 setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; - [_groupVeh,1] setWaypointBehaviour "AWARE"; - } - else - { - {_x disableAI "TARGET"; _x disableAI "AUTOTARGET"} foreach units _groupVeh; - if ((_typeVehX in vehFastRope) and ((count(garrison getVariable [_mrkDestination, []])) < 10)) then - { - //_grupo setVariable ["mrkAttack",_mrkDestination]; - [_veh,_grupo,_posDestination,_posOrigin,_groupVeh] spawn A3A_fnc_fastrope; - } - else - { - [_veh,_grupo,_mrkDestination,_mrkOrigin] spawn A3A_fnc_paradrop; - } - }; - }; - }; - }; - if ((_countX > _countNewSupport) && (count _soldiers >= 10) && ([_sideX] call A3A_fnc_remUnitCount < 5)) exitWith { - Info_1("Air wave reached maximum units count after %1 vehicles", _countX); - }; - sleep 1; - _pos = [_pos, 80,_ang] call BIS_fnc_relPos; - _countX = _countX + 1; - }; - - Info_4("Spawn performed: %1 air vehicles inc. %2 supports, %3 land vehicles, %4 soldiers", _nVehAir, _countNewSupport, _nVehLand, count _soldiers); - - _planePool = (_faction get "vehiclesPlanesCAS") select {[_x] call A3A_fnc_vehAvailable}; - if (_sideX == Occupants) then - { - if (((not(_mrkDestination in outposts)) and (not(_mrkDestination in seaports)) and (_mrkOrigin != "NATO_carrier")) or A3A_hasIFA) then - { - private _reveal = [getMarkerPos _mrkDestination, _sideX] call A3A_fnc_calculateSupportCallReveal; - [getMarkerPos _mrkDestination, 4, ["MORTAR"], _sideX, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - if ((_planePool isNotEqualTo []) and (not(_mrkDestination in citiesX)) and _firstWave) then - { - sleep 60; - _rnd = if (_mrkDestination in airportsX) then {round random 4} else {round random 2}; - for "_i" from 0 to _rnd do - { - private _reveal = [getMarkerPos _mrkDestination, _sideX] call A3A_fnc_calculateSupportCallReveal; - [getMarkerPos _mrkDestination, 4, ["AIRSTRIKE"], _sideX, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - sleep 30; - }; - }; - }; - } - else - { - if (((not(_mrkDestination in resourcesX)) and (not(_mrkDestination in seaports)) and (_mrkOrigin != "CSAT_carrier")) or A3A_hasIFA) then - { - private _reveal = [getMarkerPos _mrkDestination, _sideX] call A3A_fnc_calculateSupportCallReveal; - [getMarkerPos _mrkDestination, 4, ["MORTAR"], _sideX, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - if ((_planePool isNotEqualTo []) and (_firstWave)) then - { - sleep 60; - _rnd = if (_mrkDestination in airportsX) then {if ({sidesX getVariable [_x,sideUnknown] == Invaders} count airportsX == 1) then {8} else {round random 4}} else {round random 2}; - _planePool = (_faction get "vehiclesPlanesCAS") select {[_x] call A3A_fnc_vehAvailable}; //refresh because time passed - for "_i" from 0 to _rnd do - { - if (_planePool isNotEqualTo []) then - { - private _reveal = [getMarkerPos _mrkDestination, _sideX] call A3A_fnc_calculateSupportCallReveal; - [getMarkerPos _mrkDestination, 4, ["AIRSTRIKE"], _sideX, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; - }; - }; - }; - }; - }; - - _timeX = time + 900; // wave timeout, 15 mins after the wave has finished spawning - - if (!_SDKShown) then - { - if !([true] call A3A_fnc_FIAradio) then {sleep 100}; - _SDKShown = true; - ["TaskSucceeded", ["", "Attack Destination Updated"]] remoteExec ["BIS_fnc_showNotification",teamPlayer]; - [_taskId, getMarkerPos _mrkDestination] call BIS_fnc_taskSetDestination; - }; - _solMax = round ((count _soldiers)*0.6); - _waves = _waves -1; - _firstWave = false; - if (sidesX getVariable [_mrkDestination,sideUnknown] != teamPlayer) then {_soldiers spawn A3A_fnc_remoteBattle}; - if (_sideX == Occupants) then - { - waitUntil {sleep 5; (({!([_x] call A3A_fnc_canFight)} count _soldiers) >= _solMax) or (time > _timeX) or (sidesX getVariable [_mrkDestination,sideUnknown] == Occupants) or (({[_x,_mrkDestination] call A3A_fnc_canConquer} count _soldiers) > 3*({(side _x != _sideX) and (side _x != civilian) and ([_x,_mrkDestination] call A3A_fnc_canConquer)} count allUnits))}; - if ((({[_x,_mrkDestination] call A3A_fnc_canConquer} count _soldiers) > 3*({(side _x != _sideX) and (side _x != civilian) and ([_x,_mrkDestination] call A3A_fnc_canConquer)} count allUnits)) or (sidesX getVariable [_mrkDestination,sideUnknown] == Occupants)) then - { - _waves = 0; - if ((!(sidesX getVariable [_mrkDestination,sideUnknown] == Occupants)) and !(_mrkDestination in citiesX)) then {[Occupants,_mrkDestination] remoteExec ["A3A_fnc_markerChange",2]}; - [_taskId, "rebelAttack", "FAILED", true] call A3A_fnc_taskSetState; - if (_mrkDestination in citiesX) then - { - //Impact the support on other cities in the area - //They cant defend us, switch back to NATO - { - if(_x != _mrkDestination) then - { - private _distance = (getMarkerPos _mrkDestination) distance2D (getMarkerPos _x); - private _supportChange = [0, 0]; - if(_distance < 2000) then - { - _supportChange = [10, -10]; - }; - if(_distance < 1000) then - { - _supportChange = [20, -20]; - }; - if(_distance < 500) then - { - _supportChange = [30, -30]; - }; - if(_distance < 2000) then - { - _supportChange pushBack _x; - _supportChange remoteExec ["A3A_fnc_citySupportChange",2]; - }; - }; - } forEach citiesX; - [60,-60,_mrkDestination,false] remoteExec ["A3A_fnc_citySupportChange",2]; // no pop scaling, force swing - ["TaskFailed", ["", format ["%1 joined %2",_mrkDestination, FactionGet(occ,"name")]]] remoteExec ["BIS_fnc_showNotification",teamPlayer]; - sidesX setVariable [_mrkDestination,Occupants,true]; - [Occupants, -10, 45] remoteExec ["A3A_fnc_addAggression",2]; - _mrkD = format ["Dum%1",_mrkDestination]; - _mrkD setMarkerColor colorOccupants; - garrison setVariable [_mrkDestination,[],true]; - }; - }; - sleep 10; - if (!(sidesX getVariable [_mrkDestination,sideUnknown] == Occupants)) then - { - if (sidesX getVariable [_mrkOrigin,sideUnknown] == Occupants) then - { - _killZones = killZones getVariable [_mrkOrigin,[]]; - _killZones append [_mrkDestination,_mrkDestination,_mrkDestination]; - killZones setVariable [_mrkOrigin,_killZones,true]; - }; - - if ((_waves <= 0) or (!(sidesX getVariable [_mrkOrigin,sideUnknown] == Occupants))) then - { - {_x doMove _posOrigin} forEach _soldiersTotal; - if (_waves <= 0) then {[_mrkDestination,_mrkOrigin] call A3A_fnc_minefieldAAF}; - - [_taskId, "rebelAttack", "SUCCEEDED", true] call A3A_fnc_taskSetState; - }; - }; - } - else - { - waitUntil {sleep 5; (({!([_x] call A3A_fnc_canFight)} count _soldiers) >= _solMax) or (time > _timeX) or (sidesX getVariable [_mrkDestination,sideUnknown] == Invaders) or (({[_x,_mrkDestination] call A3A_fnc_canConquer} count _soldiers) > 3*({(side _x != _sideX) and (side _x != civilian) and ([_x,_mrkDestination] call A3A_fnc_canConquer)} count allUnits))}; - if ((({[_x,_mrkDestination] call A3A_fnc_canConquer} count _soldiers) > 3*({(side _x != _sideX) and (side _x != civilian) and ([_x,_mrkDestination] call A3A_fnc_canConquer)} count allUnits)) or (sidesX getVariable [_mrkDestination,sideUnknown] == Invaders)) then - { - _waves = 0; - if (not(sidesX getVariable [_mrkDestination,sideUnknown] == Invaders)) then {[Invaders,_mrkDestination] remoteExec ["A3A_fnc_markerChange",2]}; - [_taskId, "rebelAttack", "FAILED", true] call A3A_fnc_taskSetState; - }; - sleep 10; - if (!(sidesX getVariable [_mrkDestination,sideUnknown] == Invaders)) then - { - Info_1("Wave number %1 lost",_waves); - if (sidesX getVariable [_mrkOrigin,sideUnknown] == Invaders) then - { - _killZones = killZones getVariable [_mrkOrigin,[]]; - _killZones append [_mrkDestination,_mrkDestination,_mrkDestination]; - killZones setVariable [_mrkOrigin,_killZones,true]; - }; - - if ((_waves <= 0) or (sidesX getVariable [_mrkOrigin,sideUnknown] != Invaders)) then - { - {_x doMove _posOrigin} forEach _soldiersTotal; - if (_waves <= 0) then {[_mrkDestination,_mrkOrigin] call A3A_fnc_minefieldAAF}; - [_taskId, "rebelAttack", "SUCCEEDED", true] call A3A_fnc_taskSetState; - }; - }; - }; - }; - - - - - -if (_isSDK) then - { - if (!(sidesX getVariable [_mrkDestination,sideUnknown] == teamPlayer)) then - { - [-10,theBoss] call A3A_fnc_playerScoreAdd; - } - else - { - {if (isPlayer _x) then {[10,_x] call A3A_fnc_playerScoreAdd}} forEach ([500,0,_posDestination,teamPlayer] call A3A_fnc_distanceUnits); - [5,theBoss] call A3A_fnc_playerScoreAdd; - }; - }; -Info("Reached end of winning conditions. Starting despawn"); -sleep 30; -[_taskId, "rebelAttack", 0, true] spawn A3A_fnc_taskDelete; - -[_mrkOrigin,60] call A3A_fnc_addTimeForIdle; -[3600, _originalSide] remoteExec ["A3A_fnc_timingCA", 2]; -bigAttackInProgress = false; publicVariable "bigAttackInProgress"; -//forcedSpawn = forcedSpawn - _forced; publicVariable "forcedSpawn"; -forcedSpawn = forcedSpawn - [_mrkDestination]; publicVariable "forcedSpawn"; - - -// Hand remaining aggressor units to the group despawner -{ - // order return to base if it's an air group, city attack or if it was unsuccessful - private _isPilot = vehicle leader _x isKindOf "Air"; - if (_isPilot || _mrkDestination in citiesX || sidesX getVariable [_mrkDestination,sideUnknown] != _sideX) then { - private _wp = _x addWaypoint [_posOrigin, 50]; - _wp setWaypointType "MOVE"; - _x setCurrentWaypoint _wp; - }; - [_x] spawn A3A_fnc_groupDespawner; -} forEach _groups; - -{ [_x] spawn A3A_fnc_VEHdespawner } forEach _vehiclesX; diff --git a/A3A/addons/core/functions/EventHandler/fn_addArtilleryDetectionEH.sqf b/A3A/addons/core/functions/EventHandler/fn_addArtilleryDetectionEH.sqf deleted file mode 100644 index 8a1d987782..0000000000 --- a/A3A/addons/core/functions/EventHandler/fn_addArtilleryDetectionEH.sqf +++ /dev/null @@ -1,47 +0,0 @@ -/* - Adds event handler to trigger enemy responses when rebels fire artillery/mortars - -Arguments: - The artillery vehicle object - -Environment: - Should be added on server so that it works when vehicle changes locality - -Example: - [_myMortar] remoteExec ["A3A_fnc_artilleryDetectionEH", 2]; -*/ - -params ["_artillery"]; - -_artillery addEventHandler ["Fired", { - _mortarX = _this select 0; - if (side group _mortarX != teamPlayer) exitWith {}; - _dataX = _mortarX getVariable ["detection",[position _mortarX,0]]; - _positionX = position _mortarX; - _chance = _dataX select 1; - if ((_positionX distance (_dataX select 0)) < 300) then - { - _chance = _chance + 2; - } - else - { - _chance = 0; - }; - if (random 100 < _chance) then - { - { - if !(side _x in [Occupants, Invaders]) then { continue }; - [leader _x, [_mortarX, 4]] remoteExec ["reveal", leader _x]; - } forEach allGroups; - if (_mortarX distance posHQ < 300 and !("DEF_HQ" in A3A_activeTasks)) then - { - _LeaderX = leader (gunner _mortarX); - if (!isPlayer _LeaderX or [_LeaderX] call A3A_fnc_isMember) then - { - [[],"A3A_fnc_attackHQ"] remoteExec ["A3A_fnc_scheduler",2]; - }; - }; - _chance = 0; // reduce spamming - }; - _mortarX setVariable ["detection",[_positionX,_chance]]; -}]; diff --git a/A3A/addons/core/functions/EventHandler/fn_enemyUnitDeletedEH.sqf b/A3A/addons/core/functions/EventHandler/fn_enemyUnitDeletedEH.sqf new file mode 100644 index 0000000000..7b1a912948 --- /dev/null +++ b/A3A/addons/core/functions/EventHandler/fn_enemyUnitDeletedEH.sqf @@ -0,0 +1,49 @@ +/* +Maintainer: John Jordan + Deleted EH for enemy units. Handles pool resources and garrison updates + +Scope: Server or HC +Environment: Unscheduled + +Arguments: + The object being deleted. + +Examples: + _unit addEventHandler ["Deleted", A3A_fnc_enemyUnitDeletedEH]; +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_unit"]; + +// Everything here should already be handled if unit was killed +if (!alive _unit) exitWith {}; + +private _pool = _unit getVariable ["A3A_resPool", "legacy"]; +private _side = _unit getVariable ["originalSide", sideUnknown]; +if (_side != Occupants and _side != Invaders) then { + Error_2("Wrong unit had delete handler, side %1, type %2, pool %3", _side, _unit getVariable "UnitType", _pool); +}; + +//Debug_3("Enemy delete handler called with side %1, type %2, pool %3", _side, _unit getVariable "UnitType", _pool) + +if (_unit call A3A_fnc_canFight) then +{ + // Refund if we paid for this unit in advance + if (_pool == "attack" or _pool == "defence") then { + [10, _side, _pool] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; + }; +} +else +{ + // Deplete resource pools if we haven't paid for this unit in advance + if (_pool == "legacy") then { + [-10, _side, _pool] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; + }; + + // Remove from garrison if it belongs to one + private _marker = _victim getVariable "markerX"; + if (isNil "_marker" or { sidesX getVariable [_marker, sideUnknown] != _side }) exitWith {}; + [_victim getVariable "unitType", _side, _marker,-1] remoteExec ["A3A_fnc_garrisonUpdate", 2]; +}; diff --git a/A3A/addons/core/functions/AI/fn_occupantInvaderUnitKilledEH.sqf b/A3A/addons/core/functions/EventHandler/fn_enemyUnitKilledEH.sqf similarity index 76% rename from A3A/addons/core/functions/AI/fn_occupantInvaderUnitKilledEH.sqf rename to A3A/addons/core/functions/EventHandler/fn_enemyUnitKilledEH.sqf index 0330a9b1a6..07284c49ff 100644 --- a/A3A/addons/core/functions/AI/fn_occupantInvaderUnitKilledEH.sqf +++ b/A3A/addons/core/functions/EventHandler/fn_enemyUnitKilledEH.sqf @@ -13,6 +13,13 @@ private _victimGroup = group _victim; private _victimSide = side (group _victim); [_victim] spawn A3A_fnc_postmortem; +// Deplete resource pools if we haven't paid for this unit in advance +private _pool = _victim getVariable ["A3A_resPool", "legacy"]; +if (_pool == "legacy") then { + [-10, _victimSide, "legacy"] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; +}; + + if (A3A_hasACE) then { if ((isNull _killer) || (_killer == _victim)) then @@ -21,6 +28,10 @@ if (A3A_hasACE) then }; }; +if (_victimSide == Occupants or _victimSide == Invaders) then { + [_victim, _victimGroup, _killer] spawn A3A_fnc_AIreactOnKill; +}; + if (side (group _killer) == teamPlayer) then { if (isPlayer _killer) then @@ -30,8 +41,7 @@ if (side (group _killer) == teamPlayer) then { if (_killer distance _victim < distanceSPWN) then { - [_killer,false] remoteExec ["setCaptive",0,_killer]; - _killer setCaptive false; + [_killer,false] remoteExec ["setCaptive",_killer]; }; }; _killer addRating 1000; @@ -41,8 +51,7 @@ if (side (group _killer) == teamPlayer) then { if ((_x distance _victim < 300) and (captive _x)) then { - [_x,false] remoteExec ["setCaptive",0,_x]; - _x setCaptive false; + [_x,false] remoteExec ["setCaptive",_x]; }; } forEach (call A3A_fnc_playableUnits); }; @@ -74,24 +83,13 @@ else }; }; -private _victimLocation = _victim getVariable "markerX"; -private _victimWasGarrison = true; -if (isNil "_victimLocation") then -{ - _victimLocation = _victim getVariable ["originX",""]; - _victimWasGarrison = false -}; - +private _victimLocation = _victim getVariable ["markerX", ""]; if (_victimLocation != "") then { if (sidesX getVariable [_victimLocation,sideUnknown] == _victimSide) then { [_victim getVariable "unitType",_victimSide,_victimLocation,-1] remoteExec ["A3A_fnc_garrisonUpdate",2]; - if (_victimWasGarrison) then - { - [_victimLocation,_victimSide] remoteExec ["A3A_fnc_zoneCheck",2] - }; + [_victimLocation,_victimSide] remoteExec ["A3A_fnc_zoneCheck",2] }; }; -[_victimGroup,_killer] spawn A3A_fnc_AIreactOnKill; diff --git a/A3A/addons/core/functions/EventHandler/fn_vehicleDeletedEH.sqf b/A3A/addons/core/functions/EventHandler/fn_vehicleDeletedEH.sqf new file mode 100644 index 0000000000..d0c2a3aad5 --- /dev/null +++ b/A3A/addons/core/functions/EventHandler/fn_vehicleDeletedEH.sqf @@ -0,0 +1,32 @@ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_veh"]; + +private _landingPad = _veh getVariable "LandingPad"; +if (!isNil "_landingPad") then { deleteVehicle _landingPad }; + +private _side = _veh getVariable ["ownerSide", teamPlayer]; +private _vehCost = A3A_vehicleResourceCosts getOrDefault [typeof _veh, 0]; +if (!alive _veh || (_side != Occupants && _side != Invaders) || _vehCost == 0) exitWith {}; + +// Apparently some vehicles (eg. CUP C47, su25) return an empty array for getAllHitPointsDamage +Debug_1("Calculating damage for vehicle type %1", typeof _veh); +private _vehDamage = damage _veh; +if (getAllHitPointsDamage _veh isNotEqualTo []) then { + private _allHP = getAllHitPointsDamage _veh select 2; + private _total = 0; { _total = _total + _x } forEach _allHP; + _vehDamage = _vehDamage max (_total / count _allHP); +}; + +private _pool = _veh getVariable ["A3A_resPool", "legacy"]; +Debug_5("Vehicle type %1 deleted with side %2, pool %3, cost %4, damage %5", typeof _veh, _side, _pool, _vehCost, _vehDamage); + +if (_pool == "legacy") then { + // If vehicle isn't prepaid, remove partial cost now if damaged + if (_vehDamage < 0.1) exitWith {}; + [-_vehDamage*_vehCost, _side, "legacy"] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; +} else { + // If vehicle is prepaid, refund up to 2/3 if not crippled + [(1-_vehDamage)*_vehCost*2/3, _side, _pool] remoteExecCall ["A3A_fnc_addEnemyResources", 2]; +}; diff --git a/A3A/addons/core/functions/Intel/fn_searchEncryptedIntel.sqf b/A3A/addons/core/functions/Intel/fn_searchEncryptedIntel.sqf index 61ba0ad44e..22e5fb96c6 100644 --- a/A3A/addons/core/functions/Intel/fn_searchEncryptedIntel.sqf +++ b/A3A/addons/core/functions/Intel/fn_searchEncryptedIntel.sqf @@ -58,7 +58,7 @@ private _largeAttackChance = switch (true) do { private _attack = selectRandomWeighted ["No", _noAttackChance, "Small", 0.6, "Large", _largeAttackChance]; if (_attack != "No") then { private _isLargeAttack = (_attack == "Large"); - [[_marker, _side, _isLargeAttack],"A3A_fnc_singleAttack"] remoteExec ["A3A_fnc_scheduler",2]; +// [[_marker, _side, _isLargeAttack],"A3A_fnc_singleAttack"] remoteExec ["A3A_fnc_scheduler",2]; }; //decryption proccess @@ -155,10 +155,9 @@ while {_pointSum <= _neededPoints} do { }; if (_pointSum >= _neededPoints) then { - private _intelText = ["Large", _side] call A3A_fnc_selectIntel; - [_intelText] remoteExec ["A3A_fnc_showIntel", 0]; + ["Large", _side] remoteExec ["A3A_fnc_selectIntel", 2]; { - ["Search Intel", "You managed to decifer the intel!"] call A3A_fnc_customHint; + ["Search Intel", "You managed to decipher the intel!"] call A3A_fnc_customHint; [10,_x] call A3A_fnc_playerScoreAdd; } forEach ([50,0,_intel,teamPlayer] call A3A_fnc_distanceUnits); [5, theBoss] call A3A_fnc_playerScoreAdd; diff --git a/A3A/addons/core/functions/Intel/fn_searchIntelOnDocument.sqf b/A3A/addons/core/functions/Intel/fn_searchIntelOnDocument.sqf index 0d7f6a9042..7d85a789de 100644 --- a/A3A/addons/core/functions/Intel/fn_searchIntelOnDocument.sqf +++ b/A3A/addons/core/functions/Intel/fn_searchIntelOnDocument.sqf @@ -11,8 +11,7 @@ params ["_intel"]; //Take intel from desk private _side = _intel getVariable "side"; ["Intel", "Intel documents taken."] call A3A_fnc_customHint; -private _intelText = ["Medium", _side] call A3A_fnc_selectIntel; -[_intelText] remoteExec ["A3A_fnc_showIntel", [teamPlayer, civilian]]; +["Medium", _side] remoteExec ["A3A_fnc_selectIntel", 2]; { [5,_x] call A3A_fnc_playerScoreAdd; } forEach ([50,0,_intel,teamPlayer] call A3A_fnc_distanceUnits); diff --git a/A3A/addons/core/functions/Intel/fn_searchIntelOnLaptop.sqf b/A3A/addons/core/functions/Intel/fn_searchIntelOnLaptop.sqf index fe08eac676..2a625408f2 100644 --- a/A3A/addons/core/functions/Intel/fn_searchIntelOnLaptop.sqf +++ b/A3A/addons/core/functions/Intel/fn_searchIntelOnLaptop.sqf @@ -91,7 +91,7 @@ private _attack = selectRandomWeighted ["No", _noAttackChance, "Small", 0.6, "La private _isLargeAttack = (_attack == "Large"); if(!(_attack == "No")) then { - [[_marker, _side, _isLargeAttack],"A3A_fnc_singleAttack"] remoteExec ["A3A_fnc_scheduler",2]; +// [[_marker, _side, _isLargeAttack],"A3A_fnc_singleAttack"] remoteExec ["A3A_fnc_scheduler",2]; }; _intel setVariable ["ActionNeeded", false, true]; @@ -239,8 +239,7 @@ _intel setVariable ["ActionNeeded", nil, true]; if(_pointSum >= _neededPoints) then { _intel setObjectTextureGlobal [0, "Pictures\Intel\laptop_complete.paa"]; - private _intelText = ["Large", _side] call A3A_fnc_selectIntel; - [_intelText] remoteExec ["A3A_fnc_showIntel", [teamPlayer, civilian]]; + ["Large", _side] remoteExec ["A3A_fnc_selectIntel", 2]; { [petros,"hint","You managed to download the intel!", "Search Intel"] remoteExec ["A3A_fnc_commsMP",_x]; [10,_x] call A3A_fnc_playerScoreAdd; diff --git a/A3A/addons/core/functions/Intel/fn_searchIntelOnLeader.sqf b/A3A/addons/core/functions/Intel/fn_searchIntelOnLeader.sqf index d41331085e..62e2d80de9 100644 --- a/A3A/addons/core/functions/Intel/fn_searchIntelOnLeader.sqf +++ b/A3A/addons/core/functions/Intel/fn_searchIntelOnLeader.sqf @@ -77,11 +77,8 @@ if(_caller getVariable ["intelFound", false]) then if(_hasIntel) then { ["Intel", "Search completed, intel found!"] call A3A_fnc_customHint; - private _intelText = ["Small", _side] call A3A_fnc_selectIntel; - [_intelText] remoteExec ["A3A_fnc_showIntel", [teamPlayer, civilian]]; - { - [5,_x] call A3A_fnc_playerScoreAdd; - } forEach ([50,0,_caller,teamPlayer] call A3A_fnc_distanceUnits); + ["Small", _side] remoteExec ["A3A_fnc_selectIntel", 2]; + [5, _caller] call A3A_fnc_playerScoreAdd; } else { diff --git a/A3A/addons/core/functions/Intel/fn_selectIntel.sqf b/A3A/addons/core/functions/Intel/fn_selectIntel.sqf index 8aeb69ef96..71f9fd27c9 100644 --- a/A3A/addons/core/functions/Intel/fn_selectIntel.sqf +++ b/A3A/addons/core/functions/Intel/fn_selectIntel.sqf @@ -3,6 +3,7 @@ #define TIME_LEFT 101 #define DECRYPTION_KEY 102 #define CONVOY 103 +#define DEF_RESOURCES 104 //Define results for medium intel #define ACCESS_ARMOR 200 @@ -10,6 +11,7 @@ #define ACCESS_HELI 202 #define CONVOYS 203 #define COUNTER_ATTACK 204 +#define KEY_PACK 205 //Define results for large intel #define WEAPON 300 @@ -42,9 +44,9 @@ private _text = ""; private _sideName = _faction get "name"; private _intelContent = ""; -if(_intelType == "Small") then +if (_intelType == "Small") then { - _intelContent = selectRandomWeighted [TROOPS, 0, TIME_LEFT, 0.3, DECRYPTION_KEY, 0.35, CONVOY, 0.35]; + _intelContent = selectRandomWeighted [TROOPS, 0, TIME_LEFT, 0.2, DEF_RESOURCES, 0.2, DECRYPTION_KEY, 0.6, CONVOY, 0]; switch (_intelContent) do { case (TROOPS): @@ -54,40 +56,50 @@ if(_intelType == "Small") then }; case (TIME_LEFT): { - private _nextAttack = 0; - if(_side == Occupants) then - { - _nextAttack = attackCountdownOccupants + (random 600) - 300; - } - else - { - _nextAttack = attackCountdownInvaders + (random 600) - 300; - }; - if(_nextAttack < 300) then + private _atkRes = [A3A_resourcesAttackOcc, A3A_resourcesAttackInv] select (_side == Invaders); + private _atkResRate = A3A_balanceResourceRate * A3A_enemyAttackMul / 10; // per minute + if (_side == Invaders) then { _atkResRate = _atkResRate * A3A_invaderBalanceMul }; + + private _nextAttack = (0.7 + random 0.6) * (-_atkRes / _atkResRate); + if(_nextAttack < 5) then { _text = format ["%1 attack is imminent!", _sideName]; } else { - _text = format ["%1 attack expected in %2 minutes", _sideName, round (_nextAttack / 60)]; + _text = format ["%1 attack expected in %2 minutes", _sideName, round (_nextAttack)]; + }; + }; + case (DEF_RESOURCES): + { + private _defRes = [A3A_resourcesDefenceOcc, A3A_resourcesDefenceInv] select (_side == Invaders); + private _defResCap = A3A_balanceResourceRate * 10 * ([1, A3A_invaderBalanceMul] select (_side == Invaders)); + + private _fraction = _defRes / _defResCap; + private _fmt = call { + if (_fraction > 0.75) exitWith { "%1 has plenty of defence reserves available" }; + if (_fraction > 0.50) exitWith { "%1 has moderate defence reserves available" }; + if (_fraction > 0.25) exitWith { "%1 is short on defence reserves" }; + if (_fraction > 0.00) exitWith { "%1 has almost no defence reserves left" }; + "%1 is completely out of defence reserves!"; }; + _text = format [_fmt, _sideName]; }; case (DECRYPTION_KEY): { if(_side == Occupants) then { occupantsRadioKeys = occupantsRadioKeys + 1; - publicVariable "occupantsRadioKeys"; } else { invaderRadioKeys = invaderRadioKeys + 1; - publicVariable "invaderRadioKeys"; }; - _text = format ["You found a %1 decryption key!
It allows your faction to fully decrypt the next support call.", _sideName]; + _text = format ["We found a %1 decryption key!
It allows us to fully decrypt the next support call.", _sideName]; }; case (CONVOY): { + // These aren't active at the moment private _convoyMarker = ""; [] call A3A_fnc_cleanConvoyMarker; if(_side == Occupants) then @@ -110,11 +122,27 @@ if(_intelType == "Small") then }; }; }; -if(_intelType == "Medium") then + +if (_intelType == "Medium") then { - _intelContent = selectRandomWeighted [ACCESS_AIR, 0.2, ACCESS_HELI, 0.3, ACCESS_ARMOR, 0.3, CONVOYS, 0.2, COUNTER_ATTACK, 0]; + _intelContent = selectRandomWeighted [KEY_PACK, 1, ACCESS_AIR, 0, ACCESS_HELI, 0, ACCESS_ARMOR, 0, CONVOYS, 0, COUNTER_ATTACK, 0]; switch (_intelContent) do { + case (KEY_PACK): + { + private _keyCount = round (3 + random 3); + if(_side == Occupants) then + { + occupantsRadioKeys = occupantsRadioKeys + _keyCount; + } + else + { + invaderRadioKeys = invaderRadioKeys + _keyCount; + }; + _text = format ["You found a package of %1 decryption keys!
They allow your faction to decrypt support calls.", _sideName]; + }; +/* + // These are meaningless at the moment case (ACCESS_AIR): { _text = format ["%1 currently has access to
%2", _sideName, ([_side, ACCESS_AIR] call A3A_fnc_getVehicleIntel)]; @@ -127,6 +155,7 @@ if(_intelType == "Medium") then { _text = format ["%1 currently has access to
%2", _sideName, ([_side, ACCESS_ARMOR] call A3A_fnc_getVehicleIntel)]; }; +*/ case (CONVOYS): { [] call A3A_fnc_cleanConvoyMarker; @@ -149,8 +178,10 @@ if(_intelType == "Medium") then //Not yet implemented, needs a rework of the attack script }; }; + }; -if(_intelType == "Large") then + +if (_intelType == "Large") then { if("AS" in A3A_activeTasks) then { @@ -164,7 +195,7 @@ if(_intelType == "Large") then { case (TRAITOR): { - _text = "You found data on the family of the traitor, we don't think he will do any more trouble"; + _text = "You found incriminating data on the traitor, we don't think he will cause any more trouble"; traitorIntel = true; publicVariable "traitorIntel"; }; case (WEAPON): @@ -185,4 +216,4 @@ if(_intelType == "Large") then }; }; -_text; +[_text] remoteExec ["A3A_fnc_showIntel", 0]; diff --git a/A3A/addons/core/functions/Missions/fn_AS_Traitor.sqf b/A3A/addons/core/functions/Missions/fn_AS_Traitor.sqf index 2aaf09ca6d..b43faa5758 100644 --- a/A3A/addons/core/functions/Missions/fn_AS_Traitor.sqf +++ b/A3A/addons/core/functions/Missions/fn_AS_Traitor.sqf @@ -183,7 +183,11 @@ else } else { - if (isPlayer theBoss) then + // Add some rebel HQ info to occupants. Must be done on server. + { A3A_curHQInfoOcc = A3A_curHQInfoOcc + 0.25 + random 0.5 } remoteExecCall ["call", 2]; + }; + +/* if (isPlayer theBoss) then { if !("DEF_HQ" in A3A_activeTasks) then { @@ -199,6 +203,7 @@ else }; }; }; +*/ }; traitorIntel = false; publicVariable "traitorIntel"; diff --git a/A3A/addons/core/functions/Missions/fn_DES_Heli.sqf b/A3A/addons/core/functions/Missions/fn_DES_Heli.sqf index c208e374b0..a4bfb72ea4 100644 --- a/A3A/addons/core/functions/Missions/fn_DES_Heli.sqf +++ b/A3A/addons/core/functions/Missions/fn_DES_Heli.sqf @@ -30,12 +30,13 @@ while {true} do { }; // selecting Aircraft -private _heliPool = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport") + (_faction get "vehiclesHelisAttack"); +private _heliPool = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport") + (_faction get "vehiclesHelisAttack") + (_faction get "vehiclesHelisLightAttack"); private _typeVehH = selectRandom (_heliPool select {_x isKindOf "Helicopter"}); if (isNil "_typeVehH") exitWith { ["DES"] remoteExecCall ["A3A_fnc_missionRequest",2]; Error("No aircrafts in arrays vehiclesHelisLight, vehiclesHelisTransport or vehiclesHelisAttack. Reselecting DES mission"); }; +private _isAttackHeli = _typeVehH in ((_faction get "vehiclesHelisAttack") + (_faction get "vehiclesHelisLightAttack")); //refining crash spawn position, to avoid exploding on spawn or "Armaing" during mission private _flatPos = [_posCrashOrigin, 0, 1000, 0, 0, 0.1] call BIS_fnc_findSafePos; @@ -181,7 +182,7 @@ if !(_typeVehH in (_faction get "vehiclesHelisLight")) then { _guardWP = [_guard, _posCrash, 10] call BIS_fnc_taskPatrol; Debug_1("Location: %1, Guard Squad spawned", _posCrash); - if (_typeVehH in (_faction get "vehiclesHelisAttack")) then { + if (_isAttackHeli) then { //if attack helicopter //creating transport vehicle _typeVeh = selectRandom (_faction get "vehiclesTrucks"); @@ -329,13 +330,13 @@ if ((not alive _heli) || (_heli distance (getMarkerPos respawnTeamPlayer) < 100) [1800*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]; {if (_x distance _heli < 500) then {[10*_bonus,_x] call A3A_fnc_playerScoreAdd}} forEach (allPlayers - (entities "HeadlessClient_F")); [5*_bonus,theBoss] call A3A_fnc_playerScoreAdd; - if (_typeVehH in (_faction get "vehiclesHelisAttack")) then {[600*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]}; + if (_isAttackHeli) then {[600*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]}; } else { Debug_2("%1 was successfully recovered by %2, mission failed", _heli, _sideX); [_taskId, "DES", "FAILED"] call A3A_fnc_taskSetState; [-600*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]; [-10*_bonus,theBoss] call A3A_fnc_playerScoreAdd; - if (_typeVehH in (_faction get "vehiclesHelisAttack")) then {[-600*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]}; + if (_isAttackHeli) then {[-600*_bonus, _sideX] remoteExec ["A3A_fnc_timingCA",2]}; }; Info("Downed Heli mission completed"); //////////// diff --git a/A3A/addons/core/functions/Missions/fn_LOG_Bank.sqf b/A3A/addons/core/functions/Missions/fn_LOG_Bank.sqf index 2261754b45..029febda0e 100644 --- a/A3A/addons/core/functions/Missions/fn_LOG_Bank.sqf +++ b/A3A/addons/core/functions/Missions/fn_LOG_Bank.sqf @@ -85,8 +85,8 @@ if ((dateToNumber date > _dateLimitNum) or (!alive _truckX)) then else { _countX = 120*_bonus;//120 - private _reveal = [_positionX , Invaders] call A3A_fnc_calculateSupportCallReveal; - [_positionX, 4, ["QRF"], Invaders, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; + private _reveal = [_positionX, Occupants] call A3A_fnc_calculateSupportCallReveal; + [Occupants, _truckX, _positionX, 4, _reveal] remoteExec ["A3A_fnc_requestSupport", 2]; [10*_bonus,-20*_bonus,_markerX] remoteExec ["A3A_fnc_citySupportChange",2]; ["TaskFailed", ["", format ["Bank of %1 being assaulted",_nameDest]]] remoteExec ["BIS_fnc_showNotification",Occupants]; {_friendX = _x; diff --git a/A3A/addons/core/functions/Missions/fn_RES_Refugees.sqf b/A3A/addons/core/functions/Missions/fn_RES_Refugees.sqf index f04c9b77f7..759ca72476 100644 --- a/A3A/addons/core/functions/Missions/fn_RES_Refugees.sqf +++ b/A3A/addons/core/functions/Missions/fn_RES_Refugees.sqf @@ -83,8 +83,9 @@ if (_sideX == Invaders) then if (_isDifficult) then {sleep 300} else {sleep 300 + (random 1800)}; if !(_taskId call BIS_fnc_taskCompleted) then { - private _reveal = [_positionX , Invaders] call A3A_fnc_calculateSupportCallReveal; - [getPos _house, 4, ["QRF"], Invaders, _reveal] remoteExec ["A3A_fnc_sendSupport", 2]; + // Needs rework + //private _reveal = [_positionX , Invaders] call A3A_fnc_calculateSupportCallReveal; + //[getPos _house, 4, ["QRF"], Invaders, _reveal] remoteExec ["A3A_fnc_createSupport", 2]; }; }; } diff --git a/A3A/addons/core/functions/Missions/fn_attackHQ.sqf b/A3A/addons/core/functions/Missions/fn_attackHQ.sqf deleted file mode 100644 index 55347dc45e..0000000000 --- a/A3A/addons/core/functions/Missions/fn_attackHQ.sqf +++ /dev/null @@ -1,118 +0,0 @@ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -//Mission: HQ is under attack -if (!isServer and hasInterface) exitWith{}; - -_positionX = getMarkerPos respawnTeamPlayer; - -_pilots = []; -_vehiclesX = []; -_groups = []; -_soldiers = []; - -if ({(_x distance _positionX < 500) and (typeOf _x == FactionGet(reb,"staticAA"))} count staticsToSave > 4) exitWith {}; - -_airportsX = airportsX select {(sidesX getVariable [_x,sideUnknown] != teamPlayer) and (spawner getVariable _x == 2)}; -if (count _airportsX == 0) exitWith {}; -_airportX = [_airportsX,_positionX] call BIS_fnc_nearestPosition; -_posOrigin = getMarkerPos _airportX; -_sideX = if (sidesX getVariable [_airportX,sideUnknown] == Occupants) then {Occupants} else {Invaders}; -private _faction = Faction(_sideX); - -private _taskId = "DEF_HQ" + str A3A_taskCount; -[[teamPlayer,civilian],_taskId,[format ["Enemy knows our HQ coordinates. They have sent a SpecOp Squad in order to kill %1. Intercept them and kill them. Or you may move our HQ 1Km away so they will loose track",name petros],format ["Defend %1",name petros],respawnTeamPlayer],_positionX,true,10,true,"Defend",true] call BIS_fnc_taskCreate; -[[_sideX],_taskId+"B",[format ["We know %2 HQ coordinates. We have sent a SpecOp Squad in order to kill his leader %1. Help the SpecOp team",name petros, FactionGet(reb,"name")],format ["Kill %1",name petros],respawnTeamPlayer],_positionX,true,10,true,"Attack",true] call BIS_fnc_taskCreate; -[_taskId, "DEF_HQ", "CREATED"] remoteExecCall ["A3A_fnc_taskUpdate", 2]; - -_typesVeh = _faction get "vehiclesHelisAttack"; -_typesVeh = _typesVeh select {[_x] call A3A_fnc_vehAvailable}; - -if (count _typesVeh > 0) then - { - _typeVehX = selectRandom _typesVeh; - //_pos = [_positionX, distanceSPWN * 3, random 360] call BIS_Fnc_relPos; - _vehicle=[_posOrigin, 0, _typeVehX, _sideX] call A3A_fnc_spawnVehicle; - _heli = _vehicle select 0; - _heliCrew = _vehicle select 1; - _groupHeli = _vehicle select 2; - _pilots = _pilots + _heliCrew; - _groups pushBack _groupHeli; - _vehiclesX pushBack _heli; - {[_x] call A3A_fnc_NATOinit} forEach _heliCrew; - [_heli, _sideX] call A3A_fnc_AIVEHinit; - _wp1 = _groupHeli addWaypoint [_positionX, 0]; - _wp1 setWaypointType "SAD"; - //[_heli,"Air Attack"] spawn A3A_fnc_inmuneConvoy; - sleep 30; - }; -_typesVeh = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesHelisTransport"); -if (_typesVeh isEqualTo []) then {_typesVeh = _faction get "vehiclesPlanesTransport"}; -_typeGroup = selectRandom (_faction get "groupSpecOpsRandom"); - -for "_i" from 0 to (round random 2) do - { - _typeVehX = selectRandom _typesVeh; - if (isNil "_typeVehX") exitWith {}; - //_pos = [_positionX, distanceSPWN * 3, random 360] call BIS_Fnc_relPos; - _vehicle=[_posOrigin, 0, _typeVehX, _sideX] call A3A_fnc_spawnVehicle; - _heli = _vehicle select 0; - _heliCrew = _vehicle select 1; - _groupHeli = _vehicle select 2; - _pilots = _pilots + _heliCrew; - _groups pushBack _groupHeli; - _vehiclesX pushBack _heli; - - {_x setBehaviour "CARELESS";} forEach units _groupHeli; - _groupX = [_posOrigin, _sideX, _typeGroup] call A3A_fnc_spawnGroup; - {_x assignAsCargo _heli; _x moveInCargo _heli; _soldiers pushBack _x; [_x] call A3A_fnc_NATOinit} forEach units _groupX; - _groups pushBack _groupX; - //[_heli,"Air Transport"] spawn A3A_fnc_inmuneConvoy; - if (_typeVehX isKindOf "Plane") then { - [_heli,_groupX,_positionX,_airportX] spawn A3A_fnc_paradrop; - } else { - [_heli,_groupX,_positionX,_posOrigin,_groupHeli] spawn A3A_fnc_fastrope; - }; - - - sleep 10; - }; - -waitUntil {sleep 1;({[_x] call A3A_fnc_canFight} count _soldiers < {!([_x] call A3A_fnc_canFight)} count _soldiers) or (_positionX distance getMarkerPos respawnTeamPlayer > 999) or (!alive petros)}; - -if (!alive petros) then - { - [_taskId, "DEF_HQ", "FAILED", true] call A3A_fnc_taskSetState; - } -else - { - [_taskId, "DEF_HQ", "SUCCEEDED", true] call A3A_fnc_taskSetState; - if (_positionX distance getMarkerPos respawnTeamPlayer < 999) then - { - if(_sideX == Occupants) then - { - [Occupants, 10, 60] remoteExec ["A3A_fnc_addAggression",2]; - [Invaders, 5, 60] remoteExec ["A3A_fnc_addAggression",2]; - } - else - { - [Occupants, 5, 60] remoteExec ["A3A_fnc_addAggression",2]; - [Invaders, 10, 60] remoteExec ["A3A_fnc_addAggression",2]; - }; - [0,300] remoteExec ["A3A_fnc_resourcesFIA",2]; - //[-5,5,_positionX] remoteExec ["A3A_fnc_citySupportChange",2]; - {if (isPlayer _x) then {[10,_x] call A3A_fnc_playerScoreAdd}} forEach ([500,0,_positionX,teamPlayer] call A3A_fnc_distanceUnits); - }; - }; - -[_taskId, "DEF_HQ", 1200, true] spawn A3A_fnc_taskDelete; -sleep 60; - -{ - // return to base - private _wp = _x addWaypoint [_posOrigin, 50]; - _wp setWaypointType "MOVE"; - _x setCurrentWaypoint _wp; - [_x] spawn A3A_fnc_groupDespawner; -} forEach _groups; - -{ [_x] spawn A3A_fnc_VEHdespawner } forEach _vehiclesX; diff --git a/A3A/addons/core/functions/Missions/fn_convoy.sqf b/A3A/addons/core/functions/Missions/fn_convoy.sqf index 2a6466d63f..37af803ebb 100644 --- a/A3A/addons/core/functions/Missions/fn_convoy.sqf +++ b/A3A/addons/core/functions/Missions/fn_convoy.sqf @@ -3,12 +3,11 @@ FIX_LINE_NUMBERS() //Mission: Capture/destroy the convoy if (!isServer and hasInterface) exitWith {}; -params ["_mrkDest", "_mrkOrigin", ["_convoyType", ""], ["_startDelay", -1]]; +params ["_mrkDest", "_mrkOrigin", ["_convoyType", ""], ["_resPool", "legacy"], ["_startDelay", -1]]; private _difficult = if (random 10 < tierWar) then {true} else {false}; private _sideX = if (sidesX getVariable [_mrkOrigin,sideUnknown] == Occupants) then {Occupants} else {Invaders}; private _faction = Faction(_sideX); -private _isMilitia = (_sideX == Occupants and (random 10 >= tierWar) and !_difficult); private _posSpawn = getMarkerPos _mrkOrigin; // used for spawning infantry before moving them into vehicles private _posHQ = getMarkerPos respawnTeamPlayer; @@ -22,14 +21,14 @@ private _reinforcementsX = []; // Setup start time -if (_startDelay < 0) then { _startDelay = random 5 + ([15, 5] select _difficult) }; // start delay, 5-10 or 15-20 mins real time +if (_startDelay < 0) then { _startDelay = random 5 + ([10, 5] select _difficult) }; // start delay, 5-10 or 15-20 mins real time private _startDateNum = dateToNumber date + _startDelay * timeMultiplier / (365*24*60); private _startDate = numberToDate [date select 0, _startDateNum]; private _displayTime = [_startDate] call A3A_fnc_dateToTimeString; private _nameDest = [_mrkDest] call A3A_fnc_localizar; private _nameOrigin = [_mrkOrigin] call A3A_fnc_localizar; -[_mrkOrigin, 30] call A3A_fnc_addTimeForIdle; +[_mrkOrigin, _startDelay + 5] call A3A_fnc_addTimeForIdle; // Determine convoy type from destination @@ -62,44 +61,44 @@ private _taskIcon = ""; private _taskState1 = "CREATED"; private _typeVehObj = ""; -switch (_convoyType) do +switch (tolower _convoyType) do { - case "Ammunition": + case "ammunition": { _textX = format ["A convoy from %1 is about to depart at %2. It will provide ammunition to %3. Try to intercept it. Steal or destroy that truck before it reaches it's destination.",_nameOrigin,_displayTime,_nameDest]; _taskTitle = "Ammo Convoy"; _taskIcon = "rearm"; _typeVehObj = selectRandom (_faction get "vehiclesAmmoTrucks"); }; - case "Armor": + case "armor": { _textX = format ["A convoy from %1 is about to depart at %2. It will reinforce %3 with armored vehicles. Try to intercept it. Steal or destroy that thing before it reaches it's destination.",_nameOrigin,_displayTime,_nameDest]; _taskTitle = "Armored Convoy"; _taskIcon = "Destroy"; _typeVehObj = selectRandom (_faction get "vehiclesAA"); }; - case "Prisoners": + case "prisoners": { _textX = format ["A group of POWs is being transported from %1 to %3, and it's about to depart at %2. Try to intercept it. Kill or capture the truck driver to make them join you and bring them to HQ. Alive if possible.",_nameOrigin,_displayTime,_nameDest]; _taskTitle = "Prisoner Convoy"; _taskIcon = "run"; _typeVehObj = selectRandom (_faction get "vehiclesTrucks"); }; - case "Reinforcements": + case "reinforcements": { _textX = format ["Reinforcements are being sent from %1 to %3 in a convoy, and it's about to depart at %2. Try to intercept and kill all the troops and vehicle objective.",_nameOrigin,_displayTime,_nameDest]; _taskTitle = "Reinforcements Convoy"; _taskIcon = "run"; _typeVehObj = selectRandom (_faction get "vehiclesTrucks"); }; - case "Money": + case "money": { _textX = format ["A truck with plenty of money is being moved from %1 to %3, and it's about to depart at %2. Steal that truck and bring it to HQ. Those funds will be very welcome.",_nameOrigin,_displayTime,_nameDest]; _taskTitle = "Money Convoy"; _taskIcon = "move"; _typeVehObj = "C_Van_01_box_F"; //ToDo: make this templated, no hard coded classnames }; - case "Supplies": + case "supplies": { _textX = format ["A truck with medical supplies destination %3 it's about to depart at %2 from %1. Steal that truck bring it to %3 and let people in there know it is %4 who's giving those supplies.",_nameOrigin,_displayTime,_nameDest,FactionGet(reb,"name")]; _taskTitle = "Supply Convoy"; @@ -127,9 +126,9 @@ private _route = [_posOrigin, _posDest] call A3A_fnc_findPath; _route = _route apply { _x select 0 }; // reduce to position array if (_route isEqualTo []) then { _route = [_posOrigin, _posDest] }; -private _vehPool = [_sideX, ["Air"]] call A3A_fnc_getVehiclePoolForQRFs; +private _vehPool = ([_sideX, tierWar] call A3A_fnc_getVehiclesGroundTransport) + ([_sideX, tierWar] call A3A_fnc_getVehiclesGroundSupport); private _pathState = []; // Set the scope so that state is preserved between findPosOnRoute calls - +private _resourcesSpent = 0; // Spawning worker functions @@ -151,12 +150,12 @@ private _fnc_spawnConvoyVehicle = { _veh allowDamage false; private _group = [_sideX, _veh] call A3A_fnc_createVehicleCrew; - { [_x] call A3A_fnc_NATOinit; _x allowDamage false; } forEach (units _group); + { [_x, nil, nil, _resPool] call A3A_fnc_NATOinit; _x allowDamage false; } forEach (units _group); _soldiers append (units _group); (driver _veh) stop true; deleteWaypoint [_group, 0]; // groups often start with a bogus waypoint - [_veh, _sideX] call A3A_fnc_AIVEHinit; + [_veh, _sideX, _resPool] call A3A_fnc_AIVEHinit; if (_vehType in FactionGet(all,"vehiclesArmor")) then { _veh allowCrewInImmobile true }; // move this to AIVEHinit at some point? _vehiclesX pushBack _veh; _markNames pushBack _markName; @@ -170,7 +169,7 @@ private _fnc_spawnEscortVehicle = { private _typeGroup = [_typeVehEsc, _sideX] call A3A_fnc_cargoSeats; if (count _typeGroup == 0) exitWith {}; private _groupEsc = [_posSpawn, _sideX, _typeGroup] call A3A_fnc_spawnGroup; // Unit limit? - {[_x] call A3A_fnc_NATOinit;_x assignAsCargo _veh;_x moveInCargo _veh;} forEach units _groupEsc; + {[_x, nil, nil, _resPool] call A3A_fnc_NATOinit;_x assignAsCargo _veh;_x moveInCargo _veh;} forEach units _groupEsc; _soldiers append (units _groupEsc); }; @@ -208,22 +207,21 @@ if (_convoyType == "Reinforcements") then { private _typeGroup = [_typeVehObj,_sideX] call A3A_fnc_cargoSeats; private _groupEsc = [_posSpawn,_sideX,_typeGroup] call A3A_fnc_spawnGroup; - {[_x] call A3A_fnc_NATOinit;_x assignAsCargo _vehObj;_x moveInCargo _vehObj;} forEach units _groupEsc; + {[_x, nil, nil, _resPool] call A3A_fnc_NATOinit;_x assignAsCargo _vehObj;_x moveInCargo _vehObj;} forEach units _groupEsc; _soldiers append (units _groupEsc); _reinforcementsX append (units _groupEsc); }; if ((_convoyType == "Money") or (_convoyType == "Supplies")) then { - reportedVehs pushBack _vehObj; - publicVariable "reportedVehs"; + _vehObj setVariable ["A3A_reported", true, true]; }; if (_convoyType == "Ammunition") then { [_vehObj] spawn A3A_fnc_fillLootCrate; }; -// Initial escort vehicles -private _countX = if (_difficult) then {2} else {1}; +// Initial escort vehicles, 0-1 for SP, 1-2 for 10+ +private _countX = round ((A3A_balancePlayerScale min 1.5) + random 0.5 + ([-0.75, 0.25] select _difficult)); for "_i" from 1 to _countX do { sleep 2; @@ -232,9 +230,16 @@ for "_i" from 1 to _countX do // Lead vehicle sleep 2; -private _typeVehX = selectRandom (if (_sideX == Occupants && _isMilitia) then {_faction get "vehiclesPolice"} else {_faction get "vehiclesLightArmed"}); +private _typeVehX = selectRandom (if (_sideX == Occupants && random 4 < tierWar) then {_faction get "vehiclesPolice"} else {_faction get "vehiclesLightArmed"}); private _vehLead = [_typeVehX, "Convoy Lead"] call _fnc_spawnConvoyVehicle; +// Apply convoy resource cost, if it's from attack or defence pool +if (_resPool != "legacy") then { + private _resources = 10 * count _soldiers; + { _resources = _resources + (A3A_vehicleResourceCosts getOrDefault [typeOf _x, 0]) } forEach _vehiclesX; + [-_resources, _sideX, _resPool] remoteExec ["A3A_fnc_addEnemyResources", 2]; +}; + // Remove spawn-suicide protection sleep 2; {_x allowDamage true} forEach _vehiclesX; @@ -251,6 +256,7 @@ ServerInfo("Convoy mission under way"); // This array is used to share remaining convoy vehicles between threads private _convoyVehicles = +_vehiclesX; reverse _convoyVehicles; +reverse _markNames; { (driver _x) stop false; [_x, _route, _convoyVehicles, 30, _x == _vehObj] spawn A3A_fnc_vehicleConvoyTravel; @@ -412,8 +418,6 @@ if (_convoyType == "Money") then {if (_x distance _vehObj < 500) then {[10*_bonus,_x] call A3A_fnc_playerScoreAdd}} forEach (allPlayers - (entities "HeadlessClient_F")); }; }; - reportedVehs = reportedVehs - [_vehObj]; - publicVariable "reportedVehs"; }; if (_convoyType == "Supplies") then @@ -446,8 +450,6 @@ if (_convoyType == "Supplies") then [15*_bonus,0,_mrkDest] remoteExec ["A3A_fnc_citySupportChange",2]; }; }; - reportedVehs = reportedVehs - [_vehObj]; - publicVariable "reportedVehs"; }; [_taskId, "CONVOY", _taskState] call A3A_fnc_taskSetState; diff --git a/A3A/addons/core/functions/Pathfinding/fn_addNodesNearMarkers.sqf b/A3A/addons/core/functions/Pathfinding/fn_addNodesNearMarkers.sqf new file mode 100644 index 0000000000..8e281da761 --- /dev/null +++ b/A3A/addons/core/functions/Pathfinding/fn_addNodesNearMarkers.sqf @@ -0,0 +1,124 @@ +/* + A3A_fnc_addNodesNearMarkers + Inserts suitable nodes into nav grid if markers don't have one sufficiently close + + Scope: Server or HC + Environment: Unscheduled + + Arguments: None + + Dependencies: + Marker arrays: airportsX, outposts etc. + NavGrid +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +// Generate additional nav nodes near markers +_straddlePoints = []; +{ + private _spawnPoint = server getVariable ["spawn_"+_x, _x]; + private _mpos = markerPos _spawnPoint; + + private _navCell = format ["%1/%2", floor ((_mpos#0)/1000), floor ((_mpos#1)/1000)]; + private _navPoints = A3A_navCellHM getOrDefault [_navCell, []]; + private _navPoints = _navPoints inAreaArray [_mpos, 300, 300]; + if (_navPoints isEqualTo []) then { Debug_1("%1 has no navpoints within 300m", _x); continue }; + if (_navPoints inAreaArray [_mpos, 50, 50] isNotEqualTo []) then { Debug_1("%1 already has nearby navpoints", _x); continue }; // close enough already + // if there are no navpoints then we should just mark this as unconnected somehow? + + // find nearest nav point in case that's actually the closest point + private _nearDist = 1e6; + { + private _distance = _x distance2d _mpos; + if (_nearDist > _distance) then { _nearDist = _distance }; + } forEach _navPoints; + + Debug_2("Checking %1 navPoints near %2", count _navPoints, _x); + private _nearData = false; + { + private _index = _x#2; + private _node = NavGrid#_index; + private _pos1 = _node#0; + private _relpos1 = _mpos vectorDiff _pos1; + { + private _pos2 = NavGrid#(_x#0)#0; + private _dir = _pos1 vectorFromTo _pos2; + private _relpos2 = _mpos vectorDiff _pos2; + if (_relpos1 vectorDotProduct _dir <= 0) then { continue }; // check that it's actually a straddle case + if (_relpos2 vectorDotProduct _dir >= 0) then { continue }; // wouldn't need both of these if we sorted by distance first + + private _dist = vectorMagnitude (_relpos1 vectorCrossProduct _dir); + if (_dist < _nearDist) then { + private _nearPos = _dir vectorMultiply (_relpos1 vectorDotProduct _dir) vectorAdd _pos1; + _nearDist = _dist; + _nearData = [_index, _x#0, _nearPos]; + }; + } forEach _node#3; // connected nodes [index, type, roaddist] + } forEach _navPoints; + + if (_nearData isEqualType false) then { Debug_1("No suitable pairs found near %1", _x); continue }; // no suitable pairs + if (NavGrid#(_nearData#0)#0 distance2d _nearData#2 < 30 or NavGrid#(_nearData#1)#0 distance2d _nearData#2 < 30) then { + Debug_1("New nav point near %1 would be too close", _x); continue; + }; + + Debug_3("Found straddle point for %1 at distance %2 (check %3)", _x, _nearDist, _nearData#2 distance2d _mpos); + + // first find nearest road segment to position + private _nearRoad = objNull; + private _nearDist = 1e4; + { + private _dist = _nearData#2 distance2d _x; + if (_dist < _nearDist) then { _nearDist = _dist; _nearRoad = _x }; + } forEach (_nearData#2 nearRoads 50); // is this enough? allegedly + + if (isNull _nearRoad) then { Error_2("No road on path near %1 at %2", _x, _nearData#2); continue }; + Debug_2("Road found for %1 at distance %2 from point", _x, _nearRoad distance2d _nearData#2); + + // Build a new node between the pair + private _node1 = NavGrid#(_nearData#0); + private _node2 = NavGrid#(_nearData#1); + private _newPos = getPosATL _nearRoad; + private _newNode = [_newPos, _node1#1, false, []]; + private _newIndex = count NavGrid; + private _roadType = 1; + + _straddlePoints append [_nearData#0, _nearData#1, _newIndex]; + + // relink node 1 + private _n1dist = _node1#0 distance2d _newPos; + _node1#3 apply { if (_x#0 == _nearData#1) then { _x set [0, _newIndex]; _x set [2, _n1dist]; _roadType = _x#1 } }; + _newNode#3 pushBack [_nearData#0, _roadType, _n1dist]; + + // relink node 2 + private _n2dist = _node2#0 distance2d _newPos; + _node2#3 apply { if (_x#0 == _nearData#0) then { _x set [0, _newIndex]; _x set [2, _n2dist] } }; + _newNode#3 pushBack [_nearData#1, _roadType, _n2dist]; + + NavGrid pushBack _newNode; + _newIndex call A3A_fnc_addToNavCells; + +} forEach (airportsX + resourcesX + factories + outposts + seaports + citiesX); + +/* +// Test rendering +{ + private _index = _x; + private _node = NavGrid#_index; + private _marker = createMarkerLocal [format ["navPoint_%1", _index], _node#0]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColor "ColorRed"; + { + private _nPos = NavGrid#(_x#0)#0; + private _mid = _node#0 vectorAdd _nPos vectorMultiply 0.5; + private _dir = _node#0 getDir _nPos; + private _lineMarker = createMarkerLocal [format ["np_%1_line_%2", _index, _forEachIndex], _mid]; + _lineMarker setMarkerShapeLocal "RECTANGLE"; + _lineMarker setMarkerBrushLocal "SOLID"; + _lineMarker setMarkerColorLocal "ColorBlue"; + _lineMarker setMarkerDirLocal _dir; + _lineMarker setMarkerSize [3, (_node#0 distance2d _nPos) * 0.5]; + } forEach _node#3; +} forEach _straddlePoints; +*/ \ No newline at end of file diff --git a/A3A/addons/core/functions/Pathfinding/fn_addToNavCells.sqf b/A3A/addons/core/functions/Pathfinding/fn_addToNavCells.sqf new file mode 100644 index 0000000000..6824334a83 --- /dev/null +++ b/A3A/addons/core/functions/Pathfinding/fn_addToNavCells.sqf @@ -0,0 +1,42 @@ +/* + A3A_fnc_addToNavCells + Links a nav point to a cell grid for fast lookups + +Scope: Server or HC +Environment: Init + +Arguments: + The index of the nav node + +Return Value: + None +*/ + +#define OFFSET 300 + +params ["_index"]; +NavGrid#_index#0 params ["_xpos", "_ypos"]; + +private _left = floor ((_xpos - OFFSET) / 1000); +private _right = floor ((_xpos + OFFSET) / 1000); +private _low = floor ((_ypos - OFFSET) / 1000); +private _high = floor ((_ypos + OFFSET) / 1000); + +private _navCells = [format ["%1/%2", _left, _low]]; +if (_left != _right) then { + _navCells pushBack format ["%1/%2", _right, _low]; + if (_low != _high) then { + _navCells pushBack format ["%1/%2", _left, _high]; + _navCells pushBack format ["%1/%2", _right, _high]; + }; +} else { + if (_low != _high) then { + _navCells pushBack format ["%1/%2", _left, _high]; + }; +}; + +private _navXYI = [_xpos, _ypos, _index]; +{ + private _navPoints = A3A_navCellHM getOrDefault [_x, [], true]; + _navPoints pushBack _navXYI; +} forEach _navCells; diff --git a/A3A/addons/core/functions/Pathfinding/fn_findLandSupportMarkers.sqf b/A3A/addons/core/functions/Pathfinding/fn_findLandSupportMarkers.sqf new file mode 100644 index 0000000000..34566a1a05 --- /dev/null +++ b/A3A/addons/core/functions/Pathfinding/fn_findLandSupportMarkers.sqf @@ -0,0 +1,54 @@ +/* +Maintainer: John Jordan + Generates list of outposts and airports within land support distance of nav index. Cached. + +Scope: Server or HC +Environment: Any + +Arguments: + Nav index, marker or position of location to support + +Return Value: + Marker name of outpost/airport within land support distance + Nav distance between markers + > +*/ + +params ["_target", "_lowAir"]; + +private _navIndex = if (_target isEqualType 0) then { _target } else { [_target] call A3A_fnc_getNearestNavPoint }; +if (_navIndex == -1) exitWith { [] }; + +if (isNil "A3A_landSupportMarkers") then { + A3A_landSupportMarkers = createHashMap; + A3A_outpostAirportXYI = []; // format [x, y, index into markersX] + { + private _nIndex = _x call A3A_fnc_getMarkerNavPoint; + if (_nIndex == -1) then { continue }; + private _npos = NavGrid#_nIndex#0; + A3A_outpostAirportXYI pushBack [_npos#0, _npos#1, markersX find _x]; + } forEach outposts + airportsX; +}; + +private _key = (["s", "l"] select _lowAir) + str _navIndex; +private _val = A3A_landSupportMarkers get _key; +if (!isNil "_val") exitWith { _val }; + +private _maxLandDist = distanceForLandAttack + ([1000, 2000] select _lowAir); // Allow extra crow-flies distance, because it checks real distance later +private _nearLand = A3A_outpostAirportXYI inAreaArray [NavGrid#_navIndex#0, _maxLandDist, _maxLandDist]; + +private _supportMrk = []; +{ + private _suppMrk = markersX#(_x#2); + if (spawner getVariable (_suppMrk + "_spawns") select 0 isEqualTo []) then {continue}; // any vehicle spawn places on base. huh. + private _suppNavIndex = _suppMrk call A3A_fnc_getMarkerNavPoint; + + private _navDist = [_navIndex, _suppNavIndex, _maxLandDist+500] call A3A_fnc_findNavDistance; + if (_navDist < 0) then { continue }; // no path found within range + _supportMrk pushBack [_suppMrk, _navDist]; + +} forEach _nearLand; + +A3A_landSupportMarkers set [_key, _supportMrk]; +_supportMrk; diff --git a/A3A/addons/core/functions/Pathfinding/fn_findNavDistance.sqf b/A3A/addons/core/functions/Pathfinding/fn_findNavDistance.sqf new file mode 100644 index 0000000000..d6c936a5e2 --- /dev/null +++ b/A3A/addons/core/functions/Pathfinding/fn_findNavDistance.sqf @@ -0,0 +1,60 @@ +/* + A3A_fnc_findNavDistance + Find shortest road distance between two positions or nav indices using simple A* + +Parameters: + Start marker, position or nav index. + End marker, position or nav index. + Optional: Maximum travel distance in metres. + +Returns: + Minimum Road distance from start to end, or -1 if none found or max dist exceeded +*/ + +params ["_start", "_end", ["_maxDist", 1e5]]; + +private _startIndex = if (_start isEqualType 0) then { _start } else { [_start] call A3A_fnc_getNearestNavPoint }; +private _endIndex = if (_end isEqualType 0) then { _end } else { [_end] call A3A_fnc_getNearestNavPoint }; +if (_startIndex < 0 or _endIndex < 0) exitWith { -1 }; +if (NavGrid#_startIndex#1 != NavGrid#_endIndex#1) exitWith { -1 }; // different islands, no route + +// TODO: subtract start->nav and end->nav from distance? Or fancier? + +private _endPos = NavGrid#_endIndex#0; +private _curEntry = [0, _startIndex, 0, -1]; // curGH is really (NavGrid#_startIndex#0 distance2d _endPos), but not accessed here +private _open = []; +private _touched = createHashMapFromArray [[_startIndex, true]]; +private ["_newIndex", "_newG", "_newGH"]; // optimization + +scopeName "main"; +while {!isNil "_curEntry"} do +{ + _curEntry params ["", "_curIndex", "_curG"]; // full is [curGH, curIndex, curG, curParent] + { + _newIndex = _x#0; + if (_newIndex in _touched) then { continue }; + if (_newIndex == _endIndex) exitWith { (_curG + _x#2) breakOut "main" }; // found the end, return distance + + _newG = _curG + _x#2; + _newGH = _newG + 1.2*(NavGrid#_newIndex#0 distance _endPos); + if (_newGH < _maxDist) then { _open pushBack [_newGH, _newIndex, _newG, _curIndex] }; + _touched set [_newIndex, true]; + + } forEach (NavGrid#_curIndex#3); + + _open sort true; + _curEntry = _open deleteAt 0; +}; +-1; // If we got here then pathfinding failed + + + +/* +// Walk parents to generate route +private _route = [_endRoad]; +while {count _curEntry == 4} do { + _route pushBack (_curEntry select 1); + _curEntry = _curEntry select 2; +}; +reverse _route; +*/ \ No newline at end of file diff --git a/A3A/addons/core/functions/Pathfinding/fn_getMainPositions.sqf b/A3A/addons/core/functions/Pathfinding/fn_getMainPositions.sqf deleted file mode 100644 index d076c0d758..0000000000 --- a/A3A/addons/core/functions/Pathfinding/fn_getMainPositions.sqf +++ /dev/null @@ -1,77 +0,0 @@ -/* -Author: Wurzel0701 - Gets the nearby positions a nav node should be linked to - -Arguments: - The position of the nav node - -Return Value: - > The positions the nav node should be linked to - -Scope: Server -Environment: Any -Public: No -Dependencies: - - -Example: - [_navNodePos] call A3A_fnc_getMainPositions; -*/ - -#define OFFSET 300 -params [["_pos", [-1, -1, -1], [[]]]]; - -private _allPositions = []; -private _x = _pos select 0; -private _y = _pos select 1; -private _xFloored = floor (_x / 1000); -private _yFloored = floor (_y / 1000); - -private _position = format ["%1/%2", _xFloored, _yFloored]; -_allPositions pushBack _position; - -private _xSidePos = floor ((_x + OFFSET)/1000); -private _xSideNeg = floor ((_x - OFFSET)/1000); -private _xDiff = _xFloored; -private _xHasDiff = false; -if(_xSideNeg != _xDiff || _xSidePos != _xDiff) then -{ - _xHasDiff = true; - if(_xSidePos != _xDiff) then - { - _xDiff = _xSidePos; - } - else - { - _xDiff = _xSideNeg; - }; - _position = format ["%1/%2", _xDiff, _yFloored]; - _allPositions pushBackUnique _position; -}; - -private _ySidePos = floor ((_y + OFFSET)/1000); -private _ySideNeg = floor ((_y - OFFSET)/1000); -private _yDiff = _yFloored; -private _yHasDiff = false; -if(_ySideNeg != _yDiff || _ySidePos != _yDiff) then -{ - _yHasDiff = true; - if (_ySidePos != _yDiff) then - { - _yDiff = _ySidePos; - } - else - { - _yDiff = _ySideNeg; - }; - _position = format ["%1/%2", _xFloored, _yDiff]; - _allPositions pushBackUnique _position; -}; - -if(_yHasDiff && _xHasDiff) then -{ - _position = format ["%1/%2", _xDiff, _yDiff]; - _allPositions pushBackUnique _position; -}; - -_allPositions; diff --git a/A3A/addons/core/functions/Pathfinding/fn_getMarkerNavPoint.sqf b/A3A/addons/core/functions/Pathfinding/fn_getMarkerNavPoint.sqf index bcb52714bb..367a63837c 100644 --- a/A3A/addons/core/functions/Pathfinding/fn_getMarkerNavPoint.sqf +++ b/A3A/addons/core/functions/Pathfinding/fn_getMarkerNavPoint.sqf @@ -7,18 +7,9 @@ if (isNil "A3A_markerNavPoints") then { private _navIndex = A3A_markerNavPoints get _marker; if !(isNil "_navIndex") exitWith { _navIndex }; -private _pos = if (_marker in airportsX) then -{ - // use the map-defined spawnpoint as a starting point for airfields - private _spawnPoint = server getVariable (format ["spawn_%1", _marker]); - getMarkerPos _spawnPoint; -} -else -{ - // Might be able to skip this given that getNearestNavPoint does a 300m search - private _spawnRoad = [getMarkerPos _marker] call A3A_fnc_findNearestGoodRoad; - position _spawnRoad; -}; +// Use hardcoded spawn point instead of marker center, if there is one +private _spawnPoint = server getVariable ["spawn_"+_marker, _marker]; +private _pos = markerPos _spawnPoint; _navIndex = [_pos] call A3A_fnc_getNearestNavPoint; A3A_markerNavPoints set [_marker, _navIndex]; diff --git a/A3A/addons/core/functions/Pathfinding/fn_getNearestNavPoint.sqf b/A3A/addons/core/functions/Pathfinding/fn_getNearestNavPoint.sqf index e06b620b39..49d3732dee 100644 --- a/A3A/addons/core/functions/Pathfinding/fn_getNearestNavPoint.sqf +++ b/A3A/addons/core/functions/Pathfinding/fn_getNearestNavPoint.sqf @@ -1,14 +1,14 @@ /* -Author: Wurzel0701 - Returns the index of the nearest nav node to a given position +Maintainer: John Jordan + Returns the index of the nearest nav node within 300m of a given position Arguments: - The start position from which should be searched + The start position or marker from which should be searched Return Value: Index of the nearest nav node (-1 if none found) -Scope: Server +Scope: Server or HC Environment: Any Public: Yes Dependencies: @@ -18,35 +18,31 @@ Example: [getPos player] call A3A_fnc_getNearestNavPoint; */ -params -[ - ["_pos", [-1,-1,-1], [[]]] -]; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -if(isNil "roadDataDone") exitWith -{ - Error("Road database not loaded yet, cannot get nodes"); - -1; -}; +params ["_pos"]; +if (_pos isEqualType "") exitWith { _this call A3A_fnc_getMarkerNavPoint }; -private _mainMarker = format ["%1/%2", floor ((_pos#0)/1000), floor ((_pos#1)/1000)]; -private _navPoints = missionNamespace getVariable [(format ["%1_navData", _mainMarker]), []]; +private _navCell = format ["%1/%2", floor ((_pos#0)/1000), floor ((_pos#1)/1000)]; +private _navPoints = A3A_navCellHM getOrDefault [_navCell, []]; -private _currentNearest = -1; -private _currentDistance = 0; +private _nearPoints = _navPoints inAreaArray [_pos, 75, 75]; +if (_nearPoints isEqualTo []) then { + _nearPoints = _navPoints inAreaArray [_pos, 150, 150]; + if (_nearPoints isEqualTo []) then { + _nearPoints = _navPoints inAreaArray [_pos, 300, 300]; + }; +}; +private _nearIndex = -1; +private _nearDist = 1e6; { - private _data = navGrid select _x; - private _navPos = _data select 0; - - private _distance = _navPos distance _pos; - if((_distance <= 300) && ((_currentNearest == -1) || {_currentDistance > _distance})) then - { - _currentNearest = _x; - _currentDistance = _distance; + private _dist = _x distance2d _pos; + if (_nearDist > _dist) then { + _nearIndex = _x#2; + _nearDist = _dist; }; -} forEach _navPoints; +} forEach _nearPoints; -_currentNearest; +_nearIndex; diff --git a/A3A/addons/core/functions/Pathfinding/fn_loadNavGrid.sqf b/A3A/addons/core/functions/Pathfinding/fn_loadNavGrid.sqf index accc39c989..9d5e00275d 100644 --- a/A3A/addons/core/functions/Pathfinding/fn_loadNavGrid.sqf +++ b/A3A/addons/core/functions/Pathfinding/fn_loadNavGrid.sqf @@ -50,16 +50,33 @@ if (NavGrid isEqualTo []) exitWith { Error("Nav Grid with the name format navGrid are no longer compatible! DO NOT LOAD THEM!"); }; +A3A_navCellHM = createHashMap; + { private _index = _forEachIndex; private _position = _x select 0; - if (count _position < 3) then { _position set [2, 0] }; // expand to ATL with global effect - private _mainMarkers = [_position] call A3A_fnc_getMainPositions; - { - [_index, _x] call A3A_fnc_setNavData; - } forEach _mainMarkers; + if (count _position < 3) then { _position set [2, 0] }; +/* + // Only need this if we have waypoints on bridges, which I'm not sure we do + private _road = roadAt _position; + if (isNull _road or {!(getRoadInfo _road # 8)}) exitWith { _position set [2, 0] }; + + // do we need to use lineIntersectsSurfaces? Sadly yes. + private _highpos = getPosASL _road vectorAdd [0,0,100]; + _li = lineIntersectsSurfaces [_highpos, _highpos [0,0,-200], objNull, objNull, true, 1, "ROADWAY", "VIEW"]; + if (_li isNotEqualTo []) then { _position = (_li#0#0) }; + }; +*/ + _index call A3A_fnc_addToNavCells; } forEach navGrid; roadDataDone = true; Info("Finished loading nav grid"); + +// ok, seriously consider marking every connected road instead? +// solves the nearest-node problem in the general case +// well, kinda... +// helps a lot if there's a second hashmap for second connected point +// but junction coalescing means that doesn't really work +// method: fat-ass hashmap of road->navIndex diff --git a/A3A/addons/core/functions/Pathfinding/fn_setNavData.sqf b/A3A/addons/core/functions/Pathfinding/fn_setNavData.sqf deleted file mode 100644 index 51bfa40e7d..0000000000 --- a/A3A/addons/core/functions/Pathfinding/fn_setNavData.sqf +++ /dev/null @@ -1,30 +0,0 @@ -/* -Author: Wurzel0701 - Sets the given nav node index on the given position - -Arguments: - The index of the nav node to set (Has to be an integer) - A string describing the position as given by A3A_fnc_getMainPositions - -Return Value: - - -Scope: Server -Environment: Any -Public: No -Dependencies: - - -Example: - [_navNodeIndex, _position] call A3A_fnc_setNavData; -*/ - -params -[ - ["_index", -1, [-1]], - ["_posString", "", [""]] -]; - -private _navPoints = missionNamespace getVariable [(format ["%1_navData", _posString]), []]; -_navPoints pushBack _index; -missionNamespace setVariable [(format ["%1_navData", _posString]), _navPoints]; diff --git a/A3A/addons/core/functions/REINF/fn_FIAinit.sqf b/A3A/addons/core/functions/REINF/fn_FIAinit.sqf index 5ba6422198..dd2b2580d9 100644 --- a/A3A/addons/core/functions/REINF/fn_FIAinit.sqf +++ b/A3A/addons/core/functions/REINF/fn_FIAinit.sqf @@ -10,7 +10,7 @@ _unit setVariable ["spawner",true,true]; _unit allowFleeing 0; private _typeX = _unit getVariable "unitType"; -private _skill = (0.6 / skillMult + 0.015 * skillFIA); +private _skill = (0.1 + 0.1*A3A_rebelSkillMul + 0.015 * skillFIA); _unit setSkill _skill; if (_typeX isEqualTo FactionGet(reb,"unitSL")) then { diff --git a/A3A/addons/core/functions/REINF/fn_addBombRun.sqf b/A3A/addons/core/functions/REINF/fn_addBombRun.sqf index 54ffabbbf2..65d670a392 100644 --- a/A3A/addons/core/functions/REINF/fn_addBombRun.sqf +++ b/A3A/addons/core/functions/REINF/fn_addBombRun.sqf @@ -44,7 +44,7 @@ if (_exit) exitWith {["Airstrike", "Backpack drones can't be used to increase Ai _pointsX = 2; -if (_typeX in FactionGet(all,"vehiclesHelisAttack")) then {_pointsX = 5}; +if (_typeX in (FactionGet(all,"vehiclesHelisAttack") + FactionGet(all,"vehiclesHelisLightAttack"))) then {_pointsX = 5}; if (_typeX in (OccAndInv("vehiclesPlanesCAS") + OccAndInv("vehiclesPlanesAA"))) then {_pointsX = 10}; deleteVehicle _veh; ["Airstrike", format ["Air Support increased in %1 points.",_pointsX]] call A3A_fnc_customHint; diff --git a/A3A/addons/core/functions/REINF/fn_garrisonDialog.sqf b/A3A/addons/core/functions/REINF/fn_garrisonDialog.sqf index ebc2b872d2..81c52e7a3d 100644 --- a/A3A/addons/core/functions/REINF/fn_garrisonDialog.sqf +++ b/A3A/addons/core/functions/REINF/fn_garrisonDialog.sqf @@ -46,6 +46,16 @@ if ([_positionX] call A3A_fnc_enemyNearCheck) exitWith { _nul=CreateDialog "build_menu"; #endif }; + +if (_nearX in forcedSpawn) exitWith { + ["Garrison", "You cannot manage this garrison when there's a major attack incoming."] call A3A_fnc_customHint; +#ifdef UseDoomGUI + ERROR("Disabled due to UseDoomGUI Switch.") +#else +_nul=CreateDialog "build_menu"; +#endif +}; + //if (((_nearX in outpostsFIA) and !(isOnRoad _positionX)) /*or (_nearX in citiesX)*/ or (_nearX in controlsX)) exitWith {hint "You cannot manage garrisons on this kind of zone"; _nul=CreateDialog "garrison_menu"}; _outpostFIA = if (_nearX in outpostsFIA) then {true} else {false}; _wPost = if (_outpostFIA and !(isOnRoad getMarkerPos _nearX)) then {true} else {false}; diff --git a/A3A/addons/core/functions/REINF/fn_spawnHCGroup.sqf b/A3A/addons/core/functions/REINF/fn_spawnHCGroup.sqf index 27344444ba..214ef48be1 100644 --- a/A3A/addons/core/functions/REINF/fn_spawnHCGroup.sqf +++ b/A3A/addons/core/functions/REINF/fn_spawnHCGroup.sqf @@ -63,7 +63,6 @@ private _initInfVeh = { private _initVeh = { [_vehicle, teamPlayer] call A3A_fnc_AIVEHinit; - [_vehicle] spawn A3A_fnc_vehDespawner; _group addVehicle _vehicle; _vehicle setVariable ["owner",_group,true]; driver _vehicle action ["engineOn", _vehicle]; @@ -92,13 +91,14 @@ switch _special do { (_units # (_countUnits -1)) moveInDriver _vehicle; (_units # _countUnits) moveInGunner _static; call _initVeh; + _vehicle allowCrewInImmobile true; _cost = _cost + ([FactionGet(reb,"staticAA")] call A3A_fnc_vehiclePrice); - }; case "VehicleSquad": { (_units # (_countUnits -1)) moveInDriver _vehicle; (_units # _countUnits) moveInGunner _vehicle; call _initVeh; + _vehicle allowCrewInImmobile true; }; //inf squad diff --git a/A3A/addons/core/functions/Revive/fn_handleDamageAAF.sqf b/A3A/addons/core/functions/Revive/fn_handleDamageAAF.sqf index 1f663e9fe2..2db2411759 100644 --- a/A3A/addons/core/functions/Revive/fn_handleDamageAAF.sqf +++ b/A3A/addons/core/functions/Revive/fn_handleDamageAAF.sqf @@ -63,15 +63,16 @@ private _makeUnconscious = if (isPlayer _unit) then {_unit allowDamage false}; //Make sure to pass group lead if unit is the leader - if (_unit == leader (group _unit)) then - { + if (_unit == leader (group _unit)) then + { private _index = (units (group _unit)) findIf {[_x] call A3A_fnc_canFight}; - if(_index != -1) then - { - (group _unit) selectLeader ((units (group _unit)) select _index); - } + if(_index != -1) then { + (group _unit) selectLeader ((units (group _unit)) select _index); + }; }; + [_unit, group _unit, _injurer] spawn A3A_fnc_AIreactOnKill; + [_unit,_injurer] spawn A3A_fnc_unconsciousAAF; }; @@ -105,7 +106,7 @@ if (side _injurer == teamPlayer) then else { - //Abort helping if hit too hard + //Abort helping if hit too hard if (_damage > 0.25) then { if (_unit getVariable ["helping",false]) then diff --git a/A3A/addons/core/functions/Revive/fn_unconsciousAAF.sqf b/A3A/addons/core/functions/Revive/fn_unconsciousAAF.sqf index 8b14119d71..6a629f7b24 100644 --- a/A3A/addons/core/functions/Revive/fn_unconsciousAAF.sqf +++ b/A3A/addons/core/functions/Revive/fn_unconsciousAAF.sqf @@ -7,16 +7,15 @@ private _playerNear = false; private _group = group _unit; private _side = side _group; +// This is... quite weird if ({if ((isPlayer _x) and (_x distance _unit < distanceSPWN2)) exitWith {1}} count allUnits != 0) then { _playerNear = true; [_unit,"heal"] remoteExec ["A3A_fnc_flagaction",0,_unit]; - [_unit,true] remoteExec ["setCaptive"]; _unit setCaptive true; }; -_unit setFatigue 1; -[_group,_injurer] spawn A3A_fnc_AIreactOnKill; +_unit setFatigue 1; // Doesn't do anything since Arma stamina rework? while { diff --git a/A3A/addons/core/functions/Save/fn_deleteSave.sqf b/A3A/addons/core/functions/Save/fn_deleteSave.sqf index c137eee261..69859e1329 100644 --- a/A3A/addons/core/functions/Save/fn_deleteSave.sqf +++ b/A3A/addons/core/functions/Save/fn_deleteSave.sqf @@ -35,7 +35,7 @@ private _savedPlayers = profileNamespace getVariable ["savedPlayers" + _postfix, "prestigeOPFOR", "prestigeBLUFOR", "garrison", "wurzelGarrison", "usesWurzelGarrison", "minesX", "outpostsFIA", "tasks", "idlebases", "idleassets", "killZones", "controlsSDK", "params", "attackCountdownOccupants", "attackCountdownInvaders", "prestigeNATO", "prestigeCSAT", - "savedPlayers", "testingTimerIsActive"]; + "savedPlayers", "testingTimerIsActive", "HR_Garage", "A3A_fuelAmountleftArray", "HQKnowledge", "enemyResources"]; // Remove this campaign from the save list, if present diff --git a/A3A/addons/core/functions/Save/fn_loadServer.sqf b/A3A/addons/core/functions/Save/fn_loadServer.sqf index 724ab6c7ad..6e8d495ccb 100644 --- a/A3A/addons/core/functions/Save/fn_loadServer.sqf +++ b/A3A/addons/core/functions/Save/fn_loadServer.sqf @@ -13,9 +13,6 @@ if (isServer) then { ["mrkCSAT"] call A3A_fnc_getStatVariable; ["destroyedSites"] call A3A_fnc_getStatVariable; ["minesX"] call A3A_fnc_getStatVariable; - ["attackCountdownOccupants"] call A3A_fnc_getStatVariable; - ["attackCountdownInvaders"] call A3A_fnc_getStatVariable; - ["countCA"] call A3A_fnc_getStatVariable; ["antennas"] call A3A_fnc_getStatVariable; ["hr"] call A3A_fnc_getStatVariable; ["dateX"] call A3A_fnc_getStatVariable; @@ -31,8 +28,9 @@ if (isServer) then { ["HR_Garage"] call A3A_fnc_getStatVariable; ["A3A_fuelAmountleftArray"] call A3A_fnc_getStatVariable; ["destroyedBuildings"] call A3A_fnc_getStatVariable; - ["idlebases"] call A3A_fnc_getStatVariable; - ["idleassets"] call A3A_fnc_getStatVariable; + ["enemyResources"] call A3A_fnc_getStatVariable; + ["HQKnowledge"] call A3A_fnc_getStatVariable; +// ["idlebases"] call A3A_fnc_getStatVariable; // Might bring this back at some point ["killZones"] call A3A_fnc_getStatVariable; ["controlsSDK"] call A3A_fnc_getStatVariable; ["bombRuns"] call A3A_fnc_getStatVariable; @@ -98,13 +96,6 @@ if (isServer) then { ["chopForest"] call A3A_fnc_getStatVariable; - /* - { - _buildings = nearestObjects [_x, listMilBld, 25, true]; - (_buildings select 1) setDamage 1; - } forEach destroyedBuildings; - */ - ["posHQ"] call A3A_fnc_getStatVariable; ["nextTick"] call A3A_fnc_getStatVariable; ["staticsX"] call A3A_fnc_getStatVariable; @@ -112,16 +103,9 @@ if (isServer) then { {_x setPos getMarkerPos respawnTeamPlayer} forEach ((call A3A_fnc_playableUnits) select {side _x == teamPlayer}); _sites = markersX select {sidesX getVariable [_x,sideUnknown] == teamPlayer}; - //Isn't that just tierCheck.sqf? -// tierWar = 1 + (floor (((5*({(_x in outposts) or (_x in resourcesX) or (_x in citiesX)} count _sites)) + (10*({_x in seaports} count _sites)) + (20*({_x in airportsX} count _sites)))/10)); -// if (tierWar > 10) then {tierWar = 10}; -// publicVariable "tierWar"; tierPreference = 1; publicVariable "tierPreference"; - //Updating the preferences based on war level -// [] call A3A_fnc_updatePreference; - // update war tier silently, calls updatePreference if changed [true] call A3A_fnc_tierCheck; diff --git a/A3A/addons/core/functions/Save/fn_loadStat.sqf b/A3A/addons/core/functions/Save/fn_loadStat.sqf index ca786e5ed7..48b682f7b5 100644 --- a/A3A/addons/core/functions/Save/fn_loadStat.sqf +++ b/A3A/addons/core/functions/Save/fn_loadStat.sqf @@ -36,13 +36,13 @@ private _translateMarker = { }; private _specialVarLoads = [ - "outpostsFIA","minesX","staticsX","attackCountdownOccupants","antennas","mrkNATO","mrkSDK","prestigeNATO", + "outpostsFIA","minesX","staticsX","antennas","mrkNATO","mrkSDK","prestigeNATO", "prestigeCSAT","posHQ","hr","armas","items","backpcks","ammunition","dateX","prestigeOPFOR", "prestigeBLUFOR","resourcesFIA","skillFIA","destroyedSites", - "garrison","tasks","smallCAmrk","membersX","vehInGarage","destroyedBuildings","idlebases", - "idleassets","chopForest","weather","killZones","jna_dataList","controlsSDK","mrkCSAT","nextTick", - "bombRuns","wurzelGarrison","aggressionOccupants", "aggressionInvaders", - "countCA", "attackCountdownInvaders", "testingTimerIsActive", "version", "HR_Garage","A3A_fuelAmountleftArray" + "garrison","tasks","membersX","vehInGarage","destroyedBuildings","idlebases", + "chopForest","weather","killZones","jna_dataList","controlsSDK","mrkCSAT","nextTick", + "bombRuns","wurzelGarrison","aggressionOccupants", "aggressionInvaders", "enemyResources", "HQKnowledge", + "testingTimerIsActive", "version", "HR_Garage", "A3A_fuelAmountleftArray" ]; private _varName = _this select 0; @@ -57,14 +57,9 @@ if (_varName in _specialVarLoads) then { }; A3A_saveVersion = 10000*parsenumber(_s#0) + 100*parseNumber(_s#1) + parseNumber(_s#2); }; - if (_varName == 'attackCountdownOccupants') then {attackCountdownOccupants = _varValue; publicVariable "attackCountdownOccupants"}; - if (_varName == 'attackCountdownInvaders') then {attackCountdownInvaders = _varValue; publicVariable "attackCountdownInvaders"}; - //Keep this for backwards compatiblity - if (_varName == 'countCA') then {attackCountdownOccupants = _varValue; publicVariable "attackCountdownOccupants"}; if (_varName == 'bombRuns') then {bombRuns = _varValue; publicVariable "bombRuns"}; if (_varName == 'nextTick') then {nextTick = time + _varValue}; if (_varName == 'membersX') then {membersX = +_varValue; publicVariable "membersX"}; - if (_varName == 'smallCAmrk') then {}; // Ignore. These are not persistent. if (_varName == 'mrkNATO') then {{sidesX setVariable [[_x] call _translateMarker,Occupants,true]} forEach _varValue;}; if (_varName == 'mrkCSAT') then {{sidesX setVariable [[_x] call _translateMarker,Invaders,true]} forEach _varValue;}; if (_varName == 'mrkSDK') then {{sidesX setVariable [[_x] call _translateMarker,teamPlayer,true]} forEach _varValue;}; @@ -262,16 +257,23 @@ if (_varName in _specialVarLoads) then { server setVariable [_city,_dataX,true]; }; }; + if (_varname == 'enemyResources') then { + A3A_resourcesDefenceOcc = _varValue#0; + A3A_resourcesDefenceInv = _varValue#1; + A3A_resourcesAttackOcc = _varValue#2; + A3A_resourcesAttackInv = _varValue#3; + }; + if (_varname == 'HQKnowledge') then { + A3A_curHQInfoOcc = _varValue#0; + A3A_curHQInfoInv = _varValue#1; + A3A_oldHQInfoOcc = _varValue#2; + A3A_oldHQInfoInv = _varValue#3; + }; if (_varname == 'idlebases') then { { server setVariable [(_x select 0),(_x select 1),true]; } forEach _varValue; }; - if (_varname == 'idleassets') then { - { - timer setVariable [(_x select 0),(_x select 1),true]; - } forEach _varValue; - }; if (_varname == 'killZones') then { { killZones setVariable [(_x select 0),(_x select 1),true]; @@ -332,6 +334,9 @@ if (_varName in _specialVarLoads) then { publicVariable "staticsToSave"; }; if (_varname == 'tasks') then { +/* + // These are really dangerous. Disable for now. + // Should be done after all the other init is completed if we really want it { if (_x == "rebelAttack") then { if(attackCountdownInvaders > attackCountdownOccupants) then @@ -350,6 +355,7 @@ if (_varName in _specialVarLoads) then { }; }; } forEach _varvalue; +*/ }; if(_varname == 'A3A_fuelAmountleftArray') then { diff --git a/A3A/addons/core/functions/Save/fn_saveLoop.sqf b/A3A/addons/core/functions/Save/fn_saveLoop.sqf index 2e5f927349..65a586d53f 100644 --- a/A3A/addons/core/functions/Save/fn_saveLoop.sqf +++ b/A3A/addons/core/functions/Save/fn_saveLoop.sqf @@ -42,8 +42,6 @@ Debug_1("Saving params: %1", _savedParams); private ["_garrison"]; ["version", antistasiVersion] call A3A_fnc_setStatVariable; -["attackCountdownOccupants", attackCountdownOccupants] call A3A_fnc_setStatVariable; -["attackCountdownInvaders", attackCountdownInvaders] call A3A_fnc_setStatVariable; ["gameMode", gameMode] call A3A_fnc_setStatVariable; // backwards compatibility ["difficultyX", skillMult] call A3A_fnc_setStatVariable; // backwards compatibiiity ["bombRuns", bombRuns] call A3A_fnc_setStatVariable; @@ -206,6 +204,7 @@ _arrayOutpostsFIA = []; ["outpostsFIA", _arrayOutpostsFIA] call A3A_fnc_setStatVariable; if (!isDedicated) then { + // Not currently used by loadServer due to timing bugs _typesX = []; { private _type = _x; @@ -217,6 +216,80 @@ if (!isDedicated) then { ["tasks",_typesX] call A3A_fnc_setStatVariable; }; + +// Add resources spent on active enemy units & vehicles before saving +private _resAttOcc = A3A_resourcesAttackOcc; +private _resDefOcc = A3A_resourcesDefenceOcc; +private _resAttInv = A3A_resourcesAttackInv; +private _resDefInv = A3A_resourcesDefenceInv; + +// Heavily based on deleted handler in AIVehInit +{ + private _veh = _x; + private _side = _veh getVariable ["ownerSide", teamPlayer]; + private _vehCost = A3A_vehicleResourceCosts getOrDefault [typeof _veh, 0]; + if (!alive _veh || (_side != Occupants && _side != Invaders) || _vehCost == 0) exitWith {}; + + private _vehDamage = damage _veh; + if (getAllHitPointsDamage _veh isNotEqualTo []) then { + private _allHP = getAllHitPointsDamage _veh select 2; + private _total = 0; { _total = _total + _x } forEach _allHP; + _vehDamage = _vehDamage max (_total / count _allHP); + }; + + private _pool = _veh getVariable ["A3A_resPool", "legacy"]; +// Debug_5("Vehicle type %1 deleted with side %2, pool %3, cost %4, damage %5", typeof _veh, _side, _pool, _vehCost, _vehDamage); + + if (_pool == "legacy") then { + // If vehicle isn't prepaid, remove partial cost now if damaged + if (_side == Occupants) then { + _resAttOcc = _resAttOcc - _vehDamage*_vehCost/2; + _resDefOcc = _resDefOcc - _vehDamage*_vehCost/2; + } else { + _resAttInv = _resAttInv - _vehDamage*_vehCost/2; + _resDefInv = _resDefInv - _vehDamage*_vehCost/2; + }; + } else { + // If vehicle is prepaid, refund if not crippled + // Note full refund, to reduce exploiting save-on-attack + if (_side == Occupants) then { + if (_pool == "attack") then { _resAttOcc = _resAttOcc + (1-_vehDamage)*_vehCost }; + if (_pool == "defence") then { _resDefOcc = _resDefOcc + (1-_vehDamage)*_vehCost }; + } else { + if (_pool == "attack") then { _resAttInv = _resAttInv + (1-_vehDamage)*_vehCost }; + if (_pool == "defence") then { _resDefInv = _resDefInv + (1-_vehDamage)*_vehCost }; + }; + }; +} forEach vehicles; + +{ + if !(_x call A3A_fnc_canFight) then { continue }; + private _resPool = _x getVariable ["A3A_resPool", ""]; + // TODO: potentially different values for different unit types? + if (_resPool == "defence") then { _resDefOcc = _resDefOcc + 10; continue }; + if (_resPool == "attack") then { _resAttOcc = _resAttOcc + 10 }; +} forEach units Occupants; + +{ + if !(_x call A3A_fnc_canFight) then { continue }; + private _resPool = _x getVariable ["A3A_resPool", ""]; + // TODO: potentially different values for different unit types? + if (_resPool == "defence") then { _resDefInv = _resDefInv + 10; continue }; + if (_resPool == "attack") then { _resAttInv = _resAttInv + 10 }; +} forEach units Invaders; + +// Adjust defence resources to playerScale 1 so that it doesn't get mangled on save/load +_resDefOcc = _resDefOcc / A3A_balancePlayerScale; +_resDefInv = _resDefInv / A3A_balancePlayerScale; + +// Enemy resources. Could hashmap this instead... +["enemyResources", [_resDefOcc, _resDefInv, _resAttOcc, _resAttInv]] call A3A_fnc_setStatVariable; + +// HQ knowledge +["HQKnowledge", [A3A_curHQInfoOcc, A3A_curHQInfoInv, A3A_oldHQInfoOcc, A3A_oldHQInfoInv]] call A3A_fnc_setStatVariable; + +// these are obsolete? idlebases is only used short-term now, idleassets is dead +/* _dataX = []; { _dataX pushBack [_x,server getVariable _x]; @@ -230,6 +303,7 @@ _dataX = []; } forEach (FactionGet(all,"vehiclesArmor") + FactionGet(all,"vehiclesFixedWing") + FactionGet(all,"vehiclesHelisTransport") + FactionGet(all,"vehiclesHelisAttack") + FactionGet(occ,"staticAT") + FactionGet(occ,"staticAA") + FactionGet(inv,"staticAT") + FactionGet(inv,"staticAA") + FactionGet(occ,"vehiclesGunBoats") + FactionGet(inv,"vehiclesGunBoats")); ["idleassets",_dataX] call A3A_fnc_setStatVariable; +*/ _dataX = []; { diff --git a/A3A/addons/core/functions/Supports/fn_SUP_ASF.sqf b/A3A/addons/core/functions/Supports/fn_SUP_ASF.sqf index 258be4a890..e8de0507db 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_ASF.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_ASF.sqf @@ -1,54 +1,48 @@ -params ["_side", "_timerIndex", "_supportObj", "_supportName"]; - -/* Sets up the ASF support - - Execution: HC or Server - - Scope: Internal - - Params: - _side: SIDE : The side of which the ASF should be send - _timerIndex: NUMBER : The number of the support timer - _supportObj: OBJ : The position to which the airstrike should be carried out - _supportName: STRING : The callsign of the support - - Returns: - The name of the target marker, empty string if not created +/* Sets up an ASF (air support fighter?) support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + or Initial target for the ASF, or "false" for no initial target + Esimated position of target, or center of patrol zone + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private _airport = [_supportObj, _side] call A3A_fnc_findAirportForAirstrike; -if(_airport == "") exitWith -{ - Info_1("No airport found for %1 support", _supportName); - "" -}; +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; -private _targetMarker = createMarker [format ["%1_coverage", _supportName], getPos _supportObj]; -_targetMarker setMarkerShape "ELLIPSE"; -_targetMarker setMarkerBrush "Grid"; -_targetMarker setMarkerSize [8000, 8000]; +private _airport = [_side, _targPos] call A3A_fnc_availableBasesAir; +if (isNil "_airport") exitWith { Debug_1("No airport found for %1 support", _supportName); -1; }; -if(_side == Occupants) then -{ - _targetMarker setMarkerColor colorOccupants; -}; -if(_side == Invaders) then -{ - _targetMarker setMarkerColor colorInvaders; +private _faction = Faction(_side); +private _vehType = selectRandom (_faction get "vehiclesPlanesAA"); + +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggro) }; + +private _targArray = []; +if (_target isEqualType objNull and {!isNull _target}) then { + A3A_supportStrikes pushBack [_side, "TARGET", _target, time + 1200, 1200, 200]; + _targArray = [_target, _targPos]; }; -_targetMarker setMarkerAlpha 0; -private _timerArray = if(_side == Occupants) then {occupantsASFTimer} else {invadersASFTimer}; -_timerArray set [_timerIndex, time + 5400]; +// name, side, suppType, center, radius, [target, targpos] +private _suppData = [_supportName, _side, "ASF", _targPos, 10000, _targArray]; // should radius be larger? +A3A_activeSupports pushBack _suppData; -private _setupTime = 1800 - ((tierWar - 1) * 170); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); +[_suppData, _resPool, _airport, _vehType, _delay, _reveal] spawn A3A_fnc_SUP_ASFRoutine; -[_side, _timerIndex, _sleepTime, _airport, _supportName, getPos _supportObj] spawn A3A_fnc_SUP_ASFRoutine; +[_reveal, _side, "ASF", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _result = [_targetMarker, _minSleepTime, _setupTime]; -_result; +// Vehicle cost + extra support cost for balance +(A3A_vehicleResourceCosts get _vehType) + 0; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_ASFAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_ASFAvailable.sqf index 146492ec78..819243dd03 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_ASFAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_ASFAvailable.sqf @@ -1,57 +1,20 @@ -params ["_side"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -if(tierWar < 4) exitWith {-1}; +/* Get ASF support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "ASF" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -//Make sure the vehicle are available -if (_faction get "vehiclesPlanesAA" isEqualTo []) exitWith {-1}; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -//Select a timer index and the max number of timers available -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/6)) + 1; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -//Search for a timer which allows the support to be fired -if(_side == Occupants) then -{ - if(count occupantsASFTimer < _playerAdjustment) then - { - _timerIndex = count occupantsASFTimer; - for "_i" from ((count occupantsASFTimer) + 1) to _playerAdjustment do - { - occupantsASFTimer pushBack -1; - }; - } - else - { - _timerIndex = occupantsASFTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; -if(_side == Invaders) then -{ - if(count invadersASFTimer < _playerAdjustment) then - { - _timerIndex = count invadersASFTimer; - for "_i" from ((count invadersASFTimer) + 1) to _playerAdjustment do - { - invadersASFTimer pushBack -1; - }; - } - else - { - _timerIndex = invadersASFTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; +if !(_target isKindOf "Air") exitWith { 0 }; // can't hit anything except air -_timerIndex; +1; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_ASFRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_ASFRoutine.sqf index 75ee949bad..89600c14de 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_ASFRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_ASFRoutine.sqf @@ -1,344 +1,145 @@ -params ["_side", "_timerIndex", "_sleepTime", "_airport", "_supportName", "_setupPos"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -private _faction = Faction(_side); -private _plane = selectRandom (_faction get "vehiclesPlanesAA"); -private _crewUnits = _faction get "unitPilot"; -private _timerArray = if(_side == Occupants) then {occupantsASFTimer} else {invadersASFTimer}; - -//Sleep to simulate preparetion time -while {_sleepTime > 0} do -{ - sleep 1; - _sleepTime = _sleepTime - 1; - if((spawner getVariable _airport) != 2) exitWith {}; -}; - -//No runway on this airport, use airport position -//Not sure if I should go with 150 or 1000 here, players might be only 1001 meters away -//While technically 1000 meter height is technically visible from a greater distance -//150 is more likely to be in the actual viewcone of a player -private _spawnPos = (getMarkerPos _airport); -private _strikePlane = createVehicle [_plane, _spawnPos, [], 0, "FLY"]; -_strikePlane setDir (_spawnPos getDir _setupPos); - -//Put it in the sky -_strikePlane setPosATL (_spawnPos vectorAdd [0, 0, 1000]); - -//Hide the hovering airplane from players view -_strikePlane setVelocityModelSpace [0, 150, 0]; - -private _strikeGroup = createGroup _side; -private _pilot = [_strikeGroup, _crewUnits, getPos _strikePlane] call A3A_fnc_createUnit; -_pilot moveInDriver _strikePlane; - -//_strikePlane disableAI "TARGET"; -_strikePlane disableAI "AUTOTARGET"; - - - -_strikePlane setVariable ["TimerArray", _timerArray, true]; -_strikePlane setVariable ["TimerIndex", _timerIndex, true]; -_strikePlane setVariable ["supportName", _supportName, true]; - -//Setting up the EH for support destruction -_strikePlane addEventHandler -[ - "Killed", - { - params ["_strikePlane"]; - ["TaskSucceeded", ["", "Fighter Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _timerArray = _strikePlane getVariable "TimerArray"; - private _timerIndex = _strikePlane getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 7200]; - [_strikePlane] spawn A3A_fnc_postMortem; - } -]; - -_strikePlane addEventHandler -[ - "IncomingMissile", - { - params ["_plane", "_ammo", "_vehicle"]; - if !(_vehicle isKindOf "Man") then - { - //Vehicle fired a missile against the plane, add to target list if ground, no warning for players as this is an internal decision of the pilot - if(_vehicle isKindOf "Air") then - { - private _supportName = _plane getVariable "supportName"; - [_supportName, [_vehicle, 3], 0] spawn A3A_fnc_addSupportTarget; - } - else - { - //Send support against ground based vehicles, retreat - [_vehicle, 4, ["SEAD", "CAS", "MISSILE"], side group (driver _plane), random 1] spawn A3A_fnc_sendSupport; - _plane setVariable ["Retreat", true, true]; - }; - }; - //Else case handled in client init - } -]; - -_strikePlane addEventHandler -[ - "HandleDamage", - { - params ["_plane", "_selection", "_damage", "_vehicle", "_projectile"]; - //Check if bullet, we dont care about missiles, as these are handled above - if(_projectile isKindOf "BulletCore") then - { - //Plane is getting hit by bullets, check if fired by unit or vehicle - if(!(isNull (objectParent _vehicle)) || (_vehicle isKindOf "AllVehicles")) then - { - //Getting hit by a vehicle - private _supportName = _plane getVariable "supportName"; - private _vehicle = if(_vehicle isKindOf "AllVehicles") then {_vehicle} else {objectParent _vehicle}; - if(_vehicle isKindOf "Air") then - { - //Air based dogfight - [_supportName, [_vehicle, 3], 0] spawn A3A_fnc_addSupportTarget; - } - else - { - //Send support against ground based vehicles, retreat - [_vehicle, 4, ["SEAD", "CAS", "MISSILE"], side group (driver _plane), random 1] spawn A3A_fnc_sendSupport; - _plane setVariable ["Retreat", true, true]; - }; - }; - }; - nil; //HandleDamage must return Nothing for damage to apply normally. - } -]; - -_pilot setVariable ["Plane", _strikePlane, true]; -_pilot addEventHandler -[ - "Killed", - { - params ["_unit"]; - ["TaskSucceeded", ["", "ASF crew killed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _strikePlane = _unit getVariable "Plane"; - private _timerArray = _strikePlane getVariable "TimerArray"; - private _timerIndex = _strikePlane getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 3600]; - [_unit] spawn A3A_fnc_postMortem; - } -]; -_strikeGroup deleteGroupWhenEmpty true; +/* Create and maintain air superiority fighter support -_strikePlane flyInHeight 1000; +Environment: Server, must be spawned -//Decrease time if aggro is low -private _sideAggression = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; -private _timeAlive = 600; -private _possibleKills = 3;//[_strikePlane, 0] call A3A_fnc_countMissiles; +Arguments: + Active support data, see initSupports + Resource pool of support, "attack" or "defence" + Marker name of source airport + Classname of aircraft to use + Delay time in seconds + Amount of information to reveal to rebels, 0-1 -if(_sideAggression < (30 + (random 40))) then -{ - _timeAlive = 300; - //Plane needs to have at least 6 missiles in all cases - _possibleKills = 2; -}; +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -[_strikePlane, "AA"] call A3A_fnc_setPlaneLoadout; +Debug_1("ASFRoutine called with %1", _this); -_strikePlane setVariable ["InArea", false, true]; -_strikePlane setVariable ["CurrentlyAttacking", false, true]; +params ["_suppData", "_resPool", "_airport", "_planeType", "_sleepTime", "_reveal"]; +_suppData params ["_supportName", "_side", "_suppType", "_suppCenter", "_suppRadius", "_suppTarget"]; -private _dir = (getPos _strikePlane) getDir _setupPos; -_strikePlane setDir _dir; +//Sleep to simulate preparation time +sleep _sleepTime; -/* -//Calculate loiter entry point -private _distance = _strikePlane distance2D _setupPos; -private _angle = asin (1500/_distance); -private _lenght = cos (_angle) * _distance; +private _spawnPos = (markerPos _airport); +private _plane = createVehicle [_planeType, _spawnPos, [], 0, "FLY"]; +_plane setDir (_spawnPos getDir _suppCenter); +_plane setPosATL (_spawnPos vectorAdd [0, 0, 1000]); +_plane setVelocityModelSpace [0, 150, 0]; +_plane flyInHeight 1000; +[_plane, _side, _resPool] call A3A_fnc_AIVehInit; +_plane setVariable ["SupportData", _suppData]; // for use in EHs +[_plane, "AA"] call A3A_fnc_setPlaneLoadout; -private _height = (ATLToASL _supportPos) select 2; -_height = _height + 500; +private _group = [_side, _plane] call A3A_fnc_createVehicleCrew; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach units _group; +_group deleteGroupWhenEmpty true; -private _entryPos = _setupPos getPos [_lenght, _dir + _angle]; -Debug_1("Entry Pos: %1", _entryPos); -_entryPos set [2, _height]; +_plane addEventHandler ["Killed", { + params ["_plane"]; + ["TaskSucceeded", ["", "Fighter Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; +}]; -private _areaWP = _strikeGroup addWaypoint [_entryPos, 50]; -_areaWP setWaypointCombatMode "GREEN"; -_areaWP setWaypointSpeed "FULL"; -_areaWP setWaypointType "Move"; -_areaWP setWaypointStatements ["true", "(vehicle this) setVariable ['InArea', true, true]; [3, 'ASF plane has arrived', 'ASFRoutine'] call A3A_fnc_log"]; -*/ -private _loiterWP = _strikeGroup addWaypoint [_setupPos, 2]; +while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; +private _loiterWP = _group addWaypoint [_suppCenter, 0]; _loiterWP setWaypointSpeed "NORMAL"; _loiterWP setWaypointType "Loiter"; _loiterWP setWaypointLoiterRadius 2000; +_group setCurrentWaypoint _loiterWP; +Debug_2("%1 underway from %2", _supportName, _airport); -private _time = time; -sleep 15; -_strikePlane setVariable ["InArea", true, true]; - -//waitUntil {sleep 1; !(alive _strikePlane) || (_strikePlane getVariable ["InArea", false])}; - -if !(alive _strikePlane) exitWith -{ - [_supportName, _side] call A3A_fnc_endSupport; -}; - -//_timeAlive = _timeAlive - (time - _time); +private _remTargets = 2; +private _timeout = time + 900; +private _currentlyAttacking = false; private _targetObj = objNull; -while {_timeAlive > 0} do +while {true} do { - if !(_strikePlane getVariable "CurrentlyAttacking") then - { - //Debug_1("Searching new target for %1", _supportName); - //Plane is currently not attacking a target, search for new order - private _targetList = server getVariable [format ["%1_targets", _supportName], []]; - if (count _targetList > 0) then - { - //New target active, read in - private _target = _targetList deleteAt 0; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - - Debug_2("Next target for %2 is %1", _target, _supportName); - - //Parse targets - private _targetParams = _target select 0; - private _reveal = _target select 1; - - _targetObj = _targetParams select 0; - private _precision = _targetParams select 1; - private _targetPos = getPos _targetObj; - - _strikeGroup reveal [_targetObj, _precision]; - _strikePlane flyInHeight 250; - - //Show target to players if change is high enough - private _textMarker = createMarker [format ["%1_text", _supportName], getPos _targetObj]; - _textMarker setMarkerShape "ICON"; - _textMarker setMarkerType "mil_objective"; - _textMarker setMarkerText "ASF Target"; - - if(_side == Occupants) then - { - _textMarker setMarkerColor colorOccupants; - } - else - { - _textMarker setMarkerColor colorInvaders; - }; - _textMarker setMarkerAlpha 0; - - [_textMarker, _targetObj, _strikePlane] spawn - { - params ["_textMarker", "_targetObj", "_strikePlane"]; - while {!(isNull _targetObj) && (alive _targetObj)} do - { - _textMarker setMarkerPos (getPos _targetObj); - - if((isNull _strikePlane) || !(alive _strikePlane)) exitWith {}; + //Plane somehow destroyed or disabled + if !(canFire _plane && side _plane == _side) exitWith { + Info_1("%1 has been destroyed or disabled, aborting routine", _supportName); + }; - sleep 0.5; - }; - deleteMarker _textMarker; - }; + if (!_currentlyAttacking && _remTargets <= 0) exitWith { + Info_1("%1 has run out of targets, aborting routine", _supportName); + }; - [_reveal, getPos _targetObj, _side, "ASF", "", _textMarker] spawn A3A_fnc_showInterceptedSupportCall; - _strikePlane setVariable ["CurrentlyAttacking", true, true]; + if (time > _timeout) exitWith { + Info_1("%1 has run out of time, aborting routine", _supportName); + }; - private _attackWP = _strikeGroup addWaypoint [_targetPos, 3]; - _attackWP setWaypointType "DESTROY"; - _attackWP waypointAttachObject _targetObj; - _attackWP setWaypointSpeed "FULL"; - _strikeGroup setCurrentWaypoint _attackWP; + if (!_currentlyAttacking) then + { + if (_suppTarget isEqualTo []) exitWith {}; - _strikeGroup setBehaviour "COMBAT"; - _strikeGroup setCombatMode "RED"; + _targetObj = _suppTarget select 0; + if !(alive _targetObj) exitWith { + _suppTarget resize 0; + Debug_1("%1 skips target, as it is already dead", _supportName); }; + Debug_2("Next target for %2 is %1", _suppTarget, _supportName); + _timeout = _timeout + 300; // make sure it has some time to kill + _remTargets = _remTargets - 1; + + private _attackWP = _group addWaypoint [_targetObj, 0]; + _attackWP setWaypointType "DESTROY"; + _attackWP waypointAttachVehicle _targetObj; +// _attackWP setWaypointSpeed "FULL"; + _group setCurrentWaypoint _attackWP; + + _group reveal [_targetObj, 1.5]; // do we need to add knowledge level to target list? Only used here? + _group setBehaviour "COMBAT"; + _group setCombatMode "RED"; + _plane flyInHeight -1; // experimental + _currentlyAttacking = true; + + [_reveal, getPos _targetObj, _side, "ASF", _targetObj, 60] spawn A3A_fnc_showInterceptedSupportCall; } else { - if(isNull _targetObj || {!(alive _targetObj) || {(_targetObj distance2D _setupPos) > 8000}}) then + // TODO: better evasion mechanics? + if (!alive _targetObj or {_targetObj distance2D _suppCenter > _suppRadius and _targetObj distance2D _plane > 3000}) then { - if(isNull _targetObj || {!(alive _targetObj)}) then - { - _possibleKills = _possibleKills - 1; - Debug_1("Target destroyed, %1 returns to cycle mode", _supportName); - } - else - { - Debug_1("Target evaded, %1 returns to cycle mode", _supportName) - }; - - //Target destroyed - _strikePlane setVariable ["CurrentlyAttacking", false, true]; + _remTargets = _remTargets + 1; + _suppTarget resize 0; // clear target array so support routines can add the next - for "_i" from count waypoints _strikeGroup - 1 to 0 step -1 do - { - deleteWaypoint [_strikeGroup, _i]; + if !(alive _targetObj) then { + Debug_1("Target destroyed, %1 returns to cycle mode", _supportName); + } else { + Debug_1("Target evaded, %1 returns to cycle mode", _supportName); }; - private _loiterWP = _strikeGroup addWaypoint [_setupPos, 2]; - _loiterWP setWaypointSpeed "NORMAL"; - _loiterWP setWaypointType "Loiter"; - _loiterWP setWaypointLoiterRadius 2000; - _strikeGroup setCurrentWaypoint _loiterWP; + deleteWaypoint [_group, 1]; + _group setCurrentWaypoint _loiterWP; - _strikeGroup setBehaviour "AWARE"; - _strikeGroup setCombatMode "GREEN"; - - _strikePlane flyInHeight 1000; + //_plane flyInHeight 1000; + _currentlyAttacking = false; + _timeout = _timeout - 300; }; }; - //Plane somehow destroyed - if - ( - !(alive _strikePlane) || - {({alive _x} count (units _strikeGroup)) == 0} - ) exitWith - { - Info_1("%1 has been destroyed or crew killed, aborting routine", _supportName); - [_side, 20, 45] remoteExec ["A3A_fnc_addAggression", 2]; - }; - - //No missiles left - if (!(_strikePlane getVariable "CurrentlyAttacking") && (_possibleKills <= 0)) exitWith - { - Info_1("%1 has no more missiles left to fire, aborting routine", _supportName); - }; - - //Retreating - if(_strikePlane getVariable ["Retreat", false]) exitWith - { - Info_1("%1 met heavy resistance, retreating", _supportName); - }; - sleep 5; - _timeAlive = _timeAlive - 5; }; +_suppData set [4, 0]; // Set activesupport radius to 0, enables cleanup + +[_group] spawn A3A_fnc_groupDespawner; +[_plane] spawn A3A_fnc_vehDespawner; + //Have the plane fly back home -if (alive _strikePlane && {!(isNull (driver _strikePlane)) && {[driver _strikePlane] call A3A_fnc_canFight}}) then +if (canMove _plane && {[driver _plane] call A3A_fnc_canFight}) then { - for "_i" from (count waypoints _strikeGroup - 1) to 0 step -1 do - { - deleteWaypoint [_strikeGroup, _i]; - }; - private _wpBase = _strikeGroup addWaypoint [getMarkerPos _airport, 0]; - _wpBase setWaypointType "MOVE"; + while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; + private _wpBase = _group addWaypoint [_spawnPos, 0]; + _wpBase setWaypointSpeed "NORMAL"; _wpBase setWaypointBehaviour "CARELESS"; - _wpBase setWaypointSpeed "FULL"; - _wpBase setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; - _strikeGroup setCurrentWaypoint _wpBase; + _group setCurrentWaypoint _wpBase; - waitUntil {sleep 0.5;_strikePlane distance2D (getMarkerPos _airport) < 100}; - { - deleteVehicle _x; - } forEach (units _strikeGroup); - deleteVehicle _strikePlane; + private _timeout = time + (getPos _plane distance2d _spawnPos) / 20; + waitUntil { sleep 2; (currentWaypoint _group != 0) or (time > _timeout) }; + if (time > _timeout) exitWith {}; + { deleteVehicle _x } forEach (units _group); + deleteVehicle _plane; }; - -//Deleting all the support data here -[_supportName, _side] call A3A_fnc_endSupport; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_CAS.sqf b/A3A/addons/core/functions/Supports/fn_SUP_CAS.sqf index 4ae4d25a6e..f7fa990c52 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_CAS.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_CAS.sqf @@ -1,54 +1,47 @@ -params ["_side", "_timerIndex", "_supportObj", "_supportName"]; - -/* Sets up the CAS support - - Execution: HC or Server - - Scope: Internal - - Params: - _side: SIDE : The side of which the CAS should be send - _timerIndex: NUMBER : The number of the support timer - _supportObj: OBJ : The position to which the airstrike should be carried out - _supportName: STRING : The callsign of the support - - Returns: - The name of the target marker, empty string if not created +/* Sets up a CAS (close air support) support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + Initial CAS target. "false" creates with no initial target + Estimated position of target, or center of target zone + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private _airport = [_supportObj, _side] call A3A_fnc_findAirportForAirstrike; -if(_airport == "") exitWith -{ - Info_1("No airport found for %1 support", _supportName); - "" -}; +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; -private _timerArray = if(_side == Occupants) then {occupantsCASTimer} else {invadersCASTimer}; -_timerArray set [_timerIndex, time + 1800]; +private _airport = [_side, _targPos] call A3A_fnc_availableBasesAir; +if (isNil "_airport") exitWith { Debug_1("No airport found for %1 support", _supportName); -1; }; -private _targetMarker = createMarker [format ["%1_coverage", _supportName], getPos _supportObj]; -_targetMarker setMarkerShape "ELLIPSE"; -_targetMarker setMarkerBrush "Grid"; -_targetMarker setMarkerSize [3000, 3000]; +private _faction = Faction(_side); +private _vehType = selectRandom (_faction get "vehiclesPlanesCAS"); -if(_side == Occupants) then -{ - _targetMarker setMarkerColor colorOccupants; -}; -if(_side == Invaders) then -{ - _targetMarker setMarkerColor colorInvaders; +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggro) }; + +private _targArray = []; +if (_target isEqualType objNull and {!isNull _target}) then { + A3A_supportStrikes pushBack [_side, "TARGET", _target, time + 1200, 1200, 200]; + _targArray = [_target, _targPos]; }; -_targetMarker setMarkerAlpha 0; -private _setupTime = 1294 - ((tierWar - 1) * 66); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); +// name, side, suppType, center, radius, [target, targpos] +private _suppData = [_supportName, _side, "CAS", _targPos, 3000, _targArray]; // should radius be larger? +A3A_activeSupports pushBack _suppData; +[_suppData, _resPool, _airport, _vehType, _delay, _reveal] spawn A3A_fnc_SUP_CASRoutine; -[_side, _sleepTime, _timerIndex, _airport, _supportName, getPos _supportObj] spawn A3A_fnc_SUP_CASRoutine; +[_reveal, _side, "CAS", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _result = [_targetMarker, _minSleepTime, _setupTime]; -_result; +// Vehicle cost + extra support cost for balance +(A3A_vehicleResourceCosts get _vehType) + 100; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_CASAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_CASAvailable.sqf index 7af1c763f6..7df959afd7 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_CASAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_CASAvailable.sqf @@ -1,58 +1,24 @@ -params ["_side"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -if(tierWar < 5) exitWith {-1}; +/* Get CAS support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "CAS" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -//Make sure the vehicle are available -if (_faction get "vehiclesPlanesCAS" isEqualTo []) exitWith {-1}; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() +params ["_target", "_side", "_maxSpend", "_availTypes"]; -//Select a timer index and the max number of timers available -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/4)) + 1; +if (_target isKindOf "Air") exitWith { 0 }; // can't hit air -//Search for a timer which allows the support to be fired -if(_side == Occupants) then -{ - if(count occupantsCASTimer < _playerAdjustment) then - { - _timerIndex = count occupantsCASTimer; - for "_i" from ((count occupantsCASTimer) + 1) to _playerAdjustment do - { - occupantsCASTimer pushBack -1; - }; - } - else - { - _timerIndex = occupantsCASTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; -if(_side == Invaders) then -{ - if(count invadersCASTimer < _playerAdjustment) then - { - _timerIndex = count invadersCASTimer; - for "_i" from ((count invadersCASTimer) + 1) to _playerAdjustment do - { - invadersCASTimer pushBack -1; - }; - } - else - { - _timerIndex = invadersCASTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; +if (_target isKindOf "Man") exitWith { 0.001 }; // Don't spawn to attack meatsacks, but re-use active supports -_timerIndex; +// Against vehicles and statics, use more frequently against more dangerous stuff +private _threat = A3A_groundVehicleThreat getOrDefault [typeOf _target, 0]; +0.001 + _threat / 80; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_CASRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_CASRoutine.sqf index 3e8efb2208..89a74d6fd0 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_CASRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_CASRoutine.sqf @@ -1,621 +1,377 @@ -params ["_side", "_sleepTime", "_timerIndex", "_airport", "_supportName", "_setupPos"]; +/* Create and maintain close air support bomber + +Environment: Server, must be spawned + +Arguments: + Active support data, see initSupports + Resource pool of support, "attack" or "defence" + Marker name of source airport + Classname of aircraft to use + Delay time in seconds + Amount of information to reveal to rebels, 0-1 + +*/ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private _faction = Faction(_side); -private _plane = selectRandom (_faction get "vehiclesPlanesCAS"); -private _crewUnits = _faction get "unitPilot"; +Debug_1("CASRoutine called with %1", _this); -//Sleep to simulate preparetion time -while {_sleepTime > 0} do -{ - sleep 1; - _sleepTime = _sleepTime - 1; - if((spawner getVariable _airport) != 2) exitWith {}; -}; +params ["_suppData", "_resPool", "_airport", "_planeType", "_sleepTime", "_reveal"]; +_suppData params ["_supportName", "_side", "_suppType", "_suppCenter", "_suppRadius", "_suppTarget"]; -//No runway on this airport, use airport position -//Not sure if I should go with 150 or 1000 here, players might be only 1001 meters away -//While technically 1000 meter height is technically visible from a greater distance -//150 is more likely to be in the actual viewcone of a player -private _spawnPos = (getMarkerPos _airport); -private _strikePlane = createVehicle [_plane, _spawnPos, [], 0, "FLY"]; -_strikePlane setDir (_spawnPos getDir _setupPos); - -//Put it in the sky -_strikePlane setPosATL (_spawnPos vectorAdd [0, 0, 1000]); -_strikePlane setVelocityModelSpace [0, 150, 0]; - -private _strikeGroup = createGroup _side; -private _pilot = [_strikeGroup, _crewUnits, getPos _strikePlane] call A3A_fnc_createUnit; -_pilot moveInDriver _strikePlane; - -_strikePlane disableAI "AUTOTARGET"; - -private _timerArray = if(_side == Occupants) then {occupantsCASTimer} else {invadersCASTimer}; -_strikePlane setVariable ["TimerArray", _timerArray, true]; -_strikePlane setVariable ["TimerIndex", _timerIndex, true]; -_strikePlane setVariable ["supportName", _supportName, true]; - -//Setting up the EH for support destruction -_strikePlane addEventHandler -[ - "Killed", - { - params ["_strikePlane"]; - ["TaskSucceeded", ["", "CAS Plane Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _timerArray = _strikePlane getVariable "TimerArray"; - private _timerIndex = _strikePlane getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 3600]; - [_strikePlane] spawn A3A_fnc_postMortem; - } -]; - -_strikePlane addEventHandler -[ - "IncomingMissile", - { - //Missile launch against this plane detected, attack if vehicle, send other support if manpads - params ["_plane", "_ammo", "_vehicle"]; - if !(_vehicle isKindOf "Man") then - { - //Vehicle fired a missile against the plane, add to target list if ground, no warning for players as this is an internal decision of the pilot - if(_vehicle isKindOf "Air") then - { - [group driver _plane, ["ASF", "SAM"], _vehicle] spawn A3A_fnc_callForSupport; - _plane setVariable ["Retreat", true, true]; - } - else - { - private _supportName = _plane getVariable "supportName"; - [_supportName, [_vehicle, 3], 0] spawn A3A_fnc_addSupportTarget; - }; - }; - } -]; +//Sleep to simulate preparation time +sleep _sleepTime; -_strikePlane addEventHandler -[ - "HandleDamage", - { - params ["_plane", "_selection", "_damage", "_vehicle", "_projectile"]; - //Check if bullet, we dont care about missiles, as these are handled above - if(_projectile isKindOf "BulletCore") then - { - //Plane is getting hit by bullets, check if fired by unit or vehicle - if(!(isNull (objectParent _vehicle)) || (_vehicle isKindOf "AllVehicles")) then - { - //Getting hit by a vehicle - private _supportName = _plane getVariable "supportName"; - private _vehicle = if(_vehicle isKindOf "AllVehicles") then {_vehicle} else {objectParent _vehicle}; - if(_vehicle isKindOf "Air") then - { - //Vehicle is a plane or attack heli (or a lucky chopper), retreat, as no AA weapons on board - [group driver _plane, ["ASF", "SAM"], _vehicle] spawn A3A_fnc_callForSupport; - _plane setVariable ["Retreat", true, true]; - } - else - { - //Vehicle is a ground based AA, add to attack list - [_supportName, [_vehicle, 3], 0] spawn A3A_fnc_addSupportTarget; - }; - }; - }; - nil; //HandleDamage must return Nothing for damage to apply normally. - } -]; - -_pilot setVariable ["Plane", _strikePlane, true]; -_pilot addEventHandler -[ - "Killed", - { - params ["_unit"]; - ["TaskSucceeded", ["", "CAS crew killed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _strikePlane = _unit getVariable "Plane"; - private _timerArray = _strikePlane getVariable "TimerArray"; - private _timerIndex = _strikePlane getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 1800]; - [_unit] spawn A3A_fnc_postMortem; - } -]; -_strikeGroup deleteGroupWhenEmpty true; -_strikePlane flyInHeight 500; - -//Decrease time if aggro is low -private _sideAggression = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; -private _timeAlive = 1200; -private _confirmedKills = 4;//[_strikePlane, 0] call A3A_fnc_countMissiles; -private _allowHeavyWeapon = true; - -if(_sideAggression < (30 + (random 40))) then -{ - _timeAlive = 600; - //Plane needs to have at least 6 missiles in all cases - _confirmedKills = 2; - _allowHeavyWeapon = false; -}; +private _spawnPos = (markerPos _airport); +private _plane = createVehicle [_planeType, _spawnPos, [], 0, "FLY"]; +_plane setDir (_spawnPos getDir _suppCenter); +_plane setPosATL (_spawnPos vectorAdd [0, 0, 500]); +_plane setVelocityModelSpace [0, 150, 0]; +_plane flyInHeight 500; +[_plane, _side, _resPool] call A3A_fnc_AIVehInit; +[_plane, "CAS"] call A3A_fnc_setPlaneLoadout; + +private _group = [_side, _plane] call A3A_fnc_createVehicleCrew; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach units _group; +_group deleteGroupWhenEmpty true; +_group setBehaviourStrong "CARELESS"; + +_plane addEventHandler ["Killed", { + params ["_plane"]; + ["TaskSucceeded", ["", "CAS Plane Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; +}]; -[_strikePlane, "CAS"] call A3A_fnc_setPlaneLoadout; //Get available ammo count of all allowed propelled weapons -private _ammoCount = []; -private _loadout = _strikePlane getVariable "loadout"; -private _weapons = (_strikePlane getVariable "rocketLauncher") + (_strikePlane getVariable "missileLauncher"); +private _ammoHM = createHashMap; +private _loadout = _plane getVariable "loadout"; +private _weapons = (_plane getVariable "rocketLauncher") + (_plane getVariable "missileLauncher"); { private _weapon = _x; private _magazines = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines"); private _ammo = 0; { - if(_x in _magazines) then - { + if(_x in _magazines) then { _ammo = _ammo + getNumber (configFile >> "CfgMagazines" >> _x >> "count"); }; } forEach _loadout; - _ammoCount pushBack [_weapon, _ammo]; + _ammoHM set [_weapon, _ammo]; } forEach _weapons; -_strikePlane setVariable ["ammoCount", _ammoCount]; +_plane setVariable ["ammoCount", _ammoHM]; +Debug("Starting ammo: %1", _ammoHM); -//REPEATING FIRE LOGIC -//Forcing the plane to fire is handled in this EH to avoid loops -_strikePlane addEventHandler -[ - "Fired", + +// Function to calculate ammo types/quantities to use against different vehicle types +private _fnc_getFireMatrix = +{ + params ["_targetType", "_allowHeavyWeapon"]; + if (_targetType in FactionGet(all,"vehiclesTanks")) exitWith + { + Debug_1("%1 target is tank", _supportName); + if(_allowHeavyWeapon) exitWith { [[true, 25, 3, 1], [true, 25, 3, 1], [true, 35, 3, 1]] }; + [[true, 20, 3, 1], [true, 20, 3, 1], [true, 30, 3, 0]]; + }; + if (_targetType in FactionGet(all,"vehiclesArmor")) exitWith + { + Debug_1("%1 target is APC", _supportName); + if(_allowHeavyWeapon) exitWith { [[true, 30, 3, 1], [true, 30, 3, 1], [true, 30, 3, 0]] }; + [[true, 25, 3, 1], [true, 25, 3, 0], [true, 25, 3, 0]]; + }; + if !(_targetType isKindOf "Man") exitWith { - params ["_strikePlane", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"]; - private _targetObj = _strikePlane getVariable ["currentTarget", objNull]; - if(isNull _targetObj) exitWith {}; + if(_allowHeavyWeapon) exitWith { [[true, 35, 3, 0], [true, 35, 3, 0], [true, 35, 3, 0]] }; + [[true, 25, 3, 0], [true, 25, 3, 0], [true, 25, 3, 0]]; + }; + [[false, 0, 0, 0], [true, 15, 0, 0], [true, 15, 0, 0]]; +}; + - private _ammoCount = _strikePlane getVariable "ammoCount"; +//REPEATING FIRE LOGIC +//Forcing the plane to fire is handled in this EH to avoid loops +_plane addEventHandler ["Fired", { + params ["_plane", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"]; + + //Reduce the available ammo for internal logic + private _ammoHM = _plane getVariable "ammoCount"; + private _ammoCount = _ammoHM get _weapon; + if (!isNil "_ammoCount") then { _ammoHM set [_weapon, _ammoCount-1] }; + + // Everything else requires an existing target + private _targetObj = _plane getVariable ["currentTarget", objNull]; + if (isNull _targetObj) exitWith {}; + + // TODO: maybe add incidence factor so we can use it for any approach angle? + private _fnc_ballisticCorrection = { + params ["_projectile", "_targetObj", "_ammo", "_aimError"]; + private _speed = vectorMagnitude velocity _projectile; + private _dist = _targetObj distance _projectile; + private _airFric = getNumber (configFile >> "CfgAmmo" >> _ammo >> "airFriction"); + if (_airFric > 0) then { _airFric = _airFric * 0.002 } else { _airFric = _airFric * -1 }; // rockets use different scale + private _travTime = (exp (_airFric*_dist) - 1) / (_airFric*_speed); // Differential equation solution for a = fv^2 + private _timeExp = 2 - 450*_airFric; // slight fudge because airFric acts on fall rate with long travel + private _fallDist = 0.986 * (4.9 * _travTime ^ _timeExp); // 0.986 is cos^2 incidence factor for 1/6 slope + private _targetPos = (eyePos _targetObj) vectorAdd [0, 0, _fallDist] vectorAdd (velocity _targetObj vectorMultiply _travTime); + _aimError = _aimError + (speed _targetObj / 20) + _dist / 500; + _targetPos = _targetPos apply {_x + (random 2 - 1) * _aimError}; + private _dir = (getPosASL _projectile) vectorFromTo _targetPos; + _projectile setVelocity (_dir vectorMultiply _speed); + _projectile setVectorDir _dir; + }; - if(_weapon == (_strikePlane getVariable "mainGun")) then + if(_weapon == _plane getVariable ["mainGun", ""]) exitWith + { + //Bullet, improve course and accuracy + // TODO: could trace line per burst instead? + [_projectile, _targetObj, _ammo, 2] call _fnc_ballisticCorrection; + + //Remove from shot count, check if we need to try firing again + private _remainingShots = _plane getVariable ["mainGunShots", 0]; + _plane setVariable ["mainGunShots", _remainingShots - 1]; + if(_remainingShots > 1) then { - //Bullet, improve course and accuracy - private _speed = speed _projectile/3.6; - private _targetPos = ((getPosASL _targetObj) vectorAdd [0, 0, 3.5]) vectorAdd (vectorDir _targetObj vectorMultiply ((speed _targetObj)/4.5)); - _targetPos = _targetPos apply {_x + (random 15) - 7.5}; - private _dir = vectorNormalized (_targetPos vectorDiff (getPosASL _projectile)); - _projectile setVelocity (_dir vectorMultiply (_speed)); - _projectile setVectorDir _dir; - - //Check if next shot needs to be fired - private _remainingShots = _strikePlane getVariable ["mainGunShots", 0]; - if(_remainingShots > 0) then + //Fire next shot (does nothing if we're in the middle of a burst) + [_plane, _weapon, _mode] spawn { - //Fire next shot - [_strikePlane, _weapon, _mode] spawn - { - params ["_strikePlane", "_weapon", "_mode"]; - sleep 0.03; - (driver _strikePlane) forceWeaponFire [_weapon, _mode]; - }; - _strikePlane setVariable ["mainGunShots", _remainingShots - 1]; + params ["_plane", "_weapon", "_mode"]; + sleep (0.05 + (_plane getVariable "mainGunReload")); + //Debug_2("Firing followup %1 burst with mode %2", _weapon, _mode); + (driver _plane) forceWeaponFire [_weapon, _mode]; }; }; - if(_weapon in (_strikePlane getVariable ["rocketLauncher", []])) then - { - //Unguided rocket, improve course and accuracy - private _targetPos = (getPosASL _targetObj) vectorAdd (vectorDir _targetObj vectorMultiply ((speed _targetObj))); - private _target = _targetPos apply {_x + (random 30) - 15}; - - //Reduce available ammo - private _index = _ammoCount findIf {_weapon == _x select 0}; - _ammoCount select _index set [1, (_ammoCount#_index#1) - 1]; + }; + if(_weapon in (_plane getVariable ["rocketLauncher", []])) exitWith + { + //Unguided rocket, wait until thrust is complete before fixing accuracy + //Thrust seems to give terrible vertical accuracy for some reason, maybe busted simulation + [time, _projectile, _targetObj, _ammo, _fnc_ballisticCorrection] spawn { + params ["_startTime", "_projectile", "_targetObj", "_ammo", "_fnc_ballisticCorrection"]; + private _thrustTime = getNumber (configFile >> "cfgAmmo" >> _ammo >> "thrustTime"); + sleep (_thrustTime + _startTime - time); + if (isNull _projectile or isNull _targetObj) exitWith {}; + [_projectile, _targetObj, _ammo, 5] call _fnc_ballisticCorrection; + }; - //Check if next shot needs to be fired - private _remainingShots = _strikePlane getVariable ["rocketShots", 0]; - if(_remainingShots > 0) then + //Check if next shot needs to be fired + private _remainingShots = _plane getVariable ["rocketShots", 0]; + _plane setVariable ["rocketShots", _remainingShots - 1]; + if(_remainingShots > 0) then + { + //Fire next shot + [_plane, _weapon, _mode] spawn { - //Fire next shot - [_strikePlane, _weapon, _mode] spawn - { - params ["_strikePlane", "_weapon", "_mode"]; - sleep 0.2; - (driver _strikePlane) forceWeaponFire [_weapon, _mode]; - }; - _strikePlane setVariable ["rocketShots", _remainingShots - 1]; + params ["_plane", "_weapon", "_mode"]; + sleep (0.1 + (_plane getVariable "rocketReload")); + //Debug_2("Firing followup %1 burst with mode %2", _weapon, _mode); + (driver _plane) forceWeaponFire [_weapon, _mode]; }; + }; + }; + if(_weapon in (_plane getVariable ["missileLauncher", []])) exitWith + { + //Guided missile, dont do anything - [_projectile, _target, _gunner] spawn + //Check if next shot needs to be fired (Unlikely, but possible) + private _remainingShots = _plane getVariable ["missileShots", 0]; + _plane setVariable ["missileShots", _remainingShots - 1]; + if(_remainingShots > 1) then + { + //Fire next shot + [_plane, _weapon, _mode] spawn { - params ["_projectile", "_target", "_gunner"]; - sleep 0.05; - while {!(isNull _projectile) && (alive _projectile)} do - { - private _speed = (speed _projectile)/3.6; - private _dir = vectorNormalized (_target vectorDiff (getPosASL _projectile)); - _projectile setVelocity (_dir vectorMultiply (_speed)); - _projectile setVectorDir _dir; - sleep 0.25; - }; + params ["_plane", "_weapon", "_mode"]; + sleep 0.25; + _plane fireAtTarget [_targetObj, _weapon]; }; }; - if(_weapon in (_strikePlane getVariable ["missileLauncher", []])) then - { - //Guided missile, dont do anything + }; +}]; - //Reduce the available ammo for internal logic - private _index = _ammoCount findIf {_weapon == _x select 0}; - _ammoCount select _index set [1, (_ammoCount#_index#1) - 1]; - //Check if next shot needs to be fired (Unlikely, but possible) - private _remainingShots = _strikePlane getVariable ["missileShots", 0]; - if(_remainingShots > 0) then - { - //Fire next shot - [_strikePlane, _weapon, _mode] spawn - { - params ["_strikePlane", "_weapon", "_mode"]; - sleep 0.25; - _strikePlane fireAtTarget [_targetObj, _muzzle]; - }; - _strikePlane setVariable ["missileShots", _remainingShots - 1]; - }; - }; - } -]; -//FIRE LOGIC END - -//Prepare plane for usage -_strikePlane disableAI "TARGET"; -_strikePlane disableAI "AUTOTARGET"; -_strikeGroup setCombatMode "GREEN"; -_strikePlane setVariable ["InArea", false, true]; - -private _dir = (getPos _strikePlane) getDir _setupPos; -_strikePlane setDir _dir; - -/* -//Calculate loiter entry point -private _distance = _strikePlane distance2D _setupPos; -private _angle = asin (1500/_distance); -private _lenght = cos (_angle) * _distance; - -private _height = (ATLToASL _supportPos) select 2; -_height = _height + 500; - -private _entryPos = _setupPos getPos [_lenght, _dir + _angle]; -_entryPos set [2, _height]; - -private _areaWP = _strikeGroup addWaypoint [_entryPos, 0]; -_areaWP setWaypointSpeed "FULL"; -_areaWP setWaypointType "Move"; -_areaWP setWaypointStatements ["true", "(vehicle this) setVariable ['InArea', true, true]; [3, 'CAS plane has arrived', 'CASRoutine'] call A3A_fnc_log"]; -*/ +//distances: +#define DIST_REPOS 5000 +#define DIST_APPROACH 2000 +#define ALT_REPOS 700 +#define ALT_APPROACH 400 + +while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; +private _setupWP = _group addWaypoint [_suppCenter, 0]; +_setupWP setWaypointSpeed "NORMAL"; -private _loiterWP = _strikeGroup addWaypoint [_setupPos, 0]; +private _loiterWP = _group addWaypoint [_suppCenter, 0]; _loiterWP setWaypointSpeed "NORMAL"; _loiterWP setWaypointType "Loiter"; -_loiterWP setWaypointLoiterRadius 2000; +_loiterWP setWaypointLoiterRadius DIST_REPOS; +_loiterWP setWaypointLoiterAltitude ALT_REPOS; +_group setCurrentWaypoint _loiterWP; -sleep 15; -_strikePlane setVariable ["InArea", true, true]; -//Await arrival at AO -//waitUntil {sleep 1; !(alive _strikePlane) || (_strikePlane getVariable ["InArea", false])}; +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +private _baseSpotChance = 0.05 * (1 + _aggro / 100); -if !(alive _strikePlane) exitWith -{ - [_supportName, _side] call A3A_fnc_endSupport; -}; +//states: +#define STATE_PICK_TARGET 1 +#define STATE_REPOSITION 2 +#define STATE_APPROACH 3 -_sleepTime = 5; +private _acquired = false; private _targetObj = objNull; -private _isApproaching = false; -private _isRepathing = false; -private _currentWaypoint = _loiterWP; - -while {_timeAlive > 0} do +private _lastKnownPos = []; // PosASL +private _timeout = time + 900; +private _state = STATE_PICK_TARGET; +while {true} do { - //Check if run script has control over the plane - if !(_strikePlane getVariable ["OnRun", false]) then + //Plane somehow destroyed or disabled + if !(canFire _plane && canMove _plane && side _plane == _side) exitWith { + Info_1("%1 has been destroyed or disabled, aborting routine", _supportName); + }; + + // Target no longer valid (canFight isn't ideal for vehicles but it works) + if (_state != STATE_PICK_TARGET && !(_targetObj call A3A_fnc_canFight)) then { + Debug_1("%1 target lost or destroyed, returning to loiter", _supportName); + _suppTarget resize 0; + _group setCurrentWaypoint _loiterWP; + _state = STATE_PICK_TARGET; + _timeout = _timeout - 300; + }; + + if (time > _timeout) exitWith { + Info_1("%1 has timed out, returning to base", _supportName); + }; + + switch (_state) do { - if (isNull (_strikePlane getVariable ["currentTarget", objNull])) then - { - //Plane is currently not attacking a target, search for new order - private _targetList = server getVariable [format ["%1_targets", _supportName], []]; - if (count _targetList > 0) then - { - //New target active, read in - private _targetEntry = _targetList deleteAt 0; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - Debug_2("Next target for %2 is %1", _targetEntry, _supportName); - - //Parse targets - private _targetParams = _targetEntry select 0; - private _reveal = _targetEntry select 1; - _targetObj = _targetParams select 0; - _strikeGroup reveal [_targetObj, _targetParams select 1]; - - if (alive _targetObj) then - { - //MARKER CREATING, UPDATING AND DISPLAYING - //Show target to players if change is high enough - private _textMarker = createMarker [format ["%1_text", _supportName], getPos _targetObj]; - _textMarker setMarkerShape "ICON"; - _textMarker setMarkerType "mil_objective"; - _textMarker setMarkerText "CAS Target"; - - if(_side == Occupants) then {_textMarker setMarkerColor colorOccupants;} - else {_textMarker setMarkerColor colorInvaders;}; - _textMarker setMarkerAlpha 0; - - [_textMarker, _targetObj, _strikePlane] spawn - { - params ["_textMarker", "_targetObj", "_strikePlane"]; - while - { - !(isNull _strikePlane) && - {(alive _strikePlane) && - (_strikePlane getVariable "currentTarget") == _targetObj} - } do - { - _textMarker setMarkerPos (getPos _targetObj); - sleep 0.5; - }; - deleteMarker _textMarker; - }; - - [_reveal, getPos _targetObj, _side, "CAS", "", _textMarker] spawn A3A_fnc_showInterceptedSupportCall; - //MARKER SECTION END - - _strikePlane setVariable ["currentTarget", _targetObj]; - _strikePlane setVariable ["StartBombRun", false]; - - _fireMatrix = []; - if (_targetObj isKindOf "Tank") then - { - if(_allowHeavyWeapon) then - { - _fireMatrix = - [ - [true, 25, 3, 1], - [true, 25, 3, 1], - [true, 35, 5, 1] - ]; - } - else - { - _fireMatrix = - [ - [true, 20, 0, 1], - [true, 20, 0, 0], - [true, 30, 3, 1] - ]; - }; - } - else - { - if ( (typeOf _targetObj) in FactionGet(all,"vehiclesAPCs") ) then - { - if(_allowHeavyWeapon) then - { - _fireMatrix = - [ - [true, 30, 5, 0], - [true, 30, 5, 1], - [true, 30, 5, 1] - ]; - } - else - { - _fireMatrix = - [ - [true, 25, 5, 1], - [true, 25, 5, 0], - [true, 25, 5, 0] - ]; - }; - } - else - { - if(_allowHeavyWeapon) then - { - _fireMatrix = - [ - [true, 35, 5, 0], - [true, 35, 5, 0], - [true, 35, 5, 0] - ]; - } - else - { - _fireMatrix = - [ - [true, 25, 3, 0], - [false, 25, 5, 0], - [true, 25, 3, 0] - ]; - }; - }; - }; - _strikePlane setVariable ["fireParams", _fireMatrix]; - - //Find better path if the plane is too close - _strikePlane setVariable ["needsRecalculation", _targetObj distance2D _strikePlane < 3000]; - _isRepathing = false; - } - else - { - Debug_1("%1 skips target, as it is already dead", _supportName); - }; + case STATE_PICK_TARGET: { + if (_plane distance2d _suppCenter > 1.5 * DIST_REPOS) exitWith { sleep 5 }; + if (_suppTarget isEqualTo []) exitWith { sleep 5 }; + + _targetObj = _suppTarget select 0; + _lastKnownPos = ATLtoASL (_suppTarget select 1); + if !(_targetObj call A3A_fnc_canFight) exitWith { + _suppTarget resize 0; + Debug_1("%1 skips target, as it is already dead", _supportName); }; - } - else - { - if(_strikePlane getVariable ["needsRecalculation", false]) then - { - if !(_isRepathing) then - { - Debug_1("%1 needs to repath, calculating attack path", _supportName); - //Plane needs a new approach vector, calculate new - private _strikePlaneVector = (getPos _targetObj) vectorDiff (getPos _strikePlane); - _strikePlaneVector set [2, 0]; - private _sidePath = _strikePlaneVector vectorCrossProduct [0,0,-1]; - _repathVector = vectorNormalized _sidePath; - _repathVector = _repathVector vectorMultiply 2500; - Debug_1("Repath vector is %1", str _repathVector); - - private _repathPos = (getPos _targetObj) vectorAdd _repathVector; - _repathPos set [2, 500]; - Debug_2("Repath pos %1, object pos %2", str _repathPos, str (getPos _targetObj)); - private _repathWP = _strikeGroup addWaypoint [_repathPos, 0]; - _repathWP setWaypointType "MOVE"; - _repathWP setWaypointSpeed "FULL"; - _strikeGroup setCurrentWaypoint _repathWP; - _currentWaypoint = _repathWP; - _sleepTime = 1; - - _isRepathing = true; - } - else - { - if((waypointPosition _currentWaypoint) distance2D _strikePlane < 250) then - { - _isRepathing = false; - _strikePlane setVariable ["needsRecalculation", false]; - Debug_1("%1 repathing waypoint reached, attacking", _supportName); - }; + Debug_2("Next target for %2 is %1", _suppTarget, _supportName); + + [_reveal, getPos _targetObj, _side, "CAS", _targetObj, 60] spawn A3A_fnc_showInterceptedSupportCall; + + _timeout = _timeout + 300; + _loiterWP setWaypointPosition [_suppTarget select 1, 0]; + private _heavy = true; // TODO: improve this? + private _fireMatrix = [typeof _targetObj, _heavy] call _fnc_getFireMatrix; + _plane setVariable ["fireParams", _fireMatrix]; + + _acquired = false; + _state = STATE_APPROACH; + }; + + case STATE_APPROACH: { + if (!_acquired) then { + if (_targetObj isKindOf "Man" and _lastKnownPos distance2d _targetObj > 100) then { + // Switch to any man-sized target near the target zone + private _nearTarget = selectRandom (units side _targetObj inAreaArray [_lastKnownPos, 100, 100]); + if (!isNil "_nearTarget" and {_nearTarget call A3A_fnc_canFight} ) then { _targetObj = _nearTarget }; }; - } - else - { - if(_isApproaching) then - { - //Is on course to enter pos - //Recheck course - _targetPos = (getPos _targetObj) vectorAdd [0, 0, 2]; - _targetVector = [400, 0]; - _dir = (_strikePlane getDir _targetObj) + 90; - _targetVector = [_targetVector, -_dir] call BIS_fnc_rotateVector2D; - _targetVector pushBack 100; - _enterRunPos = _targetPos vectorAdd (_targetVector vectorMultiply 5); - _currentWaypoint setWaypointPosition [_enterRunPos, 0]; - _strikePlane setVariable ["enterPos", _enterRunPos]; - - if (terrainIntersect [_targetPos, _enterRunPos]) then - { - //Something is in the way, repathing - Debug_1("After recalculation %1 way is no longer clear, repath", _supportName); - _strikePlane setVariable ["needsRecalculation", true]; - _isRepathing = false; - _sleepTime = 5; - _isApproaching = false; - } - else - { - if(_strikePlane getVariable ["StartBombRun", false]) then - { - _strikePlane setVariable ["StartBombRun", false]; - [_strikePlane, _targetObj, _supportName] spawn A3A_fnc_SUP_CASRun; - _isApproaching = false; - _sleepTime = 5; - }; - }; - } - else - { - //Sets the approach vector - private _targetPos = (getPos _targetObj) vectorAdd [0, 0, 2]; - private _targetVector = [400, 0]; - private _dir = (_strikePlane getDir _targetObj) + 90; - _targetVector = [_targetVector, -_dir] call BIS_fnc_rotateVector2D; - _targetVector pushBack 100; - private _enterRunPos = _targetPos vectorAdd (_targetVector vectorMultiply 5); - _strikePlane setVariable ["enterPos", _enterRunPos]; - - private _wp1 = _strikeGroup addWaypoint [_enterRunPos, 0]; - _wp1 setWaypointType "MOVE"; - _wp1 setWaypointSpeed "FULL"; - _strikeGroup setCurrentWaypoint _wp1; - _currentWaypoint = _wp1; - - //Wait until run enter pos is reached - [_strikePlane] spawn - { - private _strikePlane = _this select 0; - waitUntil - { - sleep 0.1; - private _enterPos = _strikePlane getVariable ["enterPos", objNull]; - (_enterPos isEqualType objNull) || - {(_strikePlane distance2D (_strikePlane getVariable "enterPos")) < 25} - }; - private _enterPos = _strikePlane getVariable ["enterPos", objNull]; - if !(_enterPos isEqualType objNull) then - { - _strikePlane setVariable ["StartBombRun", true]; - }; - }; - - _isApproaching = true; - _sleepTime = 0.25; + private _targetPos = eyePos _targetObj; // Seems to work well even for non-turreted vehicles? + private _planePos = getPosASL _plane; + if (terrainIntersectASL [_targetPos, _planePos]) exitWith { + Debug("Acquisition blocked by terrain"); }; + if (lineIntersects [_targetPos, _planePos, _targetObj, _plane]) exitWith { + Debug("Acquisition blocked by object"); + if !(_targetObj isKindOf "Man") exitWith {}; + // Try another nearby target in case they're in the open + _targetObj = selectRandom (units side _targetObj inAreaArray [getPosATL _targetObj, 20, 20]); + }; + + private _vis = 1 max getNumber (configFile >> "CfgVehicles" >> typeOf _targetObj >> "camouflage"); + private _knownDist = _targetPos distance2d _lastKnownPos; + private _dist = _targetPos distance2d _planePos; + private _chance = _baseSpotChance * _vis * exp (_knownDist / -500) * exp (_dist / -3000); + if (_chance > random 1) then { _acquired = true }; + + Debug_4("Acquisition: vis %1, knowndist %2, dist %3, chance %4", _vis, _knownDist, _dist, _chance); }; - }; - }; + if (_acquired) then { _lastKnownPos = eyePos _targetObj }; + private _dist = _plane distance2d _lastKnownPos; + if (_dist < [300, 800] select _acquired) exitWith { + // If we're too close then break off and try again + Debug_2("%1 approach failed with %2 acquisition", _supportName, _acquired); + _state = STATE_REPOSITION; + }; - //Plane somehow destroyed - if - ( - !(alive _strikePlane) || - {({alive _x} count (units _strikeGroup)) == 0} - ) exitWith - { - Info_1("%1 has been destroyed or crew killed, aborting routine", _supportName); - [_side, 20, 45] remoteExec ["A3A_fnc_addAggression", 2]; - }; + if (_acquired and _dist < 2000) then { + // Wait until plane is pointing roughly in the right direction + private _targVector = _lastKnownPos vectorDiff (getPosASL _plane); + private _dotdir = vectorNormalized _targVector vectorDotProduct vectorDir _plane; + if (_dotdir < 0.90) exitWith {}; + + // Kick off the attack run and wait until it's done + _group setCurrentWaypoint _loiterWP; + private _runHandle = [_plane, _targetObj, _supportName] spawn A3A_fnc_SUP_CASRun; + waitUntil { sleep 2; scriptDone _runHandle }; + + // Run complete + Debug("Ammo at end of run: %1", _ammoHM); + if (-1 == (toArray _ammoHM)#1 findIf { _x > 0 }) exitWith { + Info_1("%1 out of ammo, returning to base", _supportName); + break; + }; + _state = STATE_REPOSITION; + continue; + }; - //No missiles left - if (_confirmedKills <= 0) exitWith - { - Info_1("%1 has reached its kill limit, aborting routine", _supportName); - _timeAlive = 0; - }; + // Move the approach waypoint + _setupWP setWaypointPosition [_lastKnownPos vectorAdd [0,0,50], -1]; // just aim above the target + _group setCurrentWaypoint _setupWP; + _plane flyInHeight (ALT_REPOS min (ALT_APPROACH * _dist / DIST_APPROACH)); + sleep 1; + }; - //Retreating - if(_strikePlane getVariable ["Retreat", false]) exitWith - { - Info_1("%1 met heavy resistance, retreating", _supportName); - _timeAlive = 0; - }; + case STATE_REPOSITION: { + // if we're around 3km away and facing <100 degrees from the target, switch to approach + private _dist = _plane distance2d _lastKnownPos; + private _targVector = _lastKnownPos vectorDiff (getPosASL _plane); + private _dotdir = vectorNormalized _targVector vectorDotProduct vectorDir _plane; + if (_dist < DIST_REPOS*1.1 and _dist > DIST_REPOS*0.9 and _dotdir > -0.3) exitWith { + Debug_1("%1 switching to approach", _supportName); + _state = STATE_APPROACH; + _acquired = false; + }; - //No ammo left - if(_strikePlane getVariable ["OutOfAmmo", false]) exitWith - { - Info_1("%1 run out of ammo, returning to base", _supportName); - _timeAlive = 0; - }; + // Aim at point on circle that's 45 degrees clockwise from current pos + // Larger circle + private _sideDir = [[_targVector#0, _targVector#1], -45] call BIS_fnc_rotateVector2D; + private _repathPos = (vectorNormalized _sideDir) vectorMultiply -(2*DIST_REPOS - _dist); + _repathPos = _repathPos vectorAdd [0,0,500] vectorAdd _lastKnownPos; + + _setupWP setWaypointPosition [_repathPos, -1]; + _group setCurrentWaypoint _setupWP; + _plane flyInHeight ALT_REPOS; + sleep 2; + }; - sleep _sleepTime; - _timeAlive = _timeAlive - _sleepTime; + }; }; -_strikePlane setVariable ["currentTarget", nil]; -_strikePlane setVariable ["enterPos", nil]; -_strikePlane setVariable ["InArea", false]; +_plane removeAllEventHandlers "Fired"; +_suppData set [4, 0]; // Set activesupport radius to zero, enabling cleanup + +[_group] spawn A3A_fnc_groupDespawner; +[_plane] spawn A3A_fnc_vehDespawner; //Have the plane fly back home -if (alive _strikePlane && [driver _strikePlane] call A3A_fnc_canFight) then +if (canMove _plane && {driver _plane call A3A_fnc_canFight}) then { - for "_i" from (count waypoints _strikeGroup - 1) to 0 step -1 do - { - deleteWaypoint [_strikeGroup, _i]; - }; - private _wpBase = _strikeGroup addWaypoint [getMarkerPos _airport, 0]; - _wpBase setWaypointType "MOVE"; + while {count waypoints _group > 0} do { deleteWaypoint [_group, 0] }; + private _wpBase = _group addWaypoint [_spawnPos, 0]; + _wpBase setWaypointSpeed "NORMAL"; _wpBase setWaypointBehaviour "CARELESS"; - _wpBase setWaypointSpeed "FULL"; - _wpBase setWaypointStatements ["true", "if !(local this) exitWith {}; deleteVehicle (vehicle this); {deleteVehicle _x} forEach thisList"]; - _strikeGroup setCurrentWaypoint _wpBase; + _group setCurrentWaypoint _wpBase; - waitUntil {sleep 0.5;_strikePlane distance2D (getMarkerPos _airport) < 100}; - { - deleteVehicle _x; - } forEach (units _strikeGroup); - deleteVehicle _strikePlane; + private _timeout = time + (getPos _plane distance2d _spawnPos) / 20; + waitUntil { sleep 2; (currentWaypoint _group != 0) or (time > _timeout) }; + if (time > _timeout) exitWith {}; + { deleteVehicle _x } forEach (units _group); + deleteVehicle _plane; }; - -//Deleting all the support data here -[_supportName, _side] call A3A_fnc_endSupport; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_CASRun.sqf b/A3A/addons/core/functions/Supports/fn_SUP_CASRun.sqf index 6aeecb58e5..fdbd631580 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_CASRun.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_CASRun.sqf @@ -1,167 +1,81 @@ -params ["_strikePlane", "_target", "_supportName"]; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -//Take over control -Debug_1("%1 has started gun run", _supportName); -_strikePlane setVariable ["OnRun", true]; -private _supportMarker = format ["%1_coverage", _supportName]; - -//When reached, update run path -private _targetPos = (getPosASL _target) vectorAdd [0, 0, 2]; -private _targetVector = [400, 0]; -private _dir = (_strikePlane getDir _target) + 90; -_targetVector = [_targetVector, -_dir] call BIS_fnc_rotateVector2D; -private _sideVector = [_targetVector, -_dir + 90] call BIS_fnc_rotateVector2D; -_sideVector set [2, 0]; -_enterRunPos = getPosASL _strikePlane; -private _exitRunPos = _targetPos vectorAdd _targetVector; -private _forward = _exitRunPos vectorDiff _enterRunPos; -private _upVector = (_forward vectorCrossProduct _sideVector) vectorMultiply -1; -private _forwardSpeed = (velocityModelSpace _strikePlane) select 1; -private _timeForRun = 1620 / _forwardSpeed; -private _speedVector = (vectorNormalized _forward) vectorMultiply _forwardSpeed; - -private _interval = 0; -private _realTime = 0; +params ["_plane", "_target", "_supportName"]; +Debug_1("%1 has started gun run", _supportName); //Creating the startpoint for the fire EH loop private _fnc_executeWeaponFire = { - params ["_strikePlane", "_fireParams"]; + params ["_plane", "_fireParams"]; _fireParams params ["_armed", "_mainGunShots", "_rocketShots", "_missileShots"]; - private _ammoCount = _strikePlane getVariable "ammoCount"; + private _ammoHM = _plane getVariable "ammoCount"; - if(_mainGunShots > 0) then + Debug_1("Execute weapon fire called with fireParams %1", _fireParams); + + private _weapons = _plane getVariable ["missileLauncher", []]; + if (_missileShots > 0 && _weapons isNotEqualTo []) then { - //Fire main gun with selected mode - private _weapon = _strikePlane getVariable ["mainGun", ""]; - private _modes = getArray (configFile >> "cfgweapons" >> _weapon >> "modes"); - private _mode = _modes select 0; - if (_mode == "this") then - { - _mode = _weapon; - } - else + //Select missile weapon + private _selectedWeapon = ""; + private _currentHighest = -1; { - if ("close" in _modes) then - { - _mode = "close"; + if (_ammoHM get _x > _currentHighest) then { + _selectedWeapon = _x; + _currentHighest = _ammoHM get _x; }; - }; + if (_currentHighest >= _missileShots) exitWith {}; + } forEach _weapons; + Debug_2("Selected missile %1, remaining shots %2", _selectedWeapon, _currentHighest); + if (_currentHighest <= 0) exitWith {}; - //Force weapon fire - _strikePlane setVariable ["mainGunShots", (_mainGunShots - 1)]; - (driver _strikePlane) forceWeaponFire [_weapon, _mode]; + //Fire weapon if one is selected (guided weapons only gets fired when they have a lockon possibility on the target) + _plane setVariable ["missileShots", _missileShots min _currentHighest]; + _plane fireAtTarget [_plane getVariable "currentTarget", _selectedWeapon]; }; - if(_rocketShots > 0) then + + private _weapons = _plane getVariable ["rocketLauncher", []]; + if (_rocketShots > 0 && _weapons isNotEqualTo []) then { //Select rocket weapon for use - private _weapons = _strikePlane getVariable ["rocketLauncher", []]; - private _selectedWeapon = objNull; - if(count _weapons > 1) then - { - - private _currentHighest = 0; - { - private _weapon = _x; - private _index = _ammoCount findIf {_x select 0 == _weapon}; - if ((_selectedWeapon == "") || {_ammoCount#_index#1 > _currentHighest}) then - { - _selectedWeapon = _weapon; - _currentHighest = _ammoCount#_index#1; - }; - //Weapon with more shots then needed found, using it - if(_currentHighest >= _rocketShots) exitWith {}; - } forEach _weapons; - if(_currentHighest < _rocketShots) then - { - _strikePlane setVariable ["OutOfAmmo", true]; - }; - } - else + private _selectedWeapon = ""; + private _currentHighest = -1; { - if(count _weapons == 1) then - { - _selectedWeapon = _weapons#0; - private _index = _ammoCount findIf {_x select 0 == _selectedWeapon}; - if(_ammoCount#_index#1 < _rocketShots) then - { - _strikePlane setVariable ["OutOfAmmo", true]; - }; + if (_ammoHM get _x > _currentHighest) then { + _selectedWeapon = _x; + _currentHighest = _ammoHM get _x; }; - }; + if (_currentHighest >= _rocketShots) exitWith {}; + } forEach _weapons; + Debug_2("Selected rocket %1, remaining shots %2", _selectedWeapon, _currentHighest); + if (_currentHighest <= 0) exitWith {}; - //If weapon available fire it - if(_selectedWeapon isEqualType "") then - { - //Select fire mode for weapon - private _modes = (getArray (configFile >> "cfgweapons" >> _selectedWeapon >> "modes")); - private _mode = _modes select 0; - if (_mode == "this") then - { - _mode = _selectedWeapon; - } - else - { - if ("Close_AI" in _modes) then - { - _mode = "Close_AI"; - }; - if("Single" in _modes) then - { - _mode = "Single"; - }; - }; + private _weapCfg = configFile >> "cfgWeapons" >> _selectedWeapon; + private _modes = ["Single", "Close_AI"] arrayIntersect getArray (_weapCfg >> "modes"); + if (_modes isEqualTo []) then { _modes = getArray (_weapCfg >> "modes") }; + private _modeCfg = [_weapCfg >> (_modes#0), _weapCfg] select (_modes#0 == "this"); - //Force weapon fire - _strikePlane setVariable ["rocketShots", (_rocketShots - 1)]; - (driver _strikePlane) forceWeaponFire [_selectedWeapon, _mode]; - }; + //Force weapon fire + _plane setVariable ["rocketShots", _rocketShots min _currentHighest]; + _plane setVariable ["rocketReload", getNumber (_modeCfg >> "reloadTime")]; + Debug_3("Firing %1 shots with mode %2 and reload %3", _plane getVariable "rocketShots", configName _modeCfg, _plane getVariable "rocketReload"); + (driver _plane) forceWeaponFire [_selectedWeapon, configName _modeCfg]; }; - if(_missileShots > 0) then + + private _selectedWeapon = _plane getVariable ["mainGun", ""]; + if(_mainGunShots > 0 && _selectedWeapon != "") then { - //Select missile weapon - private _weapons = _strikePlane getVariable ["missileLauncher", []]; - private _selectedWeapon = ""; - if(count _weapons > 1) then - { - private _currentHighest = 0; - { - private _weapon = _x; - private _index = _ammoCount findIf {_x select 0 == _weapon}; - if ((_selectedWeapon == "") || {_ammoCount#_index#1 > _currentHighest}) then - { - _selectedWeapon = _weapon; - _currentHighest = _ammoCount#_index#1; - }; - //Weapon with more shots then needed found, using it - if(_currentHighest >= _missileShots) exitWith {}; - } forEach _weapons; - if(_currentHighest < _missileShots) then - { - _strikePlane setVariable ["OutOfAmmo", true]; - }; - } - else - { - if(count _weapons == 1) then - { - _selectedWeapon = _weapons#0; - private _index = _ammoCount findIf {_x select 0 == _selectedWeapon}; - if(_ammoCount#_index#1 < _missileShots) then - { - _strikePlane setVariable ["OutOfAmmo", true]; - }; - }; - }; + //Fire main gun with selected mode. Assume that we won't run out of ammo... + private _weapCfg = configFile >> "cfgWeapons" >> _selectedWeapon; + private _modes = ["close"] arrayIntersect getArray (_weapCfg >> "modes"); // can add preferred modes here in priority order + if (_modes isEqualTo []) then { _modes = getArray (_weapCfg >> "modes") }; + private _modeCfg = [_weapCfg >> (_modes#0), _weapCfg] select (_modes#0 == "this"); - //Fire weapon if one is selected (guided weapons only gets fired when they have a lockon possibility on the target) - if(_selectedWeapon isEqualType "") then - { - _strikePlane fireAtTarget [_strikePlane getVariable "currentTarget", _selectedWeapon]; - _strikePlane setVariable ["missileShots", (_missileShots - 1)]; - }; + //Force weapon fire + _plane setVariable ["mainGunShots", _mainGunShots]; + _plane setVariable ["mainGunReload", getNumber (_modeCfg >> "reloadTime")]; + Debug_3("Firing %1 shots with mode %2 and reload %3", _plane getVariable "mainGunShots", configName _modeCfg, _plane getVariable "mainGunReload"); + (driver _plane) forceWeaponFire [_selectedWeapon, configName _modeCfg]; }; }; @@ -174,111 +88,92 @@ private _fireParams = [true, 40, 7, 0] ]; */ -private _fireParams = +(_strikePlane getVariable "fireParams"); +//private _fireParams = [[true, 30, 0, 0], [true, 30, 0, 0], [true, 30, 0, 0]]; +//private _fireParams = [[true, 0, 0, 1], [true, 0, 0, 1], [true, 0, 0, 1]]; +private _fireParams = +(_plane getVariable "fireParams"); +_plane setVariable ["currentTarget", _target]; + +private _enterRunPos = getPosASL _plane; +private _targetPos = eyePos _target; +if(terrainIntersectASL [_enterRunPos, _targetPos]) exitWith { + Debug_1("%1 gun way is blocked, recalculating", _supportName); +}; +private _exitRunPos = _targetPos vectorAdd [0,0,20]; -while {_interval < 0.95 && alive _strikePlane && {!(isNull (driver _strikePlane))}} do -{ - if(!(alive _target) || {!(_strikePlane getVariable ["InArea", false]) || {!(getPos _target inArea _supportMarker)}}) exitWith - { - Debug_1("%1 target eliminated or escaped, returning to loitering", _supportName); - _strikePlane setVariable ["currentTarget", objNull]; - }; +private _forwardSpeed = (velocityModelSpace _plane) select 1; +private _timeForRun = (_enterRunPos vectorDistance _exitRunPos) / _forwardSpeed; - if(_realTime > 0.5) then - { - //Update course of plane - _realTime = 0; - _targetPos = (getPosASL _target) vectorAdd [0, 0, 2]; - _targetVector = [400, 0]; - _dir = (_strikePlane getDir _target) + 90; - _sideVector = [_targetVector, -_dir + 90] call BIS_fnc_rotateVector2D; - _targetVector = [_targetVector, -_dir] call BIS_fnc_rotateVector2D; - _targetVector pushBack 100; - _sideVector pushBack 0; - _exitRunPos = _targetPos vectorAdd _targetVector; +private _forward = _enterRunPos vectorFromTo _exitRunPos; +private _speedVector = _forward vectorMultiply _forwardSpeed; +private _upVector = _forward vectorCrossProduct (vectorUp _plane) vectorCrossProduct _forward; + +private _transform = [ + _enterRunPos, _exitRunPos, + _speedVector, _speedVector, + _forward, _forward, + _upVector, _upVector, 0]; - private _strikePlanePos = getPosASL _strikePlane; - private _way = _strikePlanePos vectorDiff _exitRunPos; +// Set up intervals at which to fire +private _fireIntervals = []; +private _runDist = _plane distance2d _target; +{ if (_runDist > _x) then { _fireIntervals pushBack (1 - _x / _runDist) } } forEach [700, 1000, 1500]; +reverse _fireIntervals; +while { count _fireParams > count _fireIntervals } do { _fireParams deleteAt 0 }; +Debug_2("Fire intervals for run dist %1: %2", _runDist, _fireIntervals); - _enterRunPos = _exitRunPos vectorAdd (_way vectorMultiply (1/(1-_interval))); - _forward = _exitRunPos vectorDiff _enterRunPos; - _speedVector = (vectorNormalized _forward) vectorMultiply _forwardSpeed; - _upVector = (_forward vectorCrossProduct _sideVector) vectorMultiply -1; - if(terrainIntersect [getPosASL _strikePlane, _targetPos]) exitWith - { - Debug_1("%1 gun way is blocked, recalculating", _supportName); - _strikePlane setVariable ["needsRecalculation", true]; - }; +addMissionEventHandler ["EachFrame", +{ + _thisArgs params ["_plane", "_target", "_startTime", "_timeForRun", "_transform", "_fireParams", "_fireFnc", "_fireIntervals"]; + _interval = (time - _startTime) / _timeForRun; + + if (!alive _target or (_plane distance2d _target) < 300 or _interval > 0.95 or !canMove _plane or isNull driver _plane) exitWith { + Debug_1("EachFrame handler terminated with interval %1", _interval); + _transform set [8, 1]; // signal completion to the waitUntil + removeMissionEventHandler ["EachFrame", _thisEventHandler]; }; - if(_strikePlane getVariable ["needsRecalculation", false]) exitWith {}; + _transform set [8, _interval]; + _plane setVelocityTransformation _transform; - _strikePlane setVelocityTransformation - [ - _enterRunPos, _exitRunPos, - _speedVector, _speedVector, - _forward, _forward, - _upVector, _upVector, - _interval - ]; + if (_interval > _fireIntervals#0) then { + if (_fireParams#0#0) then { [_plane, _fireParams#0] spawn _fireFnc }; + _fireParams deleteAt 0; + _fireIntervals deleteAt 0; + }; + +}, [_plane, _target, time, _timeForRun, _transform, _fireParams, _fnc_executeWeaponFire, _fireIntervals]]; - sleep 0.05; - _interval = _interval + (0.05 / _timeForRun); - _realTime = _realTime + 0.05; +waitUntil { sleep 1; _transform#8 >= 1 }; - //FIRE MECHANISM - //First burst +Debug_1("Gun run for %1 finished, returning control", _supportName); + +/* if(_interval > 0.25 && (_fireParams#0#0)) then { + Debug_1("Rounds to fire in first phase: %1", _fireParams#0); //Execute fire params - [_strikePlane, _fireParams#0] spawn _fnc_executeWeaponFire; + [_plane, _fireParams#0] spawn _fireFnc; (_fireParams#0) set [0, false]; }; //Second burst if(_interval > 0.5 && (_fireParams#1#0)) then { + Debug_3("Rounds unfired in first phase: %1, %2, %3", _plane getVariable "mainGunShots", _plane getVariable "rocketShots", _plane getVariable "missileShots"); + Debug_1("Rounds to fire in second phase: %1", _fireParams#1); //Execute fire params - [_strikePlane, _fireParams#1] spawn _fnc_executeWeaponFire; + [_plane, _fireParams#1] spawn _fireFnc; (_fireParams#1) set [0, false]; }; //Third burst if(_interval > 0.75 && (_fireParams#2#0)) then { + Debug_3("Rounds unfired in second phase: %1, %2, %3", _plane getVariable "mainGunShots", _plane getVariable "rocketShots", _plane getVariable "missileShots"); + Debug_1("Rounds to fire in third phase: %1", _fireParams#2); //Execute fire params - [_strikePlane, _fireParams#2] spawn _fnc_executeWeaponFire; + [_plane, _fireParams#2] spawn _fireFnc; (_fireParams#2) set [0, false]; }; - //FIRE MECHANISM END -}; -//Plane died, exit -if(!(alive _strikePlane) || (isNull driver _strikePlane)) exitWith {}; - -if(_strikePlane getVariable ["InArea", false]) then -{ - //Plane is alive, set new circle waypoint - private _group = group driver _strikePlane; - for "_i" from (count waypoints _group - 1) to 0 step -1 do - { - deleteWaypoint [_group, _i]; - }; - - private _loiterWP = (group driver _strikePlane) addWaypoint [(getMarkerPos _supportMarker), 0]; - _loiterWP setWaypointSpeed "NORMAL"; - _loiterWP setWaypointType "Loiter"; - _loiterWP setWaypointLoiterRadius 2000; -}; - -//Await until the plane arrived at a specific height until breaking control -waitUntil -{ - private _velocity = velocity _strikePlane; - _velocity set [2, (_velocity select 2) + 0.5]; - _strikePlane setVelocity _velocity; - sleep 0.5; - ((getPos _strikePlane) select 2) > 450 -}; -Debug_1("Gun run for %1 finished, returning control", _supportName); -_strikePlane setVariable ["OnRun", false]; -_strikePlane setVariable ["needsRecalculation", true]; +Debug_3("Rounds unfired in third phase: %1, %2, %3", _plane getVariable "mainGunShots", _plane getVariable "rocketShots", _plane getVariable "missileShots"); +*/ diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRF.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRF.sqf deleted file mode 100644 index 973eb2b6ef..0000000000 --- a/A3A/addons/core/functions/Supports/fn_SUP_QRF.sqf +++ /dev/null @@ -1,135 +0,0 @@ -params ["_side", "_posDestination", "_supportName"]; - -/* Sends a QRF force towards the given position - - Execution on: Server - - Scope: External - - Params: - _posDestination: POSITION : The target position where the QRF will be send to - _side: SIDE : The side of the QRF - - Returns: - _coverageMarker : STRING : The name of the marker covering the support area, "" if not possible -*/ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); - -private _typeOfAttack = [_posDestination, _side, _supportName] call A3A_fnc_chooseAttackType; -//If no type specified, exit here -if(_typeOfAttack == "") exitWith -{ - "" -}; - -private _markerOrigin = [_posDestination, _side] call A3A_fnc_findBaseForQRF; -if (_markerOrigin == "") exitWith -{ - Info_1("QRF to %1 cancelled because no usable bases in vicinity",_posDestination); - "" -}; -private _posOrigin = getMarkerPos _markerOrigin; - -Debug_2("%1 will be send from %2", _supportName, _markerOrigin); - -private _targetMarker = createMarker [format ["%1_coverage", _supportName], _posDestination]; - -_targetMarker setMarkerShape "ELLIPSE"; -_targetMarker setMarkerBrush "Grid"; -_targetMarker setMarkerSize [300, 300]; -if(_side == Occupants) then -{ - _targetMarker setMarkerColor colorOccupants; -}; -if(_side == Invaders) then -{ - _targetMarker setMarkerColor colorInvaders; -}; -_targetMarker setMarkerAlpha 0; - -//Base selected, select units now -private _vehicles = []; -private _groups = []; -private _landPosBlacklist = []; - -private _aggression = if (_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; -private _playerScale = call A3A_fnc_getPlayerScale; -private _vehicleCount = random 1 + _playerScale + _aggression/50; -_vehicleCount = (round (_vehicleCount)) max 1; - -Debug_3("Due to %1 aggression and %2 player scale, sending %3 vehicles", _aggression, _playerScale, _vehicleCount); - -//Set idle times for marker -if (_markerOrigin in airportsX) then -{ - [_markerOrigin, 10] call A3A_fnc_addTimeForIdle; -} -else -{ - [_markerOrigin, 20] call A3A_fnc_addTimeForIdle; -}; - -private _vehPool = []; -private _replacement = []; - -if ((_posOrigin distance2D _posDestination < distanceForLandAttack) && {[_posOrigin, _posDestination] call A3A_fnc_arePositionsConnected}) then -{ - //The attack will be carried out by land and air vehicles - _vehPool = [_side] call A3A_fnc_getVehiclePoolForQRFs; - _replacement = (_faction get "vehiclesHelisLight") + (_faction get "vehiclesTrucks") + (_faction get "vehiclesLightArmed"); -} -else -{ - //The attack will be carried out by air vehicles only - _vehPool = [_side, ["LandVehicle"]] call A3A_fnc_getVehiclePoolForQRFs; - _replacement = (_faction get "vehiclesHelisLight"); -}; - -//If vehicle pool is empty, fill it up -if(_vehPool isEqualTo []) then -{ - {_vehPool append [_x, 1]} forEach _replacement; -}; - -for "_i" from 1 to _vehicleCount do -{ - if ([_side] call A3A_fnc_remUnitCount < 4) exitWith { - Info("Cancelling because maxUnits exceeded"); - }; - - private _vehicleType = selectRandomWeighted _vehPool; - private _vehicleData = [_vehicleType, _typeOfAttack, _landPosBlacklist, _side, _markerOrigin, _posDestination] call A3A_fnc_createAttackVehicle; - if (_vehicleData isEqualType []) then - { - _vehicles pushBack (_vehicleData select 0); - _groups pushBack (_vehicleData select 1); - if !(isNull (_vehicleData select 2)) then - { - _groups pushBack (_vehicleData select 2); - }; - _landPosBlacklist = (_vehicleData select 3); - sleep 5; - }; - -}; -Info_3("Spawn Performed: %1 QRF sent with %2 vehicles, callsign %3", _typeOfAttack, count _vehicles, _supportName); - -[_side, _vehicles, _groups, _posDestination, _supportName] spawn A3A_fnc_SUP_QRFRoutine; - -_markerOrigin spawn -{ - sleep 60; - if(spawner getVariable _this == 2) then - { - [_this] call A3A_fnc_freeSpawnPositions; - }; -}; - -private _distance = _posOrigin distance2D _posDestination; -private _minTime = _distance / (300 / 3.6); -private _maxTime = _distance / (25 / 3.6); - -private _result = [_targetMarker, _minTime, _maxTime]; -_result; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFAir.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFAir.sqf new file mode 100644 index 0000000000..74793fb306 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_QRFAir.sqf @@ -0,0 +1,51 @@ +/* Sets up an air QRF support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend on this QRF. + Target, or "false" for none. Might be used to flavour the QRF + Estimated position of target, or center of target zone + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_suppName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + +// No typeOfAttack, QRF contents depend purely on target? +// not 100% smart but we don't want it to be +// Also no killzones, QRFs have resource spend limitations instead + +private _airbase = [_side, _targPos] call A3A_fnc_availableBasesAir; +if (isNil "_airbase") exitWith { Info("QRF cancelled because no airbases available (how?)"); -1 }; + +private _vehCount = 3 min ceil (_maxSpend / A3A_balanceVehicleCost); // will overshoot a bit (no 1.5x factor). This is preferable to sending tiny QRFs +// TODO: bias a bit for tank/APC/static targets? +private _attackCount = round random ([0, 0, 0.8, 1.5] select _vehCount); + +// 1.5 cost factor for air +private _estResources = 1.5 * _vehCount * A3A_balanceVehicleCost; +A3A_supportStrikes pushBack [_side, "TROOPS", _targPos, time + 45*60, 45*60, _estResources]; + +private _aggro = [aggressionOccupants, aggressionInvaders] select (_side == Invaders); +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggro) }; + +//Set idle times for marker, just so that stuff doesn't spawn on top? Carrier will ignore anyway +[_airbase, 5+_delay/60] call A3A_fnc_addTimeForIdle; + +// kinda epic but whatever +[[_suppName, _side, _resPool, _delay, _targPos, _airbase, true, _vehCount, _attackCount, _estResources], "A3A_fnc_SUP_QRFRoutine"] call A3A_fnc_scheduler; + +private _approxTime = _delay + (markerPos _airbase distance2D _targPos) / (200 / 3.6); // estimated travel time +[_reveal, _side, "QRFAIR", _targPos, _approxTime] spawn A3A_fnc_showInterceptedSetupCall; + +_estResources; // *estimated* resource cost of QRF diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFAirAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFAirAvailable.sqf new file mode 100644 index 0000000000..e90aca3dd7 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_QRFAirAvailable.sqf @@ -0,0 +1,34 @@ +/* Get Air QRF support selection weight against target + +Arguments: + Target object + Side to send support from + Array of strings of available types for this faction + +Return value: + Weight value, 0 for unavailable or useless +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_target", "_side", "_maxSpend", "_availTypes"]; + +// make air a bit more likely with war tier? or not? +// air QRFs are typically *less* effective at higher tiers, right? + +// specifically don't use it to attack: +// - Fixed wing aircraft +// - static AA +// - AA tanks/trucks +// TODO: Rework vehicle type system to handle this shit better +private _allAA = (A3A_faction_all get "vehiclesPlanesAA") + (A3A_faction_all get "vehiclesAA") + (A3A_faction_all get "staticAA"); +if (typeOf _target in _allAA) exitWith { 0 }; + +// Otherwise fine? +// Could reduce chance for heli or non-infantry targets in general +// It can technically hit air/tanks, it's just not great at it + +if (_target isKindOf "Air") exitWith { 0.2 }; +if !(_target isKindOf "Man") exitWith { 0.5 }; +1; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFAvailable.sqf deleted file mode 100644 index c98b3d18e8..0000000000 --- a/A3A/addons/core/functions/Supports/fn_SUP_QRFAvailable.sqf +++ /dev/null @@ -1,58 +0,0 @@ -params ["_side", "_position"]; - -/* Checks if the QRF support is available - - Execution on: Server - - Scope: Internal - - Parameters: - _side: SIDE : The side which wants to call the support - _position: POSITION : The position to which the support needs to be called - - Returns: - 0 if QRF is possible, -1 otherwise -*/ - -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -//QRFs always run on the server at the moment, so leave a buffer for wavedCAs -if ([_side] call A3A_fnc_remUnitCount < 40) exitWith -{ - Debug("Blocked QRF because unit count on server is too high"); - -1; -}; - -if ([_position,false] call A3A_fnc_fogCheck < 0.3) exitWith -{ - Debug_1("Blocked QRF to %1 due to heavy fog", _position); - -1; -}; - -//Do a quick check for at least one available airport -private _index = airportsX findIf -{ - sidesX getVariable [_x, sideUnknown] == _side && - {(getMarkerPos _x) distance2D _position < distanceForAirAttack && - {[_x, true] call A3A_fnc_airportCanAttack}} -}; -if(_index != -1) exitWith -{ - 0; -}; - -//No airport found, search for bases -_index = outposts findIf -{ - sidesX getVariable [_x, sideUnknown] == _side && - {(getMarkerPos _x) distance2D _position < distanceForLandAttack && - {[_x, true] call A3A_fnc_airportCanAttack && - {[getMarkerPos _x, _position] call A3A_fnc_arePositionsConnected}}} -}; -if(_index != -1) exitWith -{ - 0; -}; - --1; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFLand.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFLand.sqf new file mode 100644 index 0000000000..6dbea1e3bf --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_QRFLand.sqf @@ -0,0 +1,46 @@ +/* Sets up a land QRF support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend on this QRF. Must be greater than zero + Target, or "false" for none. Might be used to flavour the QRF + Estimated position of target, or center of target zone + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_suppName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + +private _base = [_side, _targPos] call A3A_fnc_availableBasesLand; +if (isNil "_base") exitWith { Info("QRF cancelled because no land bases available"); -1 }; + +//Set idle times for marker, just so that stuff doesn't spawn on top +[_base, 10] call A3A_fnc_addTimeForIdle; + +private _vehCount = 3 min ceil (_maxSpend / A3A_balanceVehicleCost); +private _attackCount = [0, 0, round random 1, 1] select _vehCount; + +private _estResources = _vehCount * A3A_balanceVehicleCost; +A3A_supportStrikes pushBack [_side, "TROOPS", _targPos, time + 2700, 2700, _estResources]; + +//private _aggro = [aggressionOccupants, aggressionInvaders] select (_side == Invaders); +// Land QRF delay is purely dependent on travel as they're slow enough already +if (_delay < 0) then { _delay = 0 }; // land QRFs slow enough already + +// kinda epic but whatever +[[_suppName, _side, _resPool, _delay, _targPos, _base, false, _vehCount, _attackCount, _estResources], "A3A_fnc_SUP_QRFRoutine"] call A3A_fnc_scheduler; + +private _approxTime = _delay + (markerPos _base distance2D _targPos) / (30 / 3.6); // (badly) estimated travel time +[_reveal, _side, "QRFLAND", _targPos, _approxTime] spawn A3A_fnc_showInterceptedSetupCall; + +_estResources; // *estimated* resource cost of QRF diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFLandAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFLandAvailable.sqf new file mode 100644 index 0000000000..28b01497b0 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_QRFLandAvailable.sqf @@ -0,0 +1,21 @@ +/* Get land QRF support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction + +Return value: + Weight value, 0 for unavailable or useless +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_target", "_side", "_maxSpend", "_availTypes"]; + + +if (_target in (A3A_faction_all get "vehiclesFixedWing")) exitWith { 0 }; // Arguable but whatever + +1; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_QRFRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_QRFRoutine.sqf index 7e2cfbcbde..8d76499f14 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_QRFRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_QRFRoutine.sqf @@ -1,100 +1,89 @@ -params ["_side", "_vehicles", "_groups", "_posDestination", "_supportName"]; -/* The despawn routine of the QRF support +/* Spawns and maintains an air or land QRF - Execution on: HC or Server +Environment: Server or HC, must be spawned - Scope: Internal - - Parameters: - _side: SIDE : The side of the attackers - _vehicles: ARRAY of OBJECTS : All vehicles used by the QRF - _groups: ARRAY of GROUPS : All groups used by the QRF - _posDestination: POSITION : The target position - _supportName: STRING : The callname of the support - - Returns: - Nothing +Arguments: + Unique support name (mostly for logging) + Side to send support from + Resource pool of support, "attack" or "defence" + Delay time in seconds + Target position for airstrike + Marker name of source airport + Whether the QRF is air (true) or land (false) + Total vehicle count of QRF + Support (non-transport) vehicle count of QRF + Estimated resources already spent on support */ + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -//Prepare despawn conditions -private _endTime = time + 2700; -private _qrfHasArrived = false; -private _qrfHasWon = false; -private _targetList = server getVariable [format ["%1_targets", _supportName], []]; -private _reveal = _targetList select 0 select 1; +params ["_supportName", "_side", "_resPool", "_sleepTime", "_targPos", "_base", "_isAir", "_vehCount", "_attackCount", "_estResources"]; + +sleep _sleepTime; + +// Now spawn the actual QRF +ServerDebug_3("%1 attempting to create force with %2 transport and %3 attack vehicles", _supportName, _vehCount-_attackCount, _attackCount); +private _data = if (_isAir) then { + [_side, _base, _targPos, _resPool, _vehCount, _attackCount] call A3A_fnc_createAttackForceAir; +} else { + [_side, _base, _targPos, _resPool, _vehCount, _attackCount] call A3A_fnc_createAttackForceLand; +}; +_data params ["_resources", "_vehicles", "_crewGroups", "_cargoGroups"]; +ServerInfo_1("Spawn performed: Vehicles %1", _vehicles apply { typeOf _x }); + +// Update the resource usage for the final value +[_estResources - _resources, _side, _resPool] remoteExec ["A3A_fnc_addEnemyResources", 2]; + +// Find nearest garrison marker and use that as attempted capture/garrison target if close +private _nearMrk = call { + private _potentials = outposts + airportsX + resourcesX + factories + seaports; + private _nearMrk = [_potentials, _targPos] call BIS_fnc_nearestPosition; // might be nil + [nil, _nearMrk] select (markerPos _nearMrk distance2d _targPos < 500); +}; + +private _timeOut = time + 1800; +private _searchTime = time; +private _travelling = true; +private _soldiers = []; +{ _soldiers append units _x } forEach _cargoGroups; while {true} do { - if !(_qrfHasArrived) then - { - //Not yet arrived - private _index = _vehicles findIf {getPos _x distance2D _posDestination < 300}; - if(_index != -1) then - { - Info_1("%1 has arrived with at least one vehicle, attacking now", _supportName); - _qrfHasArrived = true; - - private _textMarker = createMarker [format ["%1_text", _supportName], _posDestination]; - _textMarker setMarkerShape "ICON"; - _textMarker setMarkerType "mil_dot"; - _textMarker setMarkerText "QRF"; - if(_side == Occupants) then - { - _textMarker setMarkerColor colorOccupants; - } - else - { - _textMarker setMarkerColor colorInvaders; - }; - _textMarker setMarkerAlpha 0; - [_reveal, _posDestination, _side, "QRF", format ["%1_coverage", _supportName], _textMarker] spawn A3A_fnc_showInterceptedSupportCall; - }; - } - else - { - //QRF in combat, check if won - private _nearbyEnemyGroups = allGroups select {(side _x != _side) && (side _x != civilian) && {getPos (leader _x) distance2D _posDestination < 300}}; - if(count _nearbyEnemyGroups == 0) then - { - Info_1("%1 has arrived with at least one vehicle, attacking now", _supportName); - _qrfHasWon = true; - }; + private _curSoldiers = { !fleeing _x and _x call A3A_fnc_canFight } count _soldiers; + if (_curSoldiers <= count _soldiers * 0.25) exitWith { + ServerInfo_1("QRF %1 has been defeated, starting retreat", _supportName); + }; + if (time > _timeOut) exitWith { + // Still need this in case a QRF knows about enemies but isn't dealing with them + ServerInfo_1("QRF %1 has timed out, starting retreat", _supportName); }; - if(_qrfHasWon) exitWith {}; - - private _groupAlive = false; - { - private _index = (units _x) findIf {[_x] call A3A_fnc_canFight}; - if(_index != -1) exitWith - { - _groupAlive = true; - }; - } forEach _groups; - if !(_groupAlive) exitWith - { - Info_1("%1 has been eliminated, starting despawn routines", _supportName); - [_side, 10, 60] remoteExec ["A3A_fnc_addAggression", 2]; + if (_travelling and {-1 != _cargoGroups findif { leader _x distance2d _targPos < 300 }}) then { + _travelling = false; + _searchTime = time + 600; // give it 10 minutes to find a target + ServerDebug_1("%1 is approaching its objective", _supportName); }; - sleep 15; - if(_endTime < time) exitWith - { - Info_1("%1 timed out without winning or losing, starting despawn routines", _supportName); + if (!_travelling and {time > _searchTime}) then { + // objNull distance2d [anything] is 1e10 + if (-1 == _cargoGroups findIf { (leader _x findNearestEnemy _targPos) distance2d _targPos < 500 }) then { + ServerInfo_1("%1 has no nearby targets, returning", _supportName); + break; + }; }; + + // Attempt to flip marker in case it was left empty + if (!isNil "_nearMrk") then { [_nearMrk, sidesX getVariable _nearMrk] remoteExec ["A3A_fnc_zoneCheck", 2] }; + sleep 30; }; -{ - [_x] spawn A3A_fnc_VEHDespawner; -} forEach _vehicles; +{ [_x] spawn A3A_fnc_VEHDespawner } forEach _vehicles; +{ [_x] spawn A3A_fnc_enemyReturnToBase } forEach _crewGroups; { - [_x] spawn A3A_fnc_groupDespawner; -} forEach _groups; - -private _waitTime = 3 - (tierWar - 1); -if(_waitTime < 0) then {_waitTime = 0}; -[_supportName, _side, _waitTime] spawn A3A_fnc_endSupport; + if (isNil "_nearMrk") then { [_x] spawn A3A_fnc_enemyReturnToBase; continue }; + [_x, _nearMrk] spawn A3A_fnc_enemyReturnToBase; + sleep 10; +} forEach _cargoGroups; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_SAM.sqf b/A3A/addons/core/functions/Supports/fn_SUP_SAM.sqf index 2daa1f33cf..f7f495def0 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_SAM.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_SAM.sqf @@ -1,146 +1,74 @@ -params ["_side", "_timerIndex", "_supportObj", "_supportName"]; - -/* Prepares the SAM launcher and marker - - Execution on: Server - - Scope: Internal - - Params: - _side: SIDE : The side for which the support should be called in - _timerIndex: NUMBER - _supportPos: POS - _supportName: STRING : The call name of the support - - Returns: - The name of the marker, covering the whole support area +/* Sets up a SAM support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + Target of the support. "false" creates with no initial target + Target position for support. + Reveal value 0-1, higher values mean more information provided about support + Optional setup delay time in seconds, otherwise will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private _supportPos = getPos _supportObj; -private _spawnPos = []; -private _availableAirports = airportsX select -{ - (getMarkerPos _x distance2D _supportPos <= 8000) && - (getMarkerPos _x distance2D _supportPos > 1500) && - (sidesX getVariable [_x, sideUnknown] == _side) && - (spawner getVariable _x == 2) -}; +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; -if(count _availableAirports == 0) exitWith +private _airports = []; +private _weights = []; { - Info("No airport suitable to place SAM on it"); - ""; -}; - -//Check which airports are able to fire at the given position -private _finalAirports = []; -{ - private _airportPos = getMarkerPos _x; - private _dir = _airportPos getDir _supportPos; - private _intercectPoint = _airportPos getPos [250, _dir]; - _intercectPoint = _intercectPoint vectorAdd [0, 0, 300]; - if !(terrainIntersect [_intercectPoint, _supportPos]) then - { - _finalAirports pushBack _x; + private _pos = markerPos _x; + private _dist = _pos distance2D _targPos; + if (_dist > 8000 or _dist < 1500) then {continue}; + if (sidesX getVariable [_x,sideUnknown] != _side) then {continue}; + if (spawner getVariable _x == 0) then {continue}; // don't need spawn places, so this is fine + + if (_target isEqualType objNull and {!isNull _target}) then { + private _targDir = _pos getDir _targPos; + private _intersectPoint = (ATLtoASL _pos) getPos [250, _targDir] vectorAdd [0,0,300]; + if (terrainIntersectASL [_intersectPoint, getPosASL _target]) then {continue}; }; -} forEach _availableAirports; -private _spawnMarker = ""; + _airports pushBack _x; + _weights pushBack (1 / _dist^2); +} forEach airportsX; -if(count _finalAirports == 0) then -{ - _spawnMarker = [_availableAirports, _supportPos] call BIS_fnc_nearestPosition; -} -else -{ - if(count _finalAirports == 1) then - { - _spawnMarker = _finalAirports select 0; - } - else - { - _spawnMarker = [_finalAirports, _supportPos] call BIS_fnc_nearestPosition; - }; +if (_airports isEqualTo []) exitWith { + Error_1("No suitable airport found for %1", _supportName); -1; }; -private _coverageMarker = createMarker [format ["%1_coverage", _supportName], _supportPos]; -_coverageMarker setMarkerShape "ELLIPSE"; -_coverageMarker setMarkerBrush "Grid"; -if(_side == Occupants) then -{ - _coverageMarker setMarkerColor colorOccupants; -} -else -{ - _coverageMarker setMarkerColor colorInvaders; -}; -_coverageMarker setMarkerSize [8000, 8000]; -_coverageMarker setMarkerAlpha 0; +private _airport = _airports selectRandomWeighted _weights; +private _launcherType = ["B_SAM_System_03_F", "O_SAM_System_04_F"] select (_side == Invaders); +private _launcher = [_launcherType, markerPos _airport, 50, 5, true] call A3A_fnc_safeVehicleSpawn; -if(_side == Occupants) then -{ - occupantsSAMTimer set [0, time + (3600 * 2)]; -} -else -{ - invadersSAMTimer set [0, time + (3600 * 2)]; -}; +private _group = [_side, _launcher] call A3A_fnc_createVehicleCrew; +[_launcher, _side, _resPool] call A3A_fnc_AIVEHInit; +_group deleteGroupWhenEmpty true; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach units _group; -private _spawnPos = getMarkerPos _spawnMarker; -private _launcher = objNull; -if(_side == Occupants) then -{ - _launcher = ["B_SAM_System_03_F", _spawnPos, 50, 5, true] call A3A_fnc_safeVehicleSpawn; -} -else -{ - _launcher = ["O_SAM_System_04_F", _spawnPos, 50, 5, true] call A3A_fnc_safeVehicleSpawn; -}; -[_side, _launcher] call A3A_fnc_createVehicleCrew; -_launcher setVariable ["side", _side]; +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (350 - 15*tierWar - 1*_aggro) }; -_launcher addEventHandler ["Fired", -{ - params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"]; - [_unit, _projectile] spawn - { - params ["_unit", "_projectile"]; - private _target = _unit getVariable ["currentTarget", objNull]; - if (isNull _target) exitWith {}; - - private _textMarker = createMarker [format ["%1_text_%2", _supportName, _rounds], getPos _target]; - _textMarker setMarkerShape "ICON"; - _textMarker setMarkerType "mil_objective"; - _textMarker setMarkerText "SAM Target"; - - if(_unit getVariable "side" == Occupants) then - { - _textMarker setMarkerColor colorOccupants; - } - else - { - _textMarker setMarkerColor colorInvaders; - }; - _textMarker setMarkerAlpha 0; - - _unit setVariable ["currentTextmarker", _textMarker]; - [_projectile, _textMarker] spawn - { - params ["_projectile", "_textMarker"]; - waitUntil {sleep 1; (isNull _projectile) || !{alive _projectile}}; - deleteMarker _textMarker; - }; - }; -}]; +private _targArray = []; +if (_target isEqualType objNull and {!isNull _target}) then { + A3A_supportStrikes pushBack [_side, "TARGET", _target, time + 1200, 1200, 200]; + _targArray = [_target, _targPos]; +}; -private _setupTime = 1368 - ((tierWar - 1) * 102); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); +// name, side, suppType, center, radius, [target, targpos] +private _suppData = [_supportName, _side, "SAM", _targPos, 8000, _targArray]; +A3A_activeSupports pushBack _suppData; +[_suppData, _launcher, _group, _delay, _reveal] spawn A3A_fnc_SUP_SAMRoutine; -[_sleepTime, _launcher, _side, _supportName] spawn A3A_fnc_SUP_SAMRoutine; +[_reveal, _side, "SAM", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _result = [_coverageMarker, _minSleepTime, _setupTime]; -_result; +// Vehicle cost + extra support cost for balance +//(A3A_vehicleResourceCosts get _launcherType) + 100; +200; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_SAMAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_SAMAvailable.sqf index 8459b6d47c..160842dea6 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_SAMAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_SAMAvailable.sqf @@ -1,37 +1,22 @@ -params ["_side", "_position"]; +/* Get SAM support selection weight against target -if(tierWar < 7) exitWith {-1}; +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "SAM" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -if !(allowUnfairSupports) exitWith {-1}; -private _loadedTemplate = if (_side isEqualTo Occupants) then {A3A_Occ_template} else {A3A_Inv_template}; -if (toLower _loadedTemplate isEqualTo "VN") exitWith {-1}; //dont allow with VN +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -if({sidesX getVariable [_x, sideUnknown] == _side} count airportsX == 0) exitWith {-1}; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -if(airportsX findIf {(getMarkerPos _x) distance2D _position < 8000} == -1) exitWith {-1}; +if !(_target isKindOf "Air") exitWith { 0 }; // can't hit anything except air -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/5)) + 1; -private _supportTimer = if(_side == Occupants) then {occupantsSAMTimer} else {invadersSAMTimer}; +// Should limit to certain templates? -if(count _supportTimer < _playerAdjustment) then -{ - _timerIndex = count _supportTimer; - for "_i" from ((count _supportTimer) + 1) to _playerAdjustment do - { - _supportTimer pushBack -1; - }; -} -else -{ - _timerIndex = _supportTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; -}; - -_timerIndex; +1; // maybe set higher, especially if it's fixed-wing aircraft? diff --git a/A3A/addons/core/functions/Supports/fn_SUP_SAMRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_SAMRoutine.sqf index a58ad4e887..50e21c035f 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_SAMRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_SAMRoutine.sqf @@ -1,53 +1,96 @@ -params ["_sleepTime", "_launcher", "_side", "_supportName"]; +/* Maintains SAM launcher support + +Environment: Server, must be spawned + +Arguments: + Active support data, see initSupports + SAM launcher vehicle + Crew group for vehicle + Delay time in seconds + Amount of information to reveal to rebels, 0-1 +*/ + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -sleep _sleepTime; -private _rounds = 4; -private _onlineTime = 900; +params ["_suppData", "_launcher", "_group", "_delay", "_reveal"]; +_suppData params ["_supportName", "_side", "_suppType", "_center", "_radius", "_suppTarget"]; + +sleep _delay; -while {_onlineTime > 0} do +_launcher addEventHandler ["Fired", { + params ["_launcher", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"]; + _launcher setVariable ["A3A_currentMissile", _projectile]; +}]; + +private _targetObj = objNull; +private _timeout = time + 900; +private _targTimeout = 0; +private _acquisition = 0; +private _missiles = 4; +while {true} do { - private _targetList = server getVariable [format ["%1_targets", _supportName], []]; - if (count _targetList > 0) then + // check if launcher/crew are intact + if !(canFire _launcher and gunner _launcher call A3A_fnc_canFight) exitWith { + Info_1("%1 has been destroyed or disabled, aborting routine", _supportName); + }; + + // check if we're past the active time/missiles + if (time > _timeout or _missiles <= 0) exitWith { + Info_1("%1 has timed out or run out of missiles, aborting", _supportName); + }; + + if (isNull _targetObj) then { - private _target = _targetList deleteAt 0; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - - private _targetParams = _target select 0; - private _reveal = _target select 1; - - private _targetObj = _targetParams select 0; - private _precision = _targetParams select 1; - - private _dir = _launcher getDir _targetObj; - private _pos = _launcher getPos [250, _dir]; - _pos = _pos vectorAdd [0,0,300]; - if !(terrainIntersect [_pos vectorAdd [0, 0, 50], getPos _targetObj]) then - { - _launcher setVariable ["_currentTarget", _targetObj]; - _launcher doWatch _pos; - _launcher reveal [_targetObj, 4]; - sleep 10; - _launcher fireAtTarget [_targetObj]; - _launcher doWatch objNull; - sleep 1; - [_reveal, getPos _targetObj, _side, "SAM", _launcher getVariable ["currentTextmarker", ""], ""] spawn A3A_fnc_showInterceptedSupportCall; - _rounds = _rounds - 1; - _onlineTime = _onlineTime - 11; + if (_suppTarget isEqualTo []) then { sleep 5; continue }; + + // New target sent + _targetObj = _suppTarget select 0; + if !(alive _targetObj) exitWith { + _suppTarget resize 0; + Debug_1("%1 skips target, as it is already dead", _supportName); + continue; }; + Debug_2("Next target for %2 is %1", _suppTarget, _supportName); + + [_reveal, getPosATL _targetObj, _side, "SAM", _targetObj, 60] spawn A3A_fnc_showInterceptedSupportCall; + + _targTimeout = (time + 120); + _acquisition = 0; }; - if(_rounds <= 0) exitWith - { - Info_1("%1 has no missiles left to fire, aborting", _supportName); + //Target no longer valid + if (!canMove _targetObj or time > _targTimeout) then { + Debug_1("%1 target lost or destroyed, returning to idle", _supportName); + _suppTarget resize 0; + _targetObj = objNull; + _launcher doWatch objNull; + continue; }; - sleep 10; - _onlineTime = _onlineTime - 10; + // Update acquisition depending on whether path to target is blocked + private _dir = _launcher getDir _targetObj; + private _intercept = (getPosASL _launcher) getPos [250, _dir] vectorAdd [0,0,300]; + private _isBlocked = terrainIntersectASL [_intercept, getPosASL _targetObj]; + _acquisition = _acquisition + ([0.1, -0.1] select _isBlocked); + _acquisition = 1 min _acquisition max 0; + _launcher doWatch _intercept; + if (_acquisition < 1) then { sleep 1; continue }; + + // wait for previous missile to have effect (or not) + if (alive (_launcher getVariable ["A3A_currentMissile", objNull])) then { sleep 1; continue }; + + // Actually fire + Debug("Firing at target"); + _launcher reveal [_targetObj, 4]; // does this do anything? + _launcher fireAtTarget [_targetObj]; + [_reveal, getPosATL _targetObj, _side, "SAM", _targetObj, 60] spawn A3A_fnc_showInterceptedSupportCall; + _missiles = _missiles - 1; + _targTimeout = (time + 120); + sleep 1; }; -waitUntil {sleep 10; allPlayers findIf {getPos _x distance2D (getPos _launcher) < 1000} == -1}; -deleteVehicle _launcher; +_suppData set [4, 0]; // zero radius to signal termination -[_supportName, _side] spawn A3A_fnc_endSupport; +[_launcher] spawn A3A_fnc_vehDespawner; +[_group] spawn A3A_fnc_groupDespawner; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_UAV.sqf b/A3A/addons/core/functions/Supports/fn_SUP_UAV.sqf new file mode 100644 index 0000000000..8beee563f2 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_UAV.sqf @@ -0,0 +1,44 @@ +/* Sets up a UAV support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + or Target of the support. Not used here. + Target position for support. + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + +private _airport = [_side, _targPos] call A3A_fnc_availableBasesAir; +if (isNil "_airport") exitWith { Debug_1("No airport found for %1 support", _supportName); -1; }; + +private _planeType = selectRandom (Faction(_side) get "uavsAttack"); + +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggro) }; + +// Well, it doesn't actually hit anything... +// ["_side", "_supptype", "_basetype", "_target", "_endtime", "_duration", "_power"] +//A3A_supportStrikes pushBack [_side, "UAV", "TARGET", _target, time + 1200, 1200, 200]; + +// name, side, suppType, center, radius, targets +private _suppData = [_supportName, _side, "UAV", _targPos, 1000, [objNull, _targPos]]; +A3A_activeSupports pushBack _suppData; +[_suppData, _resPool, _airport, _planeType, _delay, _reveal] spawn A3A_fnc_SUP_UAVRoutine; + +[_reveal, _side, "UAV", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; + +// Uh, do these have a vehicle cost atm? +(150+0); // resource cost of support diff --git a/A3A/addons/core/functions/Supports/fn_SUP_UAVRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_UAVRoutine.sqf new file mode 100644 index 0000000000..f11ecf4c84 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_UAVRoutine.sqf @@ -0,0 +1,87 @@ +/* Creates and maintains UAV support + +Environment: Server, must be spawned + +Arguments: + Active support data, see initSupports + Resource pool of support, "attack" or "defence" + Marker name of source airport + Target position for airstrike + Classname of aircraft to use + Delay time in seconds + Amount of information to reveal to rebels, 0-1 +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_suppData", "_resPool", "_airport", "_planeType", "_sleepTime", "_reveal"]; +_suppData params ["_supportName", "_side", "_suppType", "_suppCenter", "_suppRadius", "_suppTarget"]; +// Doesn't actually process targets at the moment, it's just a dummy + +//Sleep to simulate preparation time +sleep _sleepTime; + +private _spawnPos = markerPos _airport vectorAdd [0,0,300]; +private _uav = createVehicle [_planeType, _spawnPos, [], 0, "FLY"]; +[_side, _uav] call A3A_fnc_createVehicleCrew; +_groupVeh = group driver _uav; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach (crew _uav); // arguable +[_uav, _side, _resPool] call A3A_fnc_AIVEHinit; + +_wp = _groupVeh addWayPoint [_suppCenter, 0]; +_wp setWaypointBehaviour "AWARE"; +_wp setWaypointType "SAD"; +_groupVeh setCurrentWaypoint _wp; +//_uav flyInHeight 500; // maybe not necessary if we lock the waypoint +_groupVeh lockWP true; // prevent exiting the SAD waypoint + +// do we just run for 20mins and then RTB? +private _timeout = time + 1200; +private _enemySide = [Invaders, Occupants] select (_side == Invaders); +while {time < _timeout && canMove _uav} do +{ + waitUntil { sleep 5; _uav distance2d _suppCenter < 500 }; + + private _friends = units _side inAreaArray [_suppCenter, 1000, 1000]; + private _friendGroups = allGroups select {(leader _x in _friends) and {isNull objectParent leader _x} }; + + // Choose four random enemies to spot + private _allEnemies = (units teamPlayer + units _enemySide) inAreaArray [_suppCenter, 500, 500]; + private _spottedEnemies = []; + for "_i" from 0 to 3 do { + if (count _allEnemies == 0) exitWith {}; + private _index = floor random (count _allEnemies); + _spottedEnemies pushBack (_allEnemies # _index); + _allEnemies deleteAt _index; + }; + { + private _group = _x; + //or: [[_group, _spottedEnemies], { { _this#0 reveal [_x, 2] } forEach _this#1 }] remoteExec ["call", leader _group]; + { [_group, [_x, 2]] remoteExec ["reveal", leader _group] } forEach _spottedEnemies; + } forEach _friendGroups; + + sleep 60; +}; + + +_suppData set [4, 0]; // Set activesupport radius to zero, prevents adding further targets + +[_groupVeh] spawn A3A_fnc_groupDespawner; +[_uav] spawn A3A_fnc_vehDespawner; + +//Have the plane fly back home +if (canMove _uav) then +{ + while {count waypoints _groupVeh > 0} do { deleteWaypoint [_groupVeh, 0] }; + private _wpBase = _groupVeh addWaypoint [markerPos _airport, 0]; + _wpBase setWaypointSpeed "NORMAL"; + _wpBase setWaypointBehaviour "CARELESS"; + _groupVeh setCurrentWaypoint _wpBase; + + private _timeout = time + (_uav distance2d _spawnPos) / 20; + waitUntil { sleep 2; (currentWaypoint _groupVeh != 0) or (time > _timeout) }; + if (time > _timeout) exitWith {}; + { deleteVehicle _x } forEach (units _groupVeh); + deleteVehicle _uav; +}; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_airstrike.sqf b/A3A/addons/core/functions/Supports/fn_SUP_airstrike.sqf index 1be829a6a8..0c036a57f9 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_airstrike.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_airstrike.sqf @@ -1,49 +1,46 @@ -params ["_side", "_timerIndex", "_supportPos", "_supportName"]; - -/* Sets up the data for the airstrike support - - Execution on: Server - - Scope: Internal - - Params: - _side: SIDE : The side of which the airstrike should be send - _timerIndex: NUMBER : The number of the support timer - _supportPos: POSITION : The position to which the airstrike should be carried out - _supportName: STRING : The callsign of the support - - Returns: - The name of the target marker, empty string if not created +/* Sets up an airstrike support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here + Target of the support. False for none + Target position for airstrike + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure */ + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -private _airport = [_supportPos, _side] call A3A_fnc_findAirportForAirstrike; -if(_airport == "") exitWith -{ - Info_1("No airport found for %1 support", _supportName); - ["", 0, 0]; -}; +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; -private _coverageMarker = createMarkerLocal [format ["%1_coverage", _supportName], _supportPos]; -_coverageMarker setMarkerShapeLocal "ELLIPSE"; -_coverageMarker setMarkerSizeLocal [200, 200]; -_coverageMarker setMarkerAlphaLocal 0; +private _airport = [_side, _targPos] call A3A_fnc_availableBasesAir; +if(isNil "_airport") exitWith { Debug_1("No airport found for %1 support", _supportName); -1; }; private _aggroValue = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; private _weightHE = if (_side == Occupants) then {2} else {1}; // occupants less likely to use the wide-area stuff private _weightCluster = 0 max ((tierWar - 5) / 10 + _aggroValue / 200); // 1 at max warlevel and aggro private _weightNapalm = if (napalmEnabled) then {_weightCluster} else {0}; - private _bombType = selectRandomWeighted ["HE", _weightHE, "CLUSTER", _weightCluster, "NAPALM", _weightNapalm]; -Info_1("Airstrike will be carried out with bombType %1", _bombType); +private _planeType = selectRandom (Faction(_side) get "vehiclesPlanesCAS"); +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggroValue) }; + +Debug_3("Airstrike will be carried out with aircraft type %1, bombType %2 and setup time %3", _planeType, _bombType, _delay); + +// ["_side", "_basetype", "_target", "_endtime", "_duration", "_power"] +A3A_supportStrikes pushBack [_side, "AREA", _targPos, time + 1200, 1200, 200]; -private _setupTime = 1200 - ((tierWar - 1) * 110); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); +[_supportName, _side, _delay, _targPos, _airport, _resPool, _planeType, _bombType, _reveal] spawn A3A_fnc_SUP_airstrikeRoutine; -[_side, _timerIndex, _sleepTime, _bombType, _airport, _supportPos, _supportName] spawn A3A_fnc_SUP_airstrikeRoutine; +[_reveal, _side, "AIRSTRIKE", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _result = [_coverageMarker, _minSleepTime, _setupTime]; -_result; +// Return resource cost of support (planecost + 0) +A3A_vehicleResourceCosts get _planeType; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_airstrikeAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_airstrikeAvailable.sqf index 5f78512e42..77afa1f7dc 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_airstrikeAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_airstrikeAvailable.sqf @@ -1,57 +1,23 @@ -params ["_side"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -if(tierWar < 3) exitWith {-1}; +/* Get airstrike support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "AIRSTRIKE" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -//Vehicles not available, block support -if (_faction get "vehiclesPlanesCAS" isEqualTo []) exitWith {-1}; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -//Select a timer index and the max number of timers available -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/6)) + 1; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -//Search for a timer which allows the support to be fired -if(_side == Occupants) then -{ - if(count occupantsAirstrikeTimer < _playerAdjustment) then - { - _timerIndex = count occupantsAirstrikeTimer; - for "_i" from ((count occupantsAirstrikeTimer) + 1) to _playerAdjustment do - { - occupantsAirstrikeTimer pushBack -1; - }; - } - else - { - _timerIndex = occupantsAirstrikeTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; -if(_side == Invaders) then -{ - if(count invadersAirstrikeTimer < _playerAdjustment) then - { - _timerIndex = count invadersAirstrikeTimer; - for "_i" from ((count invadersAirstrikeTimer) + 1) to _playerAdjustment do - { - invadersAirstrikeTimer pushBack -1; - }; - } - else - { - _timerIndex = invadersAirstrikeTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; +if (_target isKindOf "Air") exitWith { 0 }; // airstrikes can't hit air -_timerIndex; +// balance against carpetbombs from tier 6+ +if (tierWar < 3) exitWith { 0 }; +if (tierWar < 6 or !("CARPETBOMBS" in _availTypes)) exitWith { 1 }; +1 - (tierWar - 5) / 10; // 90% at tier 6 to 50% at tier 10 diff --git a/A3A/addons/core/functions/Supports/fn_SUP_airstrikeRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_airstrikeRoutine.sqf index 04becd6c54..756ca266cf 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_airstrikeRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_airstrikeRoutine.sqf @@ -1,109 +1,79 @@ -params ["_side", "_timerIndex", "_sleepTime", "_bombType", "_airport", "_targetPos", "_supportName"]; +/* Send airstrike against target + +Environment: Server, must be spawned + +Arguments: + Unique support name (mostly for logging) + Side to send support from + Delay time in seconds + Target position for airstrike + Marker name of source airport + Resource pool of support, "attack" or "defence" + Classname of aircraft to use + Bomb type to use, "HE", "CLUSTER" or "NAPALM" + Amount of information to reveal to rebels, 0-1 + +*/ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -//Sleep to simulate preparetion time -while {_sleepTime > 0} do -{ - sleep 1; - _sleepTime = _sleepTime - 1; - if((spawner getVariable _airport) != 2) exitWith {}; -}; -private _faction = Faction(_side); -private _plane = selectRandom (_faction get "vehiclesPlanesCAS"); -private _crewUnits = _faction get "unitPilot"; -private _isHelicopter = _plane isKindOf "Helicopter"; +params ["_supportName", "_side", "_sleepTime", "_targetPos", "_airport", "_resPool", "_planeType", "_bombType", "_reveal"]; + +//Sleep to simulate preparation time +sleep _sleepTime; +private _isHelicopter = _planeType isKindOf "Helicopter"; private _spawnPos = (getMarkerPos _airport) vectorAdd [0, 0, if (_isHelicopter) then {150} else {500}]; -private _strikePlane = createVehicle [_plane, _spawnPos, [], 0, "FLY"]; // FLY forces 100m alt +private _plane = createVehicle [_planeType, _spawnPos, [], 0, "FLY"]; // FLY forces 100m alt private _targDir = _spawnPos getDir _targetPos; -_strikePlane setDir _targDir; -_strikePlane setPosATL _spawnPos; // setPosATL kills velocity -_strikePlane setVelocityModelSpace [0, 100, 0]; - -private _strikeGroup = createGroup _side; -private _pilot = [_strikeGroup, _crewUnits, getPos _strikePlane] call A3A_fnc_createUnit; -_pilot moveInDriver _strikePlane; -_strikeGroup deleteGroupWhenEmpty true; - -_strikePlane disableAI "TARGET"; -_strikePlane disableAI "AUTOTARGET"; - -private _timerArray = if(_side == Occupants) then {occupantsAirstrikeTimer} else {invadersAirstrikeTimer}; -_timerArray set [_timerIndex, time + 1800]; - -//Setting up the EH for support destruction -// Could probably just use NATOinit/AIVEHinit -_strikePlane addEventHandler -[ - "Killed", - { - params ["_strikePlane"]; - ["TaskSucceeded", ["", "Airstrike Vessel Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - [_strikePlane] spawn A3A_fnc_postMortem; - [(_strikePlane getVariable "side"), 20, 45] remoteExec ["A3A_fnc_addAggression", 2]; - } -]; - -_pilot addEventHandler -[ - "Killed", - { - params ["_unit"]; - ["TaskSucceeded", ["", "Airstrike crew killed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - [_unit] spawn A3A_fnc_postMortem; - } -]; - -private _targetList = server getVariable [format ["%1_targets", _supportName], []]; -private _reveal = _targetList select 0 select 1; - -private _markerColor = if(_side == Occupants) then {colorOccupants} else {colorInvaders}; - -private _targetMarker = createMarkerLocal [format ["%1_target", _supportName], _targetPos]; -_targetMarker setMarkerShapeLocal "ELLIPSE"; -_targetMarker setMarkerBrushLocal "Grid"; -_targetMarker setMarkerSizeLocal [25, 100]; -_targetMarker setMarkerDirLocal _targDir; -_targetMarker setMarkerColorLocal _markerColor; -_targetMarker setMarkerAlphaLocal 0; - -private _textMarker = createMarkerLocal [format ["%1_text", _supportName], _targetPos]; -_textMarker setMarkerShapeLocal "ICON"; -_textMarker setMarkerTypeLocal "mil_dot"; -_textMarker setMarkerTextLocal "Airstrike"; -_textMarker setMarkerColorLocal _markerColor; -_textMarker setMarkerAlphaLocal 0; - -[_reveal, _targetPos, _side, "AIRSTRIKE", _targetMarker, _textMarker] spawn A3A_fnc_showInterceptedSupportCall; -//[_side, format ["%1_coverage", _supportName]] spawn A3A_fnc_clearTargetArea; +_plane setDir _targDir; +_plane setPosATL _spawnPos; // setPosATL kills velocity +_plane setVelocityModelSpace [0, 100, 0]; +[_plane, _side, _resPool] call A3A_fnc_AIVEHInit; -_strikePlane flyInHeight 150; -private _minAltASL = (ATLToASL [_targetPos select 0, _targetPos select 1, 0])#2 +150; -_strikePlane flyInHeightASL [_minAltASL, _minAltASL, _minAltASL]; -Debug_2("Fly height ASL: %1 | Target hight: %2", _minAltASL, _targetPos); +private _group = [_side, _plane] call A3A_fnc_createVehicleCrew; +_group deleteGroupWhenEmpty true; +{ + [_x, nil, false, _resPool] call A3A_fnc_NATOinit; + _x disableAI "TARGET"; + _x disableAI "AUTOTARGET"; +} forEach units _group; + +// Should we really have these? +_plane addEventHandler ["Killed", { + params ["_plane"]; + ["TaskSucceeded", ["", "Airstrike Vessel Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; +}]; + +//["_reveal", "_position", "_side", "_supportType", "_markerType", "_markerLifeTime"] +[_reveal, _targetPos, _side, "Airstrike", 150, 120] spawn A3A_fnc_showInterceptedSupportCall; +//[_side, format ["%1_coverage", _supportName]] spawn A3A_fnc_clearTargetArea; -private _startBombPosition = _targetPos getPos [100, _targDir + 180]; -_startBombPosition set [2, 150]; -private _endBombPosition = _targetPos getPos [100, _targDir]; -_endBombPosition set [2, 150]; //Determine speed and bomb count on aggression private _aggroValue = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; -private _flightSpeed = ["LIMITED", "NORMAL", "FULL"] select (round random [1, _aggroValue / 50, 0]); private _bombCount = [2, 3, 4] select (round random [1, _aggroValue / 50, 0]); if (_bombType == "HE") then {_bombCount = _bombCount * 2}; -private _bombParams = [_strikePlane, _bombType, _bombCount, 200]; - +private _bombParams = [_plane, _bombType, _bombCount, 200]; +private _flightSpeed = ["LIMITED", "NORMAL", "FULL"] select (round random [1, _aggroValue / 50, 0]); if (_isHelicopter) then {_flightSpeed = "FULL"}; Info_3("Airstrike %1 will be carried out with %2 bombs at %3 speed", _supportName, _bombCount, toLower _flightSpeed); -private _wp2 = _strikeGroup addWaypoint [_startBombPosition, 0]; +_plane flyInHeight 150; +private _minAltASL = (ATLToASL [_targetPos select 0, _targetPos select 1, 0])#2 +150; +_plane flyInHeightASL [_minAltASL, _minAltASL, _minAltASL]; + +private _startBombPosition = _targetPos getPos [100, _targDir + 180]; +_startBombPosition set [2, 150]; +private _endBombPosition = _targetPos getPos [100, _targDir]; +_endBombPosition set [2, 150]; + +private _wp2 = _group addWaypoint [_startBombPosition, 0]; _wp2 setWaypointType "MOVE"; _wp2 setWaypointSpeed _flightSpeed; _wp2 setWaypointBehaviour "CARELESS"; -[_startBombPosition, driver _strikePlane, _bombParams] spawn +[_startBombPosition, driver _plane, _bombParams] spawn { params ["_pos", "_pilot", "_bombParams"]; waitUntil {sleep 1; ((_pos distance2D _pilot) < 500) || {isNull (objectParent _pilot)}}; @@ -113,31 +83,26 @@ _wp2 setWaypointBehaviour "CARELESS"; _bombParams spawn A3A_fnc_airbomb; }; -private _wp3 = _strikeGroup addWaypoint [_endBombPosition, 1]; +private _wp3 = _group addWaypoint [_endBombPosition, 1]; _wp3 setWaypointType "MOVE"; _wp3 setWaypointSpeed _flightSpeed; _wp3 setWaypointBehaviour "CARELESS"; -private _wp4 = _strikeGroup addWaypoint [getMarkerPos _airport, 2]; +private _wp4 = _group addWaypoint [getMarkerPos _airport, 2]; _wp4 setWaypointType "MOVE"; _wp4 setWaypointSpeed "FULL"; private _timeout = time + (_targetPos distance _spawnPos) / 20; -waitUntil { sleep 2; (currentWaypoint _strikeGroup == 4) or (time > _timeOut) }; +waitUntil { sleep 2; (currentWaypoint _group > 3) or (time > _timeOut) }; // could potentially "optimize" with this, or an upper-bounds speed version: -//sleep ((time - _timeout) min (_targetPos distance _strikePlane / (speed _strikePlane / 3.6))) +//sleep ((time - _timeout) min (_targetPos distance _plane / (speed _plane / 3.6))) if (time >_timeOut) then { Info_1("Plane for %1 did not return before timeout", _supportName); - // should this be done anyway? Depends how reliable the waypoints are... - if !(canMove _strikePlane) then { _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 3600] }; - [_strikeGroup] spawn A3A_fnc_groupDespawner; - [_strikePlane] spawn A3A_fnc_vehDespawner; + [_group] spawn A3A_fnc_groupDespawner; + [_plane] spawn A3A_fnc_vehDespawner; } else { - deleteVehicle _pilot; - deleteVehicle _strikePlane; + Info_1("Cleaning up %1", _supportName); + { deleteVehicle _x } forEach units _group; + deleteVehicle _plane; }; - -deleteMarker _targetMarker; -deleteMarker _textMarker; -[_supportName, _side, 5] spawn A3A_fnc_endSupport; // hold the coverage marker for a bit diff --git a/A3A/addons/core/functions/Supports/fn_SUP_artillery.sqf b/A3A/addons/core/functions/Supports/fn_SUP_artillery.sqf new file mode 100644 index 0000000000..a2316bdbbe --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_artillery.sqf @@ -0,0 +1,67 @@ +/* Sets up an artillery support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + Target of the support, or objNull for position strike. "false" creates with no initial target + Target position for initial artillery strike + 0-1, higher values more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, -1 for failed +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + +private _faction = Faction(_side); +private _vehType = selectRandom (_faction get "vehiclesArtillery"); +private _shellType = ((_faction get "magazines") get _vehType)#0; +([_vehType, _shellType] call A3A_fnc_getArtilleryRanges) params ["_minRange", "_maxRange"]; + +Info_6("Artillery support %1 against %2 will be carried out by a %3 with %4 mags, min range %5 max %6", _supportName, _targPos, _vehType, _shellType, _minRange, _maxRange); + +private _possibleBases = airportsX select +{ + (sidesX getVariable [_x, sideUnknown] == _side) && + {(markerPos _x distance2D _targPos <= _maxRange) && + {(markerPos _X distance2D _targPos > _minRange) && + {spawner getVariable _x == 2}}} +}; +if(count _possibleBases == 0) exitWith { Debug("Couldn't find a suitable base for artillery"); -1 }; +private _base = selectRandom _possibleBases; + +// Spawn in artillery +private _vehicle = [_vehType, markerPos _base, 50, 5, true] call A3A_fnc_safeVehicleSpawn; +_vehicle setVariable ["shellType", _shellType]; +[_vehicle, _side, _resPool] call A3A_fnc_AIVehInit; + +// Spawn in crew +private _group = [_side, _vehicle] call A3A_fnc_createVehicleCrew; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach units _group; +_group deleteGroupWhenEmpty true; + +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (300 - 15*tierWar - 1*_aggro) }; + +private _targArray = []; +if (_target isEqualType objNull) then { + A3A_supportStrikes pushBack [_side, "AREA", _targPos, time + 20*60, 20*60, 200]; + _targArray = [_target, _targPos]; +}; + +// name, side, suppType, pos, radius, remTargets, targets +private _suppData = [_supportName, _side, "ARTILLERY", markerPos _base, _maxRange, _targArray, _minRange]; +A3A_activeSupports pushBack _suppData; +[_suppData, _vehicle, _group, _delay, _reveal] spawn A3A_fnc_SUP_mortarRoutine; + +[_reveal, _side, "ARTILLERY", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; + +// Vehicle cost + extra support cost for balance +(A3A_vehicleResourceCosts get _vehType) + 200; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_artilleryAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_artilleryAvailable.sqf new file mode 100644 index 0000000000..d968fc48df --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_SUP_artilleryAvailable.sqf @@ -0,0 +1,22 @@ +/* Get artillery support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction + +Return value: + Weight value, 0 for unavailable or useless +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_target", "_side", "_maxSpend", "_availTypes"]; + +if (_target isKindOf "Air") exitWith { 0 }; // can't hit air + +// Weighted against mortars +if(tierWar < 5) exitWith { 0 }; +(tierWar - 4) / 8; // ~12.5% at tier 5, 75% at tier 10 diff --git a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombs.sqf b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombs.sqf index 081d42e670..42c2540a33 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombs.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombs.sqf @@ -1,50 +1,35 @@ -params ["_side", "_timerIndex", "_supportPos", "_supportName"]; - -/* Sets up the data for the airstrike support - - Execution on: Server - - Scope: Internal - - Params: - _side: SIDE : The side of which the airstrike should be send - _timerIndex: NUMBER : The number of the support timer - _supportPos: POSITION : The position to which the airstrike should be carried out - _supportName: STRING : The callsign of the support - - Returns: - The name of the target marker, empty string if not created +/* Sets up a carpet bombing support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here + Target of the support. False for none + Target position for airstrike + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure */ -private _fileName = "SUP_carpetBombs"; - -private _targetMarker = createMarker [format ["%1_coverage", _supportName], _supportPos]; -_targetMarker setMarkerShape "ELLIPSE"; -_targetMarker setMarkerBrush "Grid"; -_targetMarker setMarkerSize [100, 200]; -if(_side == Occupants) then -{ - _targetMarker setMarkerColor colorOccupants; -}; -if(_side == Invaders) then -{ - _targetMarker setMarkerColor colorInvaders; -}; -_targetMarker setMarkerAlpha 0; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -private _timerArray = if(_side == Occupants) then {occupantsCarpetBombTimer} else {invadersCarpetBombTimer}; -_timerArray set [_timerIndex, time + 10800]; +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; -private _carrierMarker = if (_side == Occupants) then {"NATOCarrier"} else {"CSATCarrier"}; -private _markerDir = getMarkerPos _carrierMarker getDir _supportPos; -_targetMarker setMarkerDir _markerDir; +private _aggroValue = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (350 - 15*tierWar - 1*_aggroValue) }; -private _setupTime = 1000 - ((tierWar - 1) * 90); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); +// ["_side", "_basetype", "_target", "_endtime", "_duration", "_power"] +A3A_supportStrikes pushBack [_side, "AREA", _targPos, time + 1200, 1200, 300]; +[_supportName, _side, _delay, _targPos, _reveal] spawn A3A_fnc_SUP_carpetBombsRoutine; -[_side, _sleepTime, _supportPos, _supportName] spawn A3A_fnc_SUP_carpetBombsRoutine; +[_reveal, _side, "CARPETBOMBS", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _result = [_targetMarker, _minSleepTime, _setupTime]; -_result; +// Return resource cost of support +200; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsAvailable.sqf index 1852a68ce0..263228feae 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsAvailable.sqf @@ -1,31 +1,22 @@ -params ["_side"]; +/* Get carpet bombing support selection weight against target -if(tierWar < 8) exitWith {-1}; +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "CARPETBOMB" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -if !(allowUnfairSupports) exitWith {-1}; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/8)) + 1; -private _supportTimer = if(_side == Occupants) then {occupantsCarpetBombTimer} else {invadersCarpetBombTimer}; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -if(count _supportTimer < _playerAdjustment) then -{ - _timerIndex = count _supportTimer; - for "_i" from ((count _supportTimer) + 1) to _playerAdjustment do - { - _supportTimer pushBack -1; - }; -} -else -{ - _timerIndex = _supportTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; -}; +if (_target isKindOf "Air") exitWith { 0 }; // can't hit air. What about isTouchingGround though? -_timerIndex; +// balance this one against airstrikes +if (tierWar < 6) exitWith { 0 }; +(tierWar - 5) / 10; // 10% at tier 6 to 50% at tier 10 diff --git a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsRoutine.sqf index d68e4a8f81..36a201d8db 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_carpetBombsRoutine.sqf @@ -1,29 +1,25 @@ -params ["_side", "_setupTime", "_position", "_supportName"]; +/* Carpet bomb target area -sleep _setupTime; +Environment: Server, must be spawned -private _targetList = server getVariable [format ["%1_targets", _supportName], []]; -private _reveal = _targetList select 0 select 1; +Arguments: + Unique support name (mostly for logging) + Side to send support from + Delay time in seconds + Target position for airstrike + Amount of information to reveal to rebels, 0-1 -private _textMarker = createMarker [format ["%1_text", _supportName], _position]; -_textMarker setMarkerShape "ICON"; -_textMarker setMarkerType "mil_dot"; -_textMarker setMarkerText "Carpet bombing"; -if(_side == Occupants) then -{ - _textMarker setMarkerColor colorOccupants; -} -else -{ - _textMarker setMarkerColor colorInvaders; -}; -_textMarker setMarkerAlpha 0; +*/ + +params ["_supportName", "_side", "_delay", "_targPos", "_reveal"]; -[_reveal, _position, _side, "CARPETBOMB", format ["%1_coverage", _supportName], _textMarker] spawn A3A_fnc_showInterceptedSupportCall; -[_side, format ["%1_coverage", _supportName]] spawn A3A_fnc_clearTargetArea; +sleep _delay; -private _carrierMarker = if (_side == Occupants) then {"NATOCarrier"} else {"CSATCarrier"}; -private _dir = getMarkerPos _carrierMarker getDir _position; +//["_reveal", "_position", "_side", "_supportType", "_markerType", "_markerLifeTime"] +[_reveal, _targPos, _side, "CarpetBombs", 200, 120] spawn A3A_fnc_showInterceptedSupportCall; + +private _carrierMarker = if (_side == Occupants) then {"NATO_carrier"} else {"CSAT_carrier"}; +private _dir = _targPos getDir markerPos _carrierMarker; private _vectorDir = [[1,0], _dir] call BIS_fnc_rotateVector2D; private _vectorRight = [[1,0], _dir + 90] call BIS_fnc_rotateVector2D; @@ -36,7 +32,7 @@ private _widthDistanceBetweenBombs = 40;//25; //The logic for bomb positioning, first bomb is always of tho, no idea why for "_counter" from 0 to 20 do { - private _dropPos = _position vectorAdd (_vectorDir vectorMultiply ((_counter * (_lengthDistanceBetweenBombs/5)) - (2.2 * _lengthDistanceBetweenBombs))); + private _dropPos = _targPos vectorAdd (_vectorDir vectorMultiply ((_counter * (_lengthDistanceBetweenBombs/5)) - (2.2 * _lengthDistanceBetweenBombs))); private _sideOffset = 0; if(_counter < 3) then @@ -63,7 +59,3 @@ for "_counter" from 0 to 20 do sleep 0.35; }; - -sleep 15; - -[_supportName, _side] spawn A3A_fnc_endSupport; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_mortar.sqf b/A3A/addons/core/functions/Supports/fn_SUP_mortar.sqf index e269a8a5ae..cdf0ce8c68 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_mortar.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_mortar.sqf @@ -1,199 +1,91 @@ -params ["_side", "_timerIndex", "_supportPos", "_supportName"]; - -/* Places the mortar used for fire support and initializes them - - Execution on: Server - - Scope: Internal - - Params: - _side: SIDE : The side for which the support should be called in - _timerIndex: NUMBER - _supportPos: POSITION : The position the mortar should be able to target - _supportName: STRING : The call name of the mortar support - - Returns: - The name of the marker, covering the whole support area +/* Sets up a mortar support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here. + Target of the support, or objNull for positional strike. "false" creates with no initial target + Target position for initial mortar strike + 0-1, higher values more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, -1 for failed */ + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() + +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; + private _faction = Faction(_side); -private _mortarType = selectRandom (_faction get "staticMortars"); +private _vehType = selectRandom (_faction get "staticMortars"); private _shellType = _faction get "mortarMagazineHE"; -private _isMortar = true; +([_vehType, _shellType] call A3A_fnc_getArtilleryRanges) params ["_minRange", "_maxRange"]; + +Info_6("Mortar support %1 against %2 will be carried out by a %3 with %4 mags, min range %5 max %6", _supportName, _targPos, _vehType, _shellType, _minRange, _maxRange); -//If war level between 6 and 8 there is a chance (25%/50%/75%) that it switches to a howitzer instead, above it howitzer is guaranteed -if((25 * (tierWar - 5)) > random 100) then +//Search for a outpost, that isnt more than 3 kilometers away, which isnt spawned +private _possibleBases = (outposts + airportsX) select { - _mortarType = selectRandom (_faction get "vehiclesArtillery"); - _shellType = ((_faction get "magazines") get _mortarType) #0; - _isMortar = false; + (sidesX getVariable [_x, sideUnknown] == _side) && + {(markerPos _x distance2D _targPos <= _maxRange) && + {(markerPos _X distance2D _targPos > _minRange) && + {spawner getVariable _x == 2}}} }; +if(count _possibleBases == 0) exitWith { Debug("No bases found for mortar support"); -1 }; -Info_3("Mortar support %1 will be carried out by a %2 with %3 mags", _supportName, _mortarType, _shellType); - -private _mortar = objNull; -private _spawnRadius = 5; +//Search for an outpost with a designated mortar position if possible +private _spawnRadius = 10; private _spawnPos = []; private _spawnDir = 0; - - -if(_isMortar) then { - //Search for a outpost, that isnt more than 2 kilometers away, which isnt spawned - private _possibleBases = (outposts + airportsX) select - { - (sidesX getVariable [_x, sideUnknown] == _side) && - {((getMarkerPos _x) distance2D _supportPos <= 3000) && - {spawner getVariable [_x, -1] == 2}} - }; - - if(count _possibleBases == 0) exitWith {}; - - //Search for an outpost with a designated mortar position if possible - private _index = -1; - private _spawnParams = -1; - { - _spawnParams = [_x, "Mortar"] call A3A_fnc_findSpawnPosition; - if (_spawnParams isEqualType []) exitWith - { - //Will occupy a mortar spawn position until the outpost spawnes in and despawns again (Currently we dont spawn mortars at outposts anyways) - _spawnRadius = 0; - _index = _forEachIndex; - }; - [_x] spawn A3A_fnc_freeSpawnPositions; - } forEach _possibleBases; - - if(_index != -1) then + private _spawnParams = [_x, "Mortar"] call A3A_fnc_findSpawnPosition; + if (_spawnParams isEqualType []) exitWith { + //Will occupy a mortar spawn position until the outpost spawnes in and despawns again (Currently we dont spawn mortars at outposts anyways) + _spawnRadius = 0; _spawnPos = _spawnParams select 0; _spawnDir = _spawnParams select 1; - } - else - { - private _base = selectRandom _possibleBases; - _spawnPos = getMarkerPos _base; }; -} -else -{ - private _possibleBases = airportsX select - { - (sidesX getVariable [_x, sideUnknown] == _side) && - {((getMarkerPos _x) distance2D _supportPos <= 10000) && - {((getMarkerPos _X) distance2D _supportPos > 2000) && - {spawner getVariable [_x, -1] == 2}}} - }; - - if(count _possibleBases == 0) exitWith {}; + [_x] spawn A3A_fnc_freeSpawnPositions; +} forEach _possibleBases; +if (_spawnPos isEqualTo []) then +{ private _base = selectRandom _possibleBases; - _spawnPos = getMarkerPos _base; - _spawnDir = random 360; - _spawnRadius = 50; + _spawnPos = markerPos _base; }; -if(_spawnPos isEqualTo []) exitWith -{ - Info_1("Couldn't spawn in mortar %1, no suitable position found!", _supportName); - ["", 0, 0]; -}; -//Spawn in mortar -_mortar = [_mortarType, _spawnPos, _spawnRadius, 5, true] call A3A_fnc_safeVehicleSpawn; +// Spawn in mortar +private _vehicle = [_vehType, _spawnPos, _spawnRadius, 5, true] call A3A_fnc_safeVehicleSpawn; +_vehicle setVariable ["shellType", _shellType]; +[_vehicle, _side, _resPool] call A3A_fnc_AIVehInit; -//Spawn in crew -private _mortarGroup = [_side, _mortar] call A3A_fnc_createVehicleCrew; +// Spawn in crew +private _group = [_side, _vehicle] call A3A_fnc_createVehicleCrew; +{ [_x, nil, false, _resPool] call A3A_fnc_NATOinit } forEach units _group; +_group deleteGroupWhenEmpty true; -_mortar setVariable ["shellType", _shellType, true]; -[_mortar] call A3A_fnc_addArtilleryTrailEH; +private _aggro = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (250 - 10*tierWar - 1*_aggro) }; -//Creates the marker which coveres the area in which the support can help -private _coverageMarker = createMarker [format ["%1_coverage", _supportName], getPos _mortar]; -_coverageMarker setMarkerShape "ELLIPSE"; -_coverageMarker setMarkerBrush "Grid"; -if(_side == Occupants) then -{ - _coverageMarker setMarkerColor colorOccupants; -} -else -{ - _coverageMarker setMarkerColor colorInvaders; -}; - -private _timerArray = if(_side == Occupants) then {occupantsMortarTimer} else {invadersMortarTimer}; -if(_isMortar) then -{ - _coverageMarker setMarkerSize [3000, 3000]; - _timerArray set [_timerIndex, time + 3600]; -} -else -{ - _coverageMarker setMarkerSize [10000, 10000]; - _timerArray set [_timerIndex, time + 7200]; +private _targArray = []; +if (_target isEqualType objNull) then { + A3A_supportStrikes pushBack [_side, "AREA", _targPos, time + 20*60, 20*60, 100]; + _targArray = [_target, _targPos]; }; -_coverageMarker setMarkerAlpha 0; +// name, side, suppType, pos, radius, remTargets, targets +private _suppData = [_supportName, _side, "MORTAR", _spawnPos, _maxRange, _targArray, _minRange]; +A3A_activeSupports pushBack _suppData; +[_suppData, _vehicle, _group, _delay, _reveal] spawn A3A_fnc_SUP_mortarRoutine; -_mortar setVariable ["TimerArray", _timerArray, true]; -_mortar setVariable ["TimerIndex", _timerIndex, true]; +[_reveal, _side, "MORTAR", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -//Setting up the EH for support destruction -_mortar addEventHandler -[ - "Killed", - { - params ["_mortar"]; - ["TaskSucceeded", ["", "Mortar Support Destroyed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _timerArray = _mortar getVariable "TimerArray"; - private _timerIndex = _mortar getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 7200]; - } -]; - -_mortar addEventHandler -[ - "GetIn", - { - params ["_vehicle", "_role", "_unit", "_turret"]; - if(side (group _unit) == teamPlayer) then - { - ["TaskSucceeded", ["", "Mortar Support Stolen"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - _vehicle setVariable ["Stolen", true, true]; - _vehicle removeAllEventHandlers "GetIn"; - private _timerArray = _vehicle getVariable "TimerArray"; - private _timerIndex = _vehicle getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 7200]; - }; - } -]; - -_mortarGroup setVariable ["Mortar", _mortar, true]; -{ - _x addEventHandler - [ - "Killed", - { - params ["_unit"]; - private _group = group _unit; - if({alive _x} count (units _group) == 0) then - { - ["TaskSucceeded", ["", "Mortar Support crew killed"]] remoteExec ["BIS_fnc_showNotification", teamPlayer]; - private _mortar = _group getVariable "Mortar"; - private _timerArray = _mortar getVariable "TimerArray"; - private _timerIndex = _mortar getVariable "TimerIndex"; - _timerArray set [_timerIndex, (_timerArray select _timerIndex) + 3600]; - }; - } - ]; -} forEach (units _mortarGroup); - -private _setupTime = 900 - ((tierWar - 1) * 75); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); - -_mortarGroup deleteGroupWhenEmpty true; -[_mortar, _mortarGroup, _supportName, _side, _sleepTime] spawn A3A_fnc_SUP_mortarRoutine; - -private _result = [_coverageMarker, _minSleepTime, _setupTime]; -_result; +// Mortar cost (might be free?) + extra support cost for balance +(A3A_vehicleResourceCosts getOrDefault [_vehType, 0]) + 100; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_mortarAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_mortarAvailable.sqf index d6e9a4570a..2833e7b1cf 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_mortarAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_mortarAvailable.sqf @@ -1,57 +1,23 @@ -params ["_side"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _faction = Faction(_side); -if(tierWar < 2) exitWith {-1}; +/* Get mortar support selection weight against target + +Arguments: + Target object + Side to send support from + Max resource spend (not currently used) + Array of strings of available types for this faction -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "MORTAR" && {(_lastSupport select 1) > time}) exitWith {-1}; +Return value: + Weight value, 0 for unavailable or useless +*/ -//Mortars not available, block support -if ((_faction get "staticMortars" isEqualTo []) || (_faction get "vehiclesArtillery" isEqualTo [])) exitWith {-1}; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -//Select a timer index and the max number of timers available -private _timerIndex = -1; -private _playerAdjustment = (floor ((count allPlayers)/5)) + 1; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -//Search for a timer which allows the support to be fired -if(_side == Occupants) then -{ - if(count occupantsMortarTimer < _playerAdjustment) then - { - _timerIndex = count occupantsMortarTimer; - for "_i" from ((count occupantsMortarTimer) + 1) to _playerAdjustment do - { - occupantsMortarTimer pushBack -1; - }; - } - else - { - _timerIndex = occupantsMortarTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; -if(_side == Invaders) then -{ - if(count invadersMortarTimer < _playerAdjustment) then - { - _timerIndex = count invadersMortarTimer; - for "_i" from ((count invadersMortarTimer) + 1) to _playerAdjustment do - { - invadersMortarTimer pushBack -1; - }; - } - else - { - _timerIndex = invadersMortarTimer findIf {_x < time}; - if(_playerAdjustment <= _timerIndex) then - { - _timerIndex = -1; - }; - }; -}; +if (_target isKindOf "Air") exitWith { 0 }; // can't hit air -_timerIndex; +// balance this one against artillery +if (tierWar < 2) exitWith { 0 }; +if (tierWar < 5 or !("ARTILLERY" in _availTypes)) exitWith { 1 }; +1 - (tierWar - 4) / 8; // // 87.5% at tier 5, 25% at tier 10 diff --git a/A3A/addons/core/functions/Supports/fn_SUP_mortarRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_mortarRoutine.sqf index ef703f5fe8..4b8bf0dc80 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_mortarRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_mortarRoutine.sqf @@ -1,194 +1,115 @@ -params ["_mortar", "_crewGroup", "_supportName", "_side", "_sleepTime"]; +/* Create and maintain mortar and artillery supports -/* The routine which controls the mortar support in all aspects +Environment: Server, must be spawned - Execution on: Server +Arguments: + Active support data, see initSupports + Mortar/artillery vehicle + Crew group of mortar/artillery vehicle + Delay time in seconds + Amount of information to reveal to rebels, 0-1 - Scope: Internal - - Params: - _mortar: OBJECT : The actual mortar object - _crewGroup: GROUP : The crewgroup of the mortar - _supportName: STRING : The callsign of the support - _side: SIDE : The side of the support - - Returns: - Nothing */ + #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() +params ["_suppData", "_mortar", "_crewGroup", "_sleepTime", "_reveal"]; +_suppData params ["_supportName", "_side", "_suppType", "_suppCenter", "_suppRadius", "_target"]; + //Sleep to simulate the time it would need to set the support up sleep _sleepTime; //Decrease number of rounds and time alive if aggro is low private _sideAggression = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; private _numberOfRounds = 32; -private _timeAlive = 900; +private _timeAlive = 1200; //If the aggro is low, the mortar will shoot less and stay longer in one spot -if((30 + (random 40)) >_sideAggression) then +if((30 + random 40) >_sideAggression) then { _numberOfRounds = 16; _timeAlive = 1800; }; -private _shotsPerVoley = _numberOfRounds / 4; - -_mortar setVariable ["Callsign", _supportName, true]; +private _shotsPerVolley = _numberOfRounds / 4; //A function to repeatedly fire onto a target without loops by using an EH _fn_executeMortarFire = { params ["_mortar"]; - private _targets = _mortar getVariable ["FireOrder", []]; - private _target = _targets deleteAt 0; - _mortar setVariable ["FireOrder", _targets, true]; - _mortar addEventHandler [ "Fired", { params ["_mortar"]; - private _targets = _mortar getVariable ["FireOrder", []]; - - if(count _targets == 0) exitWith + private _subTargets = _mortar getVariable ["FireOrder", []]; + if(count _subTargets == 0) exitWith { _mortar removeEventHandler ["Fired", _thisEventHandler]; - _mortar setVariable ["CurrentlyFiring", false, true]; - _mortar setVariable ["FireOrder", nil, true]; - - private _supportName = _mortar getVariable "Callsign"; - [_supportName] spawn - { - private _name = _this select 0; - sleep 60; - deleteMarker (format ["%1_targetMarker", _name]); - deleteMarker (format ["%1_text", _name]); - }; + _mortar setVariable ["FireOrder", nil]; }; + private _shellTarget = _subTargets deleteAt 0; - private _target = _targets deleteAt 0; - _mortar setVariable ["FireOrder", _targets, true]; - - [_target, _mortar] spawn + [_shellTarget, _mortar] spawn { - params ["_target", "_mortar"]; + params ["_shellTarget", "_mortar"]; sleep 0.5; - _mortar doArtilleryFire [_target, _mortar getVariable "shellType", 1]; + _mortar doArtilleryFire [_shellTarget, _mortar getVariable "shellType", 1]; } } ]; + + sleep 30; // Give players a bit more warning before the shells land + private _subTargets = _mortar getVariable ["FireOrder", []]; + private _target = _subTargets deleteAt 0; _mortar doArtilleryFire [_target, _mortar getVariable "shellType", 1]; }; -_mortar setVariable ["CurrentlyFiring", false, true]; -while {_timeAlive > 0} do +private _timeout = time + _timeAlive; +while {time < _timeout} do { - if !(_mortar getVariable "CurrentlyFiring") then - { - //Mortar is currently not attacking a target, search for new order - private _targetList = server getVariable [format ["%1_targets", _supportName], []]; - if (count _targetList > 0) then - { - //New target active, read in - private _target = _targetList deleteAt 0; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - - Debug_1("Next target is %1", _target); - - //Parse targets - private _targetParams = _target select 0; - private _reveal = _target select 1; - - private _subTargets = []; - private _targetPos = _targetParams select 0; - private _precision = _targetParams select 1; - private _distance = random (125 - ((_precision/4) * (_precision/4) * 100)); - - for "_i" from 1 to _shotsPerVoley do - { - _subTargets pushBack (_targetPos getPos [random _distance, random 360]); - }; - - //Show target to players if change is high enough - private _targetMarker = createMarker [format ["%1_targetMarker", _supportName], _targetPos]; - _targetMarker setMarkerShape "ELLIPSE"; - _targetMarker setMarkerBrush "Grid"; - _targetMarker setMarkerSize [_distance + 25, _distance + 25]; - - private _textMarker = createMarker [format ["%1_text", _supportName], _targetPos]; - _textMarker setMarkerShape "ICON"; - _textMarker setMarkerType "mil_dot"; - _textMarker setMarkerText "Artillery"; + sleep 5; - //Makes sure that all units escape before attacking - [_side, _targetMarker] spawn A3A_fnc_clearTargetArea; + //Mortar somehow disabled/stolen + if !(canFire _mortar && side _mortar == _side) exitWith { + Info_1("%1 has been destroyed or crew killed, aborting routine", _supportName); + }; - if(_side == Occupants) then - { - _targetMarker setMarkerColor colorOccupants; - _textMarker setMarkerColor colorOccupants; - } - else - { - _targetMarker setMarkerColor colorInvaders; - _textMarker setMarkerColor colorInvaders; - }; - _targetMarker setMarkerAlpha 0; - _textMarker setMarkerAlpha 0; + if !(isNil {_mortar getVariable "FireOrder"}) then { continue }; // mortar still firing at last target - [_reveal, _targetPos, _side, "MORTAR", _targetMarker, _textMarker] spawn A3A_fnc_showInterceptedSupportCall; + if (_numberOfRounds <= 0) exitWith { + Info_1("%1 has no more rounds left to fire, aborting routine", _supportName); + }; - _mortar setVariable ["CurrentlyFiring", true, true]; - _mortar setVariable ["FireOrder", _subTargets, true]; + // Read in new target if there is one + if (_target isEqualTo []) then { continue }; // no new target added yet + private _targetPos = _target select 1; // only use position here, not target object + _target resize 0; // clear target array so that a new one can be added externally + Debug_2("%1 Next target is %2", _supportName, _targetPos); - [_mortar] spawn _fn_executeMortarFire; - _numberOfRounds = _numberOfRounds - _shotsPerVoley; - }; + // 50m circular spread because it's easy + private _subTargets = []; + for "_i" from 1 to _shotsPerVolley do { + _subTargets pushBack (_targetPos getPos [random 50, random 360]); }; - //Mortar somehow destroyed - if - ( - !(alive _mortar) || - {({alive _x} count (units _crewGroup)) == 0 || - {_mortar getVariable ["Stolen", false]}} - ) exitWith - { - Info_1("%1 has been destroyed or crew killed, aborting routine", _supportName); - [_side, 20, 45] remoteExec ["A3A_fnc_addAggression", 2]; - }; + // Start shooting + _mortar setVariable ["FireOrder", _subTargets]; + [_mortar] spawn _fn_executeMortarFire; + _numberOfRounds = _numberOfRounds - _shotsPerVolley; - if (!(_mortar getVariable "CurrentlyFiring") && (_numberOfRounds <= 0)) exitWith - { - Info_1("%1 has no more rounds left to fire, aborting routine", _supportName); - }; + //Makes sure that all units escape before attacking + // [_side, _targetMarker] spawn A3A_fnc_clearTargetArea; - sleep 5; - _timeAlive = _timeAlive - 5; + [_reveal, _targetPos, _side, _suppType, 150, 5*60] spawn A3A_fnc_showInterceptedSupportCall; }; -//Mortar already destroyed _mortar removeAllEventHandlers "Fired"; +_suppData set [4, 0]; // Set radius to zero to signal completion -//Do not allow further shots and get the unit out -_crewGroup setCombatMode "GREEN"; -doGetOut (units _crewGroup); -_crewGroup setBehaviour "SAFE"; - -if({alive _x} count (units _crewGroup) != 0) then -{ - //Crew left, activating despawner - [_crewGroup] spawn A3A_fnc_groupDespawner; -}; - -if(alive _mortar && {!(_mortar getVariable ["Stolen", false])}) then -{ - //Mortar left, activating despawner - [_mortar] spawn A3A_fnc_VEHdespawner; -}; +{ unassignVehicle _x } forEach units _crewGroup; -//Deleting all the support data here -[_supportName, _side] call A3A_fnc_endSupport; +[_crewGroup] spawn A3A_fnc_groupDespawner; +[_mortar] spawn A3A_fnc_VEHdespawner; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrike.sqf b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrike.sqf index 36f05917aa..c055e403aa 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrike.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrike.sqf @@ -1,52 +1,35 @@ -params ["_side", "_timerIndex", "_supportPos", "_supportName"]; +/* Sets up an orbital strike support + +Environment: Server, scheduled, internal + +Arguments: + The (unique) name of the support, mostly for logging + The side from which the support should be sent (occupants or invaders) + Resource pool used for this support. Should be "attack" or "defence" + Maximum resources to spend. Not used here + Target of the support. False for none + Target position for orbital strike + Reveal value 0-1, higher values mean more information provided about support + Setup delay time in seconds, if negative will calculate based on war tier + +Returns: + Resource cost of support call, or -1 for failure +*/ -/* Prepares the orbital strike marker +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() - Execution on: Server +params ["_supportName", "_side", "_resPool", "_maxSpend", "_target", "_targPos", "_reveal", "_delay"]; - Scope: Internal +private _aggroValue = if(_side == Occupants) then {aggressionOccupants} else {aggressionInvaders}; +if (_delay < 0) then { _delay = (0.5 + random 1) * (350 - 15*tierWar - 1*_aggroValue) }; - Params: - _side: SIDE : The side for which the support should be called in - _timerIndex: NUMBER - _supportPos: POSITION : The position where the strike should hit - _supportName: STRING : The call name of the support +// ["_side", "_basetype", "_target", "_endtime", "_duration", "_power"] +A3A_supportStrikes pushBack [_side, "AREA", _targPos, time + 1200, 1200, 500]; - Returns: - The name of the marker, covering the whole support area -*/ +[_supportName, _side, _delay, ATLtoASL _targPos, _reveal] spawn A3A_fnc_SUP_orbitalStrikeRoutine; + +[_reveal, _side, "ORBITALSTRIKE", _targPos, _delay] spawn A3A_fnc_showInterceptedSetupCall; -private _fileName = "SUP_orbitalStrike"; - - -private _coverageMarker = createMarker [format ["%1_coverage", _supportName], _supportPos]; -_coverageMarker setMarkerShape "ELLIPSE"; -_coverageMarker setMarkerBrush "Grid"; -if(_side == Occupants) then -{ - _coverageMarker setMarkerColor colorOccupants; -} -else -{ - _coverageMarker setMarkerColor colorInvaders; -}; -_coverageMarker setMarkerSize [500, 500]; -_coverageMarker setMarkerAlpha 0; - -if(_side == Occupants) then -{ - occupantsOrbitalStrikeTimer set [0, time + (3600 * 12)]; -} -else -{ - invadersOrbitalStrikeTimer set [0, time + (3600 * 12)]; -}; - -private _setupTime = 1200 - ((tierWar - 1) * 100); -private _minSleepTime = (1 - (tierWar - 1) * 0.1) * _setupTime; -private _sleepTime = _minSleepTime + random (_setupTime - _minSleepTime); - -[ATLtoASL _supportPos, _sleepTime, _supportName, _side] spawn A3A_fnc_SUP_orbitalStrikeRoutine; - -private _result = [_coverageMarker, _minSleepTime, _setupTime]; -_result; +// Return resource cost of support +500; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeAvailable.sqf b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeAvailable.sqf index 448bc1b835..3abee98769 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeAvailable.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeAvailable.sqf @@ -1,103 +1,22 @@ -params ["_side", "_posDestination"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -if(tierWar < 9) exitWith {-1}; - -private _lastSupport = server getVariable ["lastSupport", ["", 0]]; -if((_lastSupport select 0) == "ORBSTRIKE" && {(_lastSupport select 1) > time}) exitWith {-1}; - -if !(allowFuturisticSupports) exitWith {-1}; -private _loadedTemplate = if (_side isEqualTo Occupants) then {A3A_Occ_template} else {A3A_Inv_template}; -if (toLower _loadedTemplate isEqualTo "VN") exitWith {-1}; //dont allow with VN +/* Get orbital stike support selection weight against target -//Check if support is available at all -private _timer = -1; -if(_side == Occupants) then -{ - if((occupantsOrbitalStrikeTimer select 0) < time) then - { - _timer = 0; - }; -} -else -{ - if((invadersOrbitalStrikeTimer select 0) < time) then - { - _timer = 0; - }; -}; -if(_timer == -1) exitWith {_timer}; +Arguments: + Target object + Side to send support from + Max resource spend + Array of strings of available types for this faction -//Do a logical check if the support is useful -private _proCounter = 0; -private _contraCounter = 0; +Return value: + Weight value, 0 for unavailable or useless +*/ -//It looks way better at night -if(sunOrMoon < 0.5) then -{ - _proCounter = _proCounter + 20 -} -else -{ - _contraCounter = _contraCounter + 20; -}; - -private _citiesInRange = (citiesX - destroyedSites) select {((getMarkerPos _x) distance2D _posDestination) < 200}; -if(_side == Occupants) then -{ - //Occupants try to avoid hitting cities - _contraCounter = _contraCounter + (30 * (count _citiesInRange)); -} -else -{ - //Invaders prefer to hit cities too - _proCounter = _proCounter + (50 * (count _citiesInRange)); -}; - -//Check the units on the point -private _unitsInRange = allUnits select {((getPos _x) distance2D _posDestination) < 300}; -{ - if(_side == Occupants) then - { - //Trying to not hit own units - if(side group _x == Occupants) then - { - _contraCounter = _contraCounter + 10; - if !(isNull (objectParent _x)) then - { - _contraCounter = _contraCounter + 15; - }; - } - else - { - _proCounter = _proCounter + 15; - if !(isNull (objectParent _x)) then - { - _proCounter = _proCounter + 50; - }; - }; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() - } - else - { - //As long as they hit enemies they are fine - if(side group _x == Invaders) then - { - _contraCounter = _contraCounter + 5; - } - else - { - _proCounter = _proCounter + 20; - if !(isNull (objectParent _x)) then - { - _proCounter = _proCounter + 75; - }; - }; - }; -} forEach _unitsInRange; +params ["_target", "_side", "_maxSpend", "_availTypes"]; -private _willUse = selectRandomWeighted [true, _proCounter, false, _contraCounter]; -Info_3("With %1 pro and %2 contra, decided for %3", _proCounter, _contraCounter, _willUse); +if (_target isKindOf "Air") exitWith { 0 }; // can't hit air (reliably) -if(_willUse) exitWith {0}; --1; +if (_maxSpend < 300) exitWith { 0 }; // don't use unless we're rich +if (tierWar < 8) exitWith { 0 }; // don't use until lategame +1; diff --git a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeRoutine.sqf b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeRoutine.sqf index f031b2f0bb..c6d79b1001 100644 --- a/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeRoutine.sqf +++ b/A3A/addons/core/functions/Supports/fn_SUP_orbitalStrikeRoutine.sqf @@ -1,40 +1,29 @@ -params ["_impactPosition", "_sleepTime", "_supportName", "_side"]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() //Hugely inspired and partly copied from ALIAS https://www.armaholic.com/page.php?id=32556 /* An orbital attack, resulting in an devastating beam - Execution on: Server - - Scope: External +Environment: Server, must be spawned - Params: - _impactPosition: POSITION : Position of the impact point in format posASL +Arguments: + Unique support name (mostly for logging) + Side to send support from + Delay time in seconds + Target position for airstrike + Amount of information to reveal to rebels, 0-1 - Returns: - Nothing */ -sleep _sleepTime; -private _targetList = server getVariable [format ["%1_targets", _supportName], []]; -private _reveal = _targetList select 0 select 1; +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -private _textMarker = createMarker [format ["%1_text", _supportName], _impactPosition]; -_textMarker setMarkerShape "ICON"; -_textMarker setMarkerType "mil_dot"; -_textMarker setMarkerText "Orbital strike"; -if(_side == Occupants) then -{ - _textMarker setMarkerColor colorOccupants; -} -else -{ - _textMarker setMarkerColor colorInvaders; -}; -_textMarker setMarkerAlpha 0; -[_reveal, _impactPosition, _side, "ORBSTRIKE", format ["%1_coverage", _supportName], _textMarker] spawn A3A_fnc_showInterceptedSupportCall; -[_side, format ["%1_coverage", _supportName]] spawn A3A_fnc_clearTargetArea; +params ["_supportName", "_side", "_delay", "_impactPosition", "_reveal"]; + +sleep _delay; + +//["_reveal", "_position", "_side", "_supportType", "_markerType", "_markerLifeTime"] +[_reveal, _impactPosition, _side, "ORBITALSTRIKE", 300, 120] spawn A3A_fnc_showInterceptedSupportCall; + +//[_side, format ["%1_coverage", _supportName]] spawn A3A_fnc_clearTargetArea; private _startPos = +_impactPosition; _startPos set [2, (_startPos select 2) + 1000]; @@ -141,4 +130,3 @@ private _citiesInRange = (citiesX - destroyedSites) select {((getMarkerPos _x) d sleep 10; } forEach _citiesInRange; -[_supportName, _side] spawn A3A_fnc_endSupport; diff --git a/A3A/addons/core/functions/Supports/fn_addSupportTarget.sqf b/A3A/addons/core/functions/Supports/fn_addSupportTarget.sqf index 2d661daab9..1343e23d55 100644 --- a/A3A/addons/core/functions/Supports/fn_addSupportTarget.sqf +++ b/A3A/addons/core/functions/Supports/fn_addSupportTarget.sqf @@ -1,76 +1,40 @@ /* -Author: Wurzel0701 +Maintainer: John Jordan Adds a given target to the given support +Scope: Server +Environment: Scheduled + Arguments: - The name of the support - > The target object or position and the support precision (range 0 - 4) - The reveal value of the call (range 0 - 1) + The active support array (from A3A_activeSupports) or name + The target object + Target position Return Value: - -Scope: Server -Environment: Scheduled -Public: No -Dependencies: - supportTargetsChanging - -Example: - ["CAS0", [_myCar, 3], 0.75] spawn A3A_fnc_addSupportTarget; */ - -params -[ - ["_supportName", "", [""]], - ["_targetParams", [], [[]]], - ["_revealCall", 0, [0]] -]; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -//Wait until no targets are changing -if(supportTargetsChanging) then -{ - waitUntil {!supportTargetsChanging}; -}; -supportTargetsChanging = true; -private _targetList = server getVariable [format ["%1_targets", _supportName], []]; +params ["_activeSupport", "_target", "_targPos"]; -if((_targetParams select 0) isEqualType []) then -{ - private _targetPos = _targetParams select 0; - private _index = _targetList findIf {((_x select 0 select 0) distance2D _targetPos) < 150}; - if(_index == -1) then - { - _targetList pushBack [_targetParams, _revealCall]; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - Info_2("Added fire order %1 to %2s target list", _targetParams, _supportName); - } - else - { - Info_1("Couldnt add target %1 as another target is already in the area", _targetPos); - }; -} -else -{ - private _isInList = false; - { - if((_x select 0 select 0) == (_targetParams select 0)) exitWith - { - _isInList = true; - }; - } forEach _targetList; - if !(_isInList) then - { - _targetList pushBack [_targetParams, _revealCall]; - server setVariable [format ["%1_targets", _supportName], _targetList, true]; - Debug_2("Added fire order %1 to %2s target list", _targetParams, _supportName); - } - else - { - Info_1("Couldnt add target %1 as target is already in the list", _targetParams select 0); - }; +if (_activeSupport isEqualType "") then { + private _index = A3A_activeSupports findIf { _activeSupport == _suppName }; + if (_index != -1) then { _activeSupport = A3A_activeSupports select _index }; }; +if (_activeSupport isEqualType "") exitWith { Error_1("Support name %1 not in active list", _activeSupport); false; }; + +_activeSupport params ["_suppName", "_suppSide", "_suppType", "_center", "_radius", "_suppTarget"]; +// Shouldn't really need these checks but whatever +if (_radius == 0 or _suppTarget isNotEqualTo []) exitWith { Error_2("No remaining targets for support %1", _suppName) }; + +_suppTarget append [_target, _targPos]; // target list may need both +Info_3("Added target %1 (position %2) to support %3", _target, _targPos, _suppName); + +// Add the strike call here so that we don't repeat it +private _suppTypeHM = [A3A_supportTypesOcc, A3A_supportTypesInv] select (_side == Invaders); +(_suppTypeHM get _suppType) params ["_baseType", "", "", "_strikePower"]; +private _strikeTarg = if (_baseType == "TARGET") then { _target } else { _targPos }; +A3A_supportStrikes pushBack [_suppSide, _baseType, _strikeTarg, time + 20*60, 20*60, _strikePower]; -supportTargetsChanging = false; +true; diff --git a/A3A/addons/core/functions/Supports/fn_createSupport.sqf b/A3A/addons/core/functions/Supports/fn_createSupport.sqf index 4989cd2524..ae220d7a0b 100644 --- a/A3A/addons/core/functions/Supports/fn_createSupport.sqf +++ b/A3A/addons/core/functions/Supports/fn_createSupport.sqf @@ -1,97 +1,70 @@ -params ["_side", "_timerIndex", "_supportType", "_supportTarget", "_precision", "_revealCall"]; +/* Worker function for creating supports -/* Creates an support type that attacks areas - - Execution on: Server - - Scope: Internal + Environment: Server, scheduled Parameters: - _side: SIDE: The side of the support unit - _timerIndex: NUMBER: The number of the timer for the support _supportType: STRING: The type of support to send - _supportTarget: POSITION or OBJECT: The position or object which will be attacked - _precision: NUMBER: How precise the target info is + _side: SIDE: The side of the support + _caller: POS2D or STRING: Position of caller if it's a defence response, or resource pool to override ("attack") + _maxSpend: NUMBER: Maximum resources to spend, mostly used for sizing QRFs + _target: OBJECT: The target object of the support. objNull valid for AREA. false creates with no target (for TARGET) + _targPos: POS2D: Target position of the support. + _reveal: NUMBER: Amount of info to reveal to rebels, 0 low, 1 high + _delay: NUMBER: Optional, setup delay time in seconds, otherwise will calculate based on war tier Returns: - Nothing + Name of support created, or empty string if failed */ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -//Selecting the first available name of support type -private _supportIndex = 0; -private _supportName = format ["%1%2", _supportType, _supportIndex]; -while {(server getVariable [format ["%1_targets", _supportName], -1]) isEqualType []} do -{ - _supportIndex = _supportIndex + 1; - _supportName = format ["%1%2", _supportType, _supportIndex]; -}; +params ["_type", "_side", "_caller", "_maxSpend", "_target", "_targPos", "_reveal", ["_delay", -1]]; +private _resPool = ["defence", _caller] select (_caller isEqualType ""); + +// Check if the support type exists for this faction. Ok to fail silently, just asking the question +private _suppTypeHM = [A3A_supportTypesOcc, A3A_supportTypesInv] select (_side == Invaders); +if !(_type in _suppTypeHM) exitWith { "" }; + +waitUntil { isNil "A3A_supportCallInProgress" }; +A3A_supportCallInProgress = true; -Debug_1("New support name will be %1", _supportName); +Debug_5("Attempting to create %1 support with side %2, pool %3, target %4 and reveal %5", _type, _side, _resPool, _target, _reveal); -private _supportMarker = ""; -switch (_supportType) do -{ - case ("QRF"): - { - _supportMarker = [_side, _supportTarget, _supportName] call A3A_fnc_SUP_QRF; - }; - case ("AIRSTRIKE"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_airstrike; - }; - case ("MORTAR"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_mortar; - }; - case ("ORBSTRIKE"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_orbitalStrike; - }; - case ("MISSILE"): - { - _supportMarker = [_side, _timerIndex, _supportName] call A3A_fnc_SUP_cruiseMissile; - }; - case ("SAM"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_SAM; - }; - case ("CARPETBOMB"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_carpetBombs; - }; - case ("CAS"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_CAS; - }; - case ("ASF"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_ASF; - }; - case ("GUNSHIP"): - { - _supportMarker = [_side, _timerIndex, _supportTarget, _supportName] call A3A_fnc_SUP_gunship; - }; +// Attempt to use active support if there's a valid one +private _supportIndex = A3A_activeSupports findIf { + _x params ["_suppName", "_suppSide", "_suppType", "_center", "_radius", "_suppTarg", ["_minRadius", 0]]; + private _dist = _targpos distance2d _center; + _suppSide == _side and _suppType == _type and _suppTarg isEqualTo [] and _dist < _radius and _dist > _minRadius; }; +if (_target isEqualType objNull and _supportIndex != -1) exitWith { + private _activeSupport = A3A_activeSupports # _supportIndex; + [_activeSupport, _target, _targPos] call A3A_fnc_addSupportTarget; + A3A_supportCallInProgress = nil; + _activeSupport # 0; // return support name +}; + +// Use global increment to make logging easier to track. +A3A_supportCount = A3A_supportCount + 1; +private _supportName = format ["%1%2", _type, A3A_supportCount]; + +// Spend radio key to boost support's reveal value if available +_reveal = [_side, _targPos, _reveal] call A3A_fnc_useRadioKey; + +// create function returns <0 if it couldn't do anything +private _createFunc = missionNamespace getVariable ("A3A_fnc_SUP_" + _type); +private _resourceCost = [_supportName, _side, _resPool, _maxSpend, _target, _targPos, _reveal, _delay] call _createFunc; +if (_resourceCost < 0) exitWith { A3A_supportCallInProgress = nil; "" }; + +[-_resourceCost, _side, _resPool] call A3A_fnc_addEnemyResources; -if(_supportMarker isEqualType [] && {(_supportMarker select 0) != ""}) then -{ - server setVariable [format ["%1_targets", _supportName], [[[_supportTarget, _precision], _revealCall]], true]; - if (_side == Occupants) then - { - occupantsSupports pushBack [_supportType, _supportMarker select 0, _supportName]; - }; - if(_side == Invaders) then - { - invadersSupports pushBack [_supportType, _supportMarker select 0, _supportName]; - }; - private _supportPos = if (_supportTarget isEqualType objNull) then {getPos _supportTarget} else {_supportTarget}; - [_revealCall + (random 0.4) - 0.2, _side, _supportType, _supportPos, _supportMarker select 1, _supportMarker select 2] spawn A3A_fnc_showInterceptedSetupCall; -} -else -{ - Info_2("Maybe no spawn, maybe bad value, input %1, return %2", _supportType, _supportMarker); +// This (and whole callpos business) can be cleaned up a lot with the commander system +if (_caller isEqualType []) then { + // support spends should only care about defence pool? + // because that's what it's being used to manage + // [side, callpos, targpos, resources, starttime] + private _spendTarg = [_targPos, _target] select (_target isEqualType objNull and {_target isKindOf "Air"}); + A3A_supportSpends pushBack [_side, _caller, _spendTarg, _resourceCost, time]; }; -supportCallInProgress = false; +A3A_supportCallInProgress = nil; +_supportName; diff --git a/A3A/addons/core/functions/Supports/fn_endSupport.sqf b/A3A/addons/core/functions/Supports/fn_endSupport.sqf deleted file mode 100644 index c8d5e0c7eb..0000000000 --- a/A3A/addons/core/functions/Supports/fn_endSupport.sqf +++ /dev/null @@ -1,62 +0,0 @@ -/* -Author: Wurzel0701 - Ends the given support and deletes all the related data - -Arguments: - The name of the support that should end - The side the support belongs to - The amount of minutes to wait before deleting the support data (can be 0) - -Return Value: - - -Scope: Server -Environment: Any -Public: No -Dependencies: - server - Occupants - occupantsSupports - invadersSupports - -Example: -["MORTAR0", Occupants, 0] call A3A_fnc_endSupport; -*/ - -params -[ - ["_supportName", "", [""]], - ["_side", sideEnemy, [sideEnemy]], - ["_timeTillExecution", 0, [0]] -]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -if(_supportName == "" || _side == sideEnemy) exitWith -{ - Error_1("Bad input, was %1", _this); -}; - -if(_timeTillExecution != 0) then -{ - sleep (_timeTillExecution * 60); -}; - -server setVariable [format ["%1_targets", _supportName], nil, true]; - -if (_side == Occupants) then -{ - private _index = occupantsSupports findIf {(_x select 2) == _supportName}; - occupantsSupports deleteAt _index; -}; - -if(_side == Invaders) then -{ - private _index = invadersSupports findIf {(_x select 2) == _supportName}; - invadersSupports deleteAt _index; -}; - -deleteMarker (format ["%1_coverage", _supportName]); -deleteMarker (format ["%1_text", _supportName]); - -Info_1("Ended support and deleted data for %1", _supportName); diff --git a/A3A/addons/core/functions/Supports/fn_getArtilleryRanges.sqf b/A3A/addons/core/functions/Supports/fn_getArtilleryRanges.sqf new file mode 100644 index 0000000000..b95af690f7 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_getArtilleryRanges.sqf @@ -0,0 +1,49 @@ +/* Find minimum and maximum ranges for artillery type + +Environment: Any + +Arguments: + Classname of artillery vehicle + Classname of artillery magazine + +Return array: + Minimum range in metres + Maximum range in metres + +Examples: + ["UK3CB_ADA_I_BM21", "rhs_mag_m21of_1"] call A3A_fnc_getArtilleryRanges; + ["O_MBT_02_arty_F", "32Rnd_155mm_Mo_shells_O"] call A3A_fnc_getArtileryRanges; +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_vehType", "_shellType"]; + +private _turretCfg = call { + private _allTurrets = configProperties [configFile >> "CfgVehicles" >> _vehType >> "Turrets"]; + private _idx = _allTurrets findIf { getNumber (_x >> "elevationMode") == 3 }; // no idea if this is a valid check + if (_idx == -1) exitWith { + Error_1("Artillery turret not found on %1", _vehType); + configFile >> "CfgVehicles" >> _vehType >> "Turrets" >> "MainTurret"; + }; + _allTurrets # _idx; +}; + +// Try mags for pylon weapons, otherwise assume the turret weapon is valid +private _weapon = getText (configfile >> "CfgMagazines" >> _shellType >> "pylonWeapon"); +if (_weapon == "") then { _weapon = getArray (_turretCfg >> "Weapons") # 0 }; +private _weaponCfg = configFile >> "CfgWeapons" >> _weapon; + +// Assume that there's no speed override on weapon, probably true for arty +private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _shellType >> "initSpeed"); +private _maxElev = getNumber (_turretCfg >> "maxElev"); +// Simple formula works because Arma doesn't calculate air resistance for artillery +private _maxRange = (_initSpeed)^2 * sin (2*45) / 9.807; + +// Assumes first fire mode is closest range, probably true because artillery computer +private _minCharge = getNumber (_weaponCfg >> getArray (_weaponCfg >> "modes")#0 >> "artilleryCharge"); +if (_minCharge == 0) then { Error_1("Artillery charge lookup failed for %1", _vehType); _minCharge = 1 }; +private _minRange = (_minCharge * _initSpeed)^2 * sin (2*_maxElev) / 9.807; + +[_minRange+100, _maxRange-100]; // make sure we can spread shots diff --git a/A3A/addons/core/functions/Supports/fn_initSupportCooldowns.sqf b/A3A/addons/core/functions/Supports/fn_initSupportCooldowns.sqf deleted file mode 100644 index ff49328b2d..0000000000 --- a/A3A/addons/core/functions/Supports/fn_initSupportCooldowns.sqf +++ /dev/null @@ -1,88 +0,0 @@ -/* -Author: Wurzel0701 - Initiates initial cooldown times for supports - -Arguments: - - -Return Value: - - -Scope: Server -Environment: Any -Public: No -Dependencies: - NONE - -Example: -[] call A3A_fnc_initSupportCooldowns; -*/ - -supportCallInProgress = false; - -occupantsAirstrikeTimer = []; -invadersAirstrikeTimer = []; -for "_i" from 0 to 1 do -{ - occupantsAirstrikeTimer pushBack (random 1200); - invadersAirstrikeTimer pushBack (random 1200); -}; - -occupantsMortarTimer = []; -invadersMortarTimer = []; -for "_i" from 0 to 0 do -{ - occupantsMortarTimer pushBack (random 1800); - invadersMortarTimer pushBack (random 1800); -}; - -occupantsCruiseMissileTimer = []; -invadersCruiseMissileTimer = []; -for "_i" from 0 to 0 do -{ - occupantsCruiseMissileTimer pushBack (random (3600 * 4)); - invadersCruiseMissileTimer pushBack (random (3600 * 4)); -}; - -occupantsSAMTimer = []; -invadersSAMTimer = []; -for "_i" from 0 to 0 do -{ - occupantsSAMTimer pushBack (random (3600 * 2)); - invadersSAMTimer pushBack (random (3600 * 2)); -}; - -occupantsCarpetBombTimer = []; -invadersCarpetBombTimer = []; -for "_i" from 0 to 0 do -{ - occupantsCarpetBombTimer pushBack (random (3600 * 3)); - invadersCarpetBombTimer pushBack (random (3600 * 3)); -}; - -occupantsGunshipTimer = []; -invadersGunshipTimer = []; -for "_i" from 0 to 0 do -{ - occupantsGunshipTimer pushBack (random (3600 * 2.5)); - invadersGunshipTimer pushBack (random (3600 * 2.5)); -}; - -occupantsASFTimer = []; -invadersASFTimer = []; -for "_i" from 0 to 0 do -{ - occupantsASFTimer pushBack (random (3600 * 2)); - invadersASFTimer pushBack (random (3600 * 2)); -}; - -occupantsCASTimer = []; -invadersCASTimer = []; -for "_i" from 0 to 0 do -{ - occupantsCASTimer pushBack (random (3600 * 2)); - invadersCASTimer pushBack (random (3600 * 2)); -}; - -occupantsOrbitalStrikeTimer = [random (3600 * 12)]; -invadersOrbitalStrikeTimer = [random (3600 * 12)]; diff --git a/A3A/addons/core/functions/Supports/fn_initSupports.sqf b/A3A/addons/core/functions/Supports/fn_initSupports.sqf new file mode 100644 index 0000000000..b6ecf8c9ea --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_initSupports.sqf @@ -0,0 +1,102 @@ + + +// Used for creating unique support and marker names +A3A_supportCount = 0; +A3A_supportMarkerCount = 0; + +// Array of active/recent supports +// used to limit resource spend in an area +// ["_side", "_callpos", "_targpos", "_resources", "_starttime"] +A3A_supportSpends = []; + +// Individual strikes generated by supports (and other sources?) on creation +// used to prevent spamming same base type on a point or target +// target is object for TARGET base type, otherwise position +// power is effect radius for AREA, strength for TROOPS +// ["_side", "_basetype", "_target", "_endtime", "_duration", "_power"] +A3A_supportStrikes = []; + +// only need this for the support system itself in this version? + +// Active multitarget supports +// [_suppname, _side, _supptype, _center, _radius, _target, _minRadius (opt)] +// _target is [unit, position] array, or [] for free +A3A_activeSupports = []; + +// Interfaces: +// Avail func: _weight = [_target, _side, _maxSpend?] call _availFunc; +// Create func: _resCost = [_suppname, _side, _resPool, _maxSpend, _target, _targpos, _reveal, _delay] call _createFunc; + + +private _initData = [ + // [supptype, basetype, weight, lowair, effradius, strikepower, unfair, reqtype] + // weight/lowair: Relative weighting for selection. May be adjusted by availability functions. + // effradius: Strike radius, used for detecting friendly fire + // strikepower: Approx resource value per strike for multi-target supports + ["AIRSTRIKE", "AREA", 0.5, 0.1, 150, 0, "", "vehiclesPlanesCAS"], // balanced against carpetBombs (50/50 at tier 10), total will be 0.5 + ["ARTILLERY", "AREA", 0.5, 0.9, 150, 85, "", "vehiclesArtillery"], // balanced against mortars (50/50 at tier 10), total will be 0.5/0.9 + ["MORTAR", "AREA", 0.5, 0.9, 100, 50, "", "staticMortars"], + ["ASF", "TARGET", 1.0, 0.4, 0, 100, "", "vehiclesPlanesAA"], // balanced against SAMs (if available), 66/33 weighting + ["CAS", "TARGET", 1.0, 0.4, 0, 100, "", "vehiclesPlanesCAS"], + ["QRFLAND", "TROOPS", 1.0, 1.4, 0, 0, "", ""], + ["QRFAIR", "TROOPS", 0.5, 0.1, 0, 0, "", ""], + ["CARPETBOMBS", "AREA", 0.5, 0.1, 200, 0, "u", ""], // balanced against airstrikes + ["SAM", "TARGET", 1.0, 1.0, 0, 100, "u", ""], // balanced against ASF + ["ORBITALSTRIKE", "AREA", 0.2, 0.0, 300, 0, "f", ""] +// ["GUNSHIP", ["AREA", 0.2, 50, 0]], // uh. Does AREA work for this? Only lasts 5 minutes so maybe... +]; + +// Generate support type hashmap for a faction, suppType -> [baseType, weight, effRadius, strikepower] +private _fnc_buildSupportHM = +{ + params ["_faction"]; + private _lowAir = _faction getOrDefault ["attributeLowAir", false]; + private _suppHM = createHashMap; + { + _x params ["_suppType", "_baseType", "_weight", "_lowAirWeight", "_effRadius", "_strikepower", "_flags", "_reqType"]; + if (_faction get _reqType isEqualTo []) then { continue }; + if ("u" in _flags and !allowUnfairSupports) then { continue }; + if ("f" in _flags and !allowFuturisticSupports) then { continue }; + + private _weight = [_weight, _lowAirWeight] select _lowAir; + _suppHM set [_suppType, [_baseType, _weight, _effRadius, _strikepower]]; + } forEach _initData; + _suppHM; +}; + +A3A_supportTypesOcc = A3A_faction_occ call _fnc_buildSupportHM; +A3A_supportTypesInv = A3A_faction_inv call _fnc_buildSupportHM; + + +// Build marker lists for determining importance of target locations + +A3A_supportMarkersXYI = []; // format [x, y, index into markerTypes] +A3A_supportMarkerTypes = []; // format [markerName, markerType, hasRadio, defenceMul, ...] + +#define RADIO_TOWER_BONUS 0.15 + +// Build arrays of markers that have defence bonuses +{ A3A_supportMarkerTypes pushBack [_x, "Airport", false, 1.0] } forEach airportsX; +{ A3A_supportMarkerTypes pushBack [_x, "Seaport", false, 0.6] } forEach seaports; +{ A3A_supportMarkerTypes pushBack [_x, "Outpost", false, 0.6] } forEach outposts; +{ A3A_supportMarkerTypes pushBack [_x, "Resource", false, 0.4] } forEach resourcesX; +{ A3A_supportMarkerTypes pushBack [_x, "Factory", false, 0.5] } forEach factories; +{ A3A_supportMarkerTypes pushBack [_x, "Town", false, 0.3] } forEach citiesX; +{ + _x pushBack (0.5 + random 0.5); // current random defence multiplier + private _pos = markerPos (_x#0); + A3A_supportMarkersXYI pushBack [_pos#0, _pos#1, _forEachIndex]; +} forEach A3A_supportMarkerTypes; + +// Find nearest marker for each radio tower and mark it in markersDetail +{ + private _closeMrk = A3A_supportMarkersXYI inAreaArray [getPosATL _x, 500, 500]; + if (_closeMrk isEqualTo []) then { continue }; + private _nearest = [_closeMrk, _x] call BIS_fnc_nearestPosition; + (A3A_supportMarkerTypes select (_nearest#2)) set [2, true]; // mark as having radio tower +} forEach (antennas + antennasDead); // ugh + +{ + // increase defenceMul if it's a radio tower + if (_x#2) then { _x set [3, (_x#3) + RADIO_TOWER_BONUS] }; +} forEach A3A_supportMarkerTypes; diff --git a/A3A/addons/core/functions/Supports/fn_maxDefenceSpend.sqf b/A3A/addons/core/functions/Supports/fn_maxDefenceSpend.sqf new file mode 100644 index 0000000000..54de8c3bc3 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_maxDefenceSpend.sqf @@ -0,0 +1,179 @@ +/* +Maintainer: John Jordan + Return free defence resources to spend against given position & target + +Environment: Server, scheduled + +Arguments: + Side using the resources, must be occupants or invaders + or Target object or side to target + or Position of support caller, or a marker to defend/retake + Optional, additional cap relative to max location spend (Default: 1.0) + +Return Value: + Free defence resources to spend. + +Examples: + [Occupants, teamPlayer, "outpost_3"] call A3A_fnc_maxDefenceSpend; + [Invaders, _enemyTank, getPosATL _spottingUnit] call A3A_fnc_maxDefenceSpend; +*/ + +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_target", "_callPos", ["_maxResMod", 1]]; +private _targetSide = if (_target isEqualType objNull) then { side group _target } else { _target }; + +private _curResources = [A3A_resourcesDefenceInv, A3A_resourcesDefenceOcc] select (_side == Occupants); +private _maxResources = A3A_balanceResourceRate * 10 * ([1, A3A_invaderBalanceMul] select (_side == Invaders)); +if (gameMode == 1) then { + // Other enemy can use 30-55% of max, rebels 60-85%, depending on aggro. Resource rate/max are also increased by aggro in initSupports + private _aggro = [aggressionInvaders, aggressionOccupants] select (_side == Occupants); + if (_targetSide != teamPlayer) exitWith { _maxResources = _maxResources * (0.3 + (100-_aggro)/400) }; + _maxResources = _maxResources * (0.6 + _aggro/400); +}; +Debug_2("Current resources %1, max resources %2", _curResources, _maxResources); +if (_curResources < 0) exitWith { 0 }; + + +// If target is air, use a global spend limit and only consider anti-air spends +if (_target isEqualType objNull and {_target isKindOf "Air"}) exitWith +{ + // TODO: should we consider aircraft type here? + // ideally want to prevent supports being spammed against unarmed aircraft + // but this might need to be the concern of the airspace manager + + // TODO: Might need to constrain this with the strike list so that you don't get multiple supports sent against one aircraft + + private _isArmed = typeOf _target in (FactionGet(all, "vehiclesHelisLightAttack") + FactionGet(all, "vehiclesHelisAttack") + FactionGet(all, "vehiclesPlanesCAS") + FactionGet(all, "vehiclesPlanesAA")); + private _maxAASpend = _maxResources * ([0.1, 0.4] select _isArmed); + private _curAASpend = 0; + { + _x params ["_spSide", "_spCallPos", "_spTargPos", "_spRes", "_spTime"]; + if (_spSide != _side) then { continue }; + if (_spTargPos isEqualType []) then { continue }; // non-position targpos means called against aircraft + + // Falloff resource spend over one hour + private _res = linearConversion [_spTime, (_spTime)+3600, time, _spRes, 0, true]; + _curAASpend = _curAASpend + _res; + + } forEach A3A_supportSpends; + + Debug_2("Cur AA spend %1, max AA spend %2", _curAASpend, _maxAASpend); + _curResources min (_maxAASpend - _curAASpend); +}; + + +// For ground targets, spend limit depends on markers near caller +private _maxSpendLoc = _maxResources; +private _threatBalance = 1; +if (_callPos isEqualType "") then +{ + // If target is a marker, just return the location's maximum + private _mrkIndex = A3A_supportMarkerTypes findif { _callPos == _x#0 }; // lookup marker name + _callPos = markerPos _callPos; + if (_mrkIndex == -1) exitWith { + Error_1("Unknown support marker: %1", _target); + _maxSpendLoc = _maxSpendLoc * 0.15; + }; + private _mrkType = A3A_supportMarkerTypes select _mrkIndex; + _maxSpendLoc = _maxSpendLoc * (_mrkType#3); // * _mrkType#4; // location type multiplier * time-based random + Debug_1("Marker max spend %1", _maxSpendLoc); +} +else +{ + // Target is position + // Friendly markers near caller increase max resource spend + // Enemy markers near target reduce max spend + private _targPos = [getPosATL _target, _callPos] select (_target isEqualType west); + private _closeMrk = A3A_supportMarkersXYI inAreaArray [_callPos, 1000, 1000]; + private _defMul = 0.15; + private _defSub = 0; + { + private _mrkType = A3A_supportMarkerTypes select (_x#2); + if (sidesX getVariable (_mrkType#0) != _side) then { // enemy marker + private _dist = _x distance2d _targPos; + _defSub = _defSub max (_mrkType#3 * (1 - _dist / 500)); + } else { // friendly marker + private _dist = _x distance2d _callPos; + _defMul = _defMul max (_mrkType#3 * (1 - _dist / 1000)); + }; + } forEach _closeMrk; + _maxSpendLoc = _maxSpendLoc * (_defMul - _defSub); + Debug_3("Max location spend %1 from defmul %2 and defsub %3", _maxSpendLoc, _defMul, _defSub); + + + // Prevent overreacting to threats: recentDamage + enemyStr - friendlyStr + // Recent damage, generated by AIReactOnKill & AIVehInit stuff? + private _recentDamage = [_side, _callPos, 300] call A3A_fnc_getRecentDamage; // should this be related to marker size? hmm + + // Accumulate base strength of nearby enemies + private _enemyStr = 0; + private _nearEnemies = units _targetSide inAreaArray [_callPos, 500, 500]; + if (_target isEqualType objNull) then { _nearEnemies pushBackUnique gunner vehicle _target }; // add target, in case it's shooting from long range + { + if !(_x call A3A_fnc_canFight) then { continue }; + if (vehicle _x isKindOf "Air") then { continue }; + _enemyStr = _enemyStr + ([10, 30] select isPlayer _x); // TODO: parameterize player multiplier + if (vehicle _x != _x and {_x == gunner vehicle _x}) then { + _enemyStr = _enemyStr + (A3A_groundVehicleThreat getOrDefault [typeOf vehicle _x, 0]); + }; + } forEach _nearEnemies; + + // counter with friendly unit strength + private _friendStr = 0; + private _nearFriends = units _side inAreaArray [_callPos, 500, 500]; + { + if !(_x call A3A_fnc_canFight) then { continue }; + if (vehicle _x isKindOf "Air") then { continue }; + if (_x getVariable ["A3A_resPool", ""] isEqualTo "defence") then { continue }; // accounted for in supportSpends + _friendStr = _friendStr + 10; + // Don't include friendly statics atm because they're not remanned and not registered in recentDamage if gunner killed + //if (vehicle _x != _x and {_x == gunner vehicle _x}) then { + // _friendStr = _friendStr + (A3A_groundVehicleThreat getOrDefault [typeOf vehicle _x, 0]); + //}; + } forEach _nearFriends; + + _threatBalance = (2*_recentDamage + _enemyStr) / (_friendStr max 1); + _threatBalance = 1 min (_threatBalance - 1); + Debug_4("Threat balance %1 from: Recent damage %2 enemy strength %3 friend strength %4", _threatBalance, _recentDamage, _enemyStr, _friendStr); + +// _maxSpend = _maxSpend min 2*(2*_recentDamage + _enemyStr - _friendStr); +}; +if (_maxSpendLoc <= 0 or _threatBalance <= 0) exitWith { 0 }; // possible if near enemy markers + + +// Determine how much we've already spent to support the target & caller positions +private _callPosSpend = 0; +private _targPosSpend = 0; +{ + // [side, type, callpos, targpos, resources, start time] + _x params ["_spSide", "_spCallPos", "_spTargPos", "_spRes", "_spTime"]; + if (_spSide != _side) then { continue }; + if !(_spTargPos isEqualType []) then { continue }; // anti-air spend + + // Falloff resource spend over one hour + private _res = linearConversion [_spTime, (_spTime)+3600, time, _spRes, 0, true]; + + // Falloff resource spend to 0 at 500m distance + private _callDist = _spCallPos distance2d _callPos; + _callPosSpend = _callPosSpend + linearConversion [0, 500, _callDist, _res, 0, true]; + + if (_target isEqualType west) then { continue }; + private _targDist = _spTargPos distance2d _target; + _targPosSpend = _targPosSpend + linearConversion [0, 500, _targDist, _res, 0, true]; + +} forEach A3A_supportSpends; + +Debug_2("Callpos spend %1, targpos spend %2", _callPosSpend, _targPosSpend); + +private _maxSpend = _threatBalance*_maxSpendLoc - (_callPosSpend max _targPosSpend); // reduce by what's already been spent +_maxSpend = _maxSpend min _curResources min (_maxResMod*_maxSpendLoc); + +// If result is low then there's an increasing chance of not sending anything for now +// Does this adequately replace the counterAttack size check? Probably... +private _minThreshold = (2.1 * A3A_balanceVehicleCost) min (0.5 * _maxSpendLoc); +private _minResponse = round (time / 120) random _minThreshold; +Debug_3("Max spend %1 with minThreshold %2 and minResponse %3", _maxSpend, _minThreshold, _minResponse); +if (_maxSpend < _minResponse) then { _maxSpend = 0 }; +_maxSpend; diff --git a/A3A/addons/core/functions/Supports/fn_requestArtillery.sqf b/A3A/addons/core/functions/Supports/fn_requestArtillery.sqf new file mode 100644 index 0000000000..34b466d4b5 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_requestArtillery.sqf @@ -0,0 +1,91 @@ +/* +Maintainer: John Jordan + Chooses and creates an area-effect support to attack a target position + +Scope: Server +Environment: Scheduled + +Arguments: + Side (occupants or invaders) which should send the support. + or Target position or object to be attacked. + Resource pool to be used for the support (probably "attack"). + Precision of support, should be based on knowledge of target (0 min, 4 max). + How much information to reveal about support, 0 low 1 high. + Optional, minimum delay in seconds before setup (Default: Calculated based on tier/aggro). + +Examples: + [Occupants, getposATL _rebelUnit, "attack", 1, 0, 300] remoteExec ["A3A_fnc_requestArtillery", 2]; +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_target", "_resPool", "_precision", "_reveal", "_delay"]; // might not be a unit, so we can't just use caller + +waitUntil { isNil "A3A_supportCallInProgress" }; +A3A_supportCallInProgress = true; + +Info_3("Requested artillery against %1 from %2 pool by side %3", _target, _resPool, _side); + +// Sort out target info +private _deprecisionRange = random (150 - ((_precision/4) * (_precision/4) * 125)); +private _targPos = _target getPos [_deprecisionRange, random 360]; + +if (_target isEqualType objNull) then { + // Find the first parent object. If we're using a static attached to a vehicle then the static is more important. + if (_target isKindOf "Man" and !(isNull objectParent _target)) then { _target = objectParent _target }; +} else { + _target = objNull; +}; +Debug_2("Final target %1 at position %2", _target, _targPos); + + +// Build hashmap of active supports with spare targets capable of hitting the area +private _actSuppHM = createHashMap; +{ + _x params ["_suppName", "_suppSide", "_suppType", "_center", "_radius", "_suppTarg", ["_minRadius", 0]]; + if (_suppSide != _side or _suppType in _actSuppHM) then { continue }; // only use first one found + private _dist = _targpos distance2d _center; + if (_suppTarg isNotEqualTo [] or _dist > _radius or _dist < _minRadius) then { continue }; // ready for new target + in range + _actSuppHM set [_suppType, _x]; +} forEach A3A_activeSupports; +Debug_1("Relevant active supports found: %1", _actSuppHM); + + +// Now determine the weight of each support type +private _weightedSupports = []; // [type, weight, type, weight, ...] +private _supportTypesHM = [A3A_supportTypesOcc, A3A_supportTypesInv] select (_side == Invaders); +private _availParams = [_target, _side, 200, keys _supportTypesHM]; +{ + _y params ["_class", "_typeWeight", "_effRadius"]; + if (_class != "AREA") then { continue }; // only care about area-effect for requestArtillery + + // call the availability function for each support type + private _availFunc = missionNamespace getVariable format ["A3A_fnc_SUP_%1Available", _x]; + private _targWeight = _availParams call _availFunc; + if (_targWeight <= 0) then { continue }; // support type unavailable + + private _finalWeight = _typeWeight * _targWeight; + if (_x in _actSuppHM) then { _finalWeight = _finalWeight * 3 }; // increase chance of re-using active supports + _weightedSupports append [_x, _finalWeight]; + +} forEach _supportTypesHM; // Hashmap of support type to [baseClass, typeWeight, effectRadius] +Debug_1("Weighted supports: %1", _weightedSupports); + +A3A_supportCallInProgress = nil; + + +private _supportCreated = ""; +while {_supportCreated == "" and _weightedSupports isNotEqualTo []} do +{ + private _supportChoice = selectRandomWeighted _weightedSupports; + private _index = _weightedSupports find _supportChoice; + _weightedSupports deleteAt _index; + _weightedSupports deleteAt _index; // delete both type and weight + + // params ["_type", "_side", "_caller", "_maxSpend", "_target", "_targPos", "_reveal", ["_delay", -1]]; + _supportCreated = [_supportChoice, _side, _resPool, 200, _target, _targPos, _reveal, _delay] call A3A_fnc_createSupport; +}; + +if (_supportCreated == "") then { + Info("No support sent because none available"); +}; diff --git a/A3A/addons/core/functions/Supports/fn_requestSupport.sqf b/A3A/addons/core/functions/Supports/fn_requestSupport.sqf new file mode 100644 index 0000000000..4b3e26e3ea --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_requestSupport.sqf @@ -0,0 +1,178 @@ +/* +Maintainer: John Jordan + Requests a suitable support against a target if resources permit + +Scope: Server +Environment: Scheduled + +Arguments: + The side (occupants or invaders) which should send the support. + The target object to be attacked. + Position of caller (used for defence resource allocation). + Precision of support, should be based on knowledge of target (0 min, 4 max). + How much information to reveal about support, 0 low 1 high. + +Examples: + [Occupants, _enemyUnit, getposATL _injured, 4, 0.75] call A3A_fnc_requestSupport; +*/ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() + +params ["_side", "_target", "_caller", "_precision", "_reveal"]; // might not be a unit, so we can't just use caller + +waitUntil { isNil "A3A_supportCallInProgress" }; +A3A_supportCallInProgress = true; + +Info_3("Requested support against %1 from %2 by side %3", _target, _caller, _side); + +// Cleanup old supports +A3A_supportSpends = A3A_supportSpends select { _x#4 + 3600 > time }; // remove one hour after start time +A3A_supportStrikes = A3A_supportStrikes select { _x#3 > time }; // remove after end time +A3A_activeSupports = A3A_activeSupports select { _x#4 > 0 }; // remove if support radius set to 0 + +// HQ knowledge update +call { + private _hqDist = _target distance2d markerPos "Synd_HQ"; + private _bunker = markerPos "Synd_HQ" nearObjects ["Land_Bunker_01_tall_F", 50] isNotEqualTo []; + private _maxSpot = (500 + random 1000) * ([0.5, 1] select _bunker); + _hqSpot = (1 + random 1) * linearConversion [0, _maxSpot, _hqDist, 1, 0, true]; + if (_hqSpot <= 0) exitWith {}; + + if (_side == Invaders) then { + A3A_curHQInfoInv = A3A_curHQInfoInv + _hqSpot * (100 + aggressionInvaders) / 400; // avg +0.75 for point-blank call at max aggro + } else { + A3A_curHQInfoOcc = A3A_curHQInfoOcc + _hqSpot * (100 + aggressionOccupants) / 400; + }; +}; + + +// Sort out target info +if (_target isEqualType objNull and {!alive _target}) exitWith { + Info("No support sent because target already destroyed"); + A3A_supportCallInProgress = nil; +}; +// Find the first parent object. If we're using a static attached to a vehicle then the static is more important. +if (_target isKindOf "Man" and !(isNull objectParent _target)) then { _target = objectParent _target }; + +private _deprecisionRange = random (100 - (_precision/4) * 80); +private _targPos = _target getPos [_deprecisionRange, random 360]; +Debug_2("Final target %1 at position %2", _target, _targPos); + + +// Determine maximum resource spend with this target & caller +private _maxSpend = [_side, _target, _caller] call A3A_fnc_maxDefenceSpend; +Debug_1("Resource max spend %1", _maxSpend); + + +// Calculate support type weighting factors based on other recent strikes near target +private _classWeightsHM = call { + // Shortcut this for air targets + if (_target isKindOf "Air") exitWith { createHashMapFromArray [["AREA", 0], ["TROOPS", 0], ["TARGET", 1]] }; + + // AREA has stronger reduction than TROOPS but over a smaller area + private _weightArea = 1; + private _weightTarget = 1; + private _weightTroops = 1; + { + _x params ["_sside", "_btype", "_starg", "_endtime", "_dur", "_pow"]; + if (_sside != _side or time >= _endtime) then { continue }; + switch (_btype) do { + case "AREA": { + private _dist = _starg distance2d _targpos; + if (_dist > _pow) exitWith {}; + private _reduce = (_pow/100) * (1 - _dist/_pow) * ((_endtime - time)/_dur); + _weightArea = _weightArea / (1 + _reduce); + }; + case "TROOPS": { + private _dist = _starg distance2d _targpos; + if (_dist > 600) exitWith {}; + private _reduce = (_pow/200) * (1 - _dist/600) * ((_endtime - time)/_dur); + _weightTroops = _weightTroops / (1 + _reduce); + }; + case "TARGET": { + if (_starg == _target) then { _weightTarget = 0 }; + }; + }; + } forEach A3A_supportStrikes; + createHashMapFromArray [["AREA", _weightArea], ["TROOPS", _weightTroops], ["TARGET", _weightTarget]] +}; +Debug_1("Base support type weights: %1", _classWeightsHM); + + +// Avoid making area attacks against friendlies, although "mistakes" can be made +private _nearfriendlies = units _side inAreaArray [_targPos, 200, 200]; +if (_side == Occupants) then { _nearFriendlies append (units civilian inAreaArray [_targPos, 200, 200]) }; +private _maxFriendlies = if (_side == Invaders) then { random [2, 4, 10] } else { random [0, 2, 5] }; + +// Occupants avoid making area attacks against groups of houses within towns +// many buildings within military facilities also count as HOUSE, so first check if we're inside a town radius +private _nearHouses = call { + if (_side == Invaders || { -1 == citiesX findIf { _targPos inArea _x }}) exitWith { [] }; + nearestTerrainObjects [_targPos, ["HOUSE"], 100, false]; +}; +private _maxHouses = (1 + random 5) ^ 2; +Debug_4("Total friendlies %1, max friendlies %2, total houses %3, max houses %4", count _nearFriendlies, _maxFriendlies, count _nearHouses, _maxHouses); + + +// Build hashmap of active supports with spare targets capable of hitting the area +private _actSuppHM = createHashMap; +{ + _x params ["_suppName", "_suppSide", "_suppType", "_center", "_radius", "_suppTarg", ["_minRadius", 0]]; + if (_suppSide != _side or _suppType in _actSuppHM) then { continue }; // only use first one found + private _dist = _targpos distance2d _center; + if (_suppTarg isNotEqualTo [] or _dist > _radius or _dist < _minRadius) then { continue }; + _actSuppHM set [_suppType, _x]; +} forEach A3A_activeSupports; +Debug_1("Relevant active supports found: %1", _actSuppHM); + + +// Now determine the weight of each support type +private _weightedSupports = []; // [type, weight, type, weight, ...] +private _supportTypesHM = [A3A_supportTypesOcc, A3A_supportTypesInv] select (_side == Invaders); +private _availParams = [_target, _side, _maxSpend, keys _supportTypesHM]; +{ + if (_maxSpend <= 0 and !(_x in _actSuppHM)) then { continue }; // Skip if we have no money and support type isn't active + _y params ["_class", "_typeWeight", "_effRadius"]; + + // First fetch the weight factor derived from other recent strikes near target + private _proxWeight = _classWeightsHM get _class; + if (_proxWeight <= 0) then { continue }; // support class overused or useless against target + + // call the availability function for each support type + private _availFunc = missionNamespace getVariable format ["A3A_fnc_SUP_%1Available", _x]; + private _targWeight = _availParams call _availFunc; + if (_targWeight <= 0) then { continue }; // support type unavailable + + // Check for friendlies and civilian houses within blast radius + if (_effRadius > 0) then { + private _friendlyCount = count (_nearfriendlies inAreaArray [_targpos, _effRadius, _effRadius]); + if (_friendlyCount > _maxFriendlies) then { continue }; + private _houseCount = count (_nearHouses inAreaArray [_targpos, _effRadius/2, _effRadius/2]); + if (_houseCount > _maxHouses) then { continue }; + }; + + private _finalWeight = _proxWeight * _typeWeight * _targWeight; + if (_x in _actSuppHM) then { _finalWeight = 1 max _finalWeight * 3 }; // increase chance of re-using active supports + _weightedSupports append [_x, _finalWeight]; + +} forEach _supportTypesHM; // Hashmap of support type to [base class, weight, effradius] +Debug_1("Weighted supports: %1", _weightedSupports); + +// drop the lock now, createSupport doesn't rely on data consistency +A3A_supportCallInProgress = nil; + + +private _supportCreated = ""; +while {_supportCreated == "" and _weightedSupports isNotEqualTo []} do +{ + private _supportChoice = selectRandomWeighted _weightedSupports; + private _index = _weightedSupports find _supportChoice; + _weightedSupports deleteAt _index; + _weightedSupports deleteAt _index; // delete both type and weight + + _supportCreated = [_supportChoice, _side, _caller, _maxSpend, _target, _targPos, _reveal, nil] call A3A_fnc_createSupport; +}; + +if (_supportCreated == "") then { + Info("No support sent because none available"); +}; diff --git a/A3A/addons/core/functions/Supports/fn_sendSupport.sqf b/A3A/addons/core/functions/Supports/fn_sendSupport.sqf deleted file mode 100644 index 38f5a8b3d0..0000000000 --- a/A3A/addons/core/functions/Supports/fn_sendSupport.sqf +++ /dev/null @@ -1,136 +0,0 @@ -/* -Author: Wurzel0701 - Sends the given support to the given position - -Arguments: - The target object that should be supported against - The precision that should be used against the target (range 0 - 4) - > The list of possible supports (first available send) - The side which should send the support (cannot be teamPlayer) - The reveal value for this support (range 0 - 1) - -Return Value: - - -Scope: Server -Environment: Scheduled -Public: Yes -Dependencies: - teamPlayer - supportCallInProgress - Occupants - occupantsSupports - invadersSupports - -Example: -[player, 2, ["QRF", "AIRSTRIKE"], Occupants, 0.75] call A3A_fnc_sendSupport; -*/ - -params -[ - "_target", - ["_precision", 0, [0]], - ["_supportTypes", [], [[]]], - ["_side", sideEnemy, [sideEnemy]], - ["_revealCall", 0, [0]] -]; -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() - -//Ensure this is running on the main server, otherwise it will break -if(!isServer) exitWith -{ - Error_1("SendSupport tried to execute on %1, which is not the hosting server!", clientOwner); - _this remoteExec ["A3A_fnc_sendSupport", 2]; -}; - -if(_side == teamPlayer) exitWith {}; - -waitUntil {sleep 0.1; !supportCallInProgress}; -supportCallInProgress = true; - -//Calculate deprecision on position -private _deprecisionRange = random (150 - ((_precision/4) * (_precision/4) * 125)); -private _randomDir = random 360; -private _supportPos = _target getPos [_deprecisionRange, _randomDir]; - -//Search for any support already active in the area matching the _supportTypes -private _supportObject = ""; -private _supportType = ""; -private _blockedSupports = []; - -private _supportArray = if(_side == Occupants) then {occupantsSupports} else {invadersSupports}; -{ - _supportType = _x; - private _index = -1; - _index = _supportArray findIf {((_x select 0) == _supportType) && {_supportPos inArea (_x select 1)}}; - - if((_index != -1) && {_supportType in ["AIRSTRIKE", "QRF"]}) then - { - Info_1("Blocking %1 support for given position, as another support of this type is near", _supportType); - _index = -1; - _blockedSupports pushBack _supportType; - }; - - if(_index != -1) exitWith - { - _supportObject = _supportArray select _index select 2; - }; -} forEach _supportTypes; - - -//Support is already in the area, send instructions to them -if (_supportObject != "") exitWith -{ - supportCallInProgress = false; - if(_supportType != "QRF") then - { - Info_1("Support of type %1 is already in the area, transmitting attack orders", _supportType); - - //Attack with already existing support - if(_supportType in ["MORTAR"]) then - { - //Areal support methods, transmit position info - [_supportObject, [_supportPos, _precision], _revealCall] call A3A_fnc_addSupportTarget; - }; - if(_supportType in ["CAS", "ASF", "SAM", "GUNSHIP", "MISSILE", "CAS"]) then - { - //Target support methods, transmit target info - [_supportObject, [_target, _precision], _revealCall] call A3A_fnc_addSupportTarget; - }; - }; -}; -//Delete blocked supports -_supportTypes = _supportTypes - _blockedSupports; - -private _selectedSupport = ""; -private _timerIndex = -1; -{ - _timerIndex = [_x, _side, _supportPos] call A3A_fnc_supportAvailable; - if (_timerIndex != -1) exitWith - { - _selectedSupport = _x; - }; -} forEach _supportTypes; - -if(_selectedSupport == "") exitWith -{ - Info_1("No support available to support at %1", _supportPos); - supportCallInProgress = false; -}; - -Info_2("Sending support type %1 to help at %2", _selectedSupport, _supportPos); - -if(_selectedSupport in ["MORTAR", "QRF", "AIRSTRIKE", "ORBSTRIKE", "CARPETBOMB"]) then -{ - //Areal support methods, transmit position info - [_side, _timerIndex, _selectedSupport, _supportPos, _precision, _revealCall] spawn A3A_fnc_createSupport; -}; -if(_selectedSupport in ["CAS", "ASF", "SAM", "GUNSHIP", "MISSILE"]) then -{ - //Target support methods, transmit target info - [_side, _timerIndex, _selectedSupport, _target, _precision, _revealCall] spawn A3A_fnc_createSupport; -}; - -//Blocks the same support for ten minutes or until a new support happens -server setVariable ["lastSupport", [_selectedSupport, time + 600], true]; diff --git a/A3A/addons/core/functions/Supports/fn_showInterceptedSetupCall.sqf b/A3A/addons/core/functions/Supports/fn_showInterceptedSetupCall.sqf index 6197fe830e..600e66bd83 100644 --- a/A3A/addons/core/functions/Supports/fn_showInterceptedSetupCall.sqf +++ b/A3A/addons/core/functions/Supports/fn_showInterceptedSetupCall.sqf @@ -1,14 +1,5 @@ #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() -params -[ - ["_reveal", 0, [0]], - ["_side", sideEnemy, [sideEnemy]], - ["_supportType", "", [""]], - ["_position", [], [[]]], - ["_minSetupTime", 60, [0]], - ["_maxSetupTime", 400, [0]] -]; /* Shows the intercepted radio setup message to the players @@ -17,73 +8,25 @@ params Scope: Internal Parameters: - _reveal: NUMBER : Decides how much of the info will be revealed + _reveal: NUMBER : 0-1, determines how much info to revealed _side: SIDE : The side which called in the support - _supportType: NAME : The name of the support (not the callsign!!) + _supportType: STRING : The type of the support + _position: ARRAY : Target position of support + _setupTime : NUMBER : Approximate setup time in seconds Returns: Nothing */ -_fn_getTimeString = -{ - params - [ - ["_time", 0, [0]], - ["_isLower", true, [true]] - ]; - - _time = _time / 60; - - private _result = ""; - if(_time < 1) then - { - _result = "<1"; - } - else - { - _time = _time - 0.49; - if(_isLower) then - { - _result = format ["%1", round _time]; - } - else - { - _result = format ["%1", (round _time) + 1]; - }; - }; +// TODO: add source/setup position? - _result; -}; - -//If you have found a key before, you get the full message if it is somewhere around your HQ -if(_position distance2D (getMarkerPos "Synd_HQ") < distanceMission) then -{ - if(_side == Occupants) then - { - if(occupantsRadioKeys > 0) then - { - occupantsRadioKeys = occupantsRadioKeys - 1; - publicVariable "occupantsRadioKeys"; - _reveal = 1; - }; - } - else - { - if(invaderRadioKeys > 0) then - { - invaderRadioKeys = invaderRadioKeys - 1; - publicVariable "invaderRadioKeys"; - _reveal = 1; - }; - }; -}; +params ["_reveal", "_side", "_supportType", "_position", "_setupTime"]; //Nothing will be revealed if(_reveal <= 0.2) exitWith {}; private _text = ""; -private _sideName = if(_side == Occupants) then {FactionGet(occ,"name")} else {FactionGet(inv,"name")}; +private _sideName = Faction(_side) get "name"; if (_reveal <= 0.5) then { //Side and setup is revealed @@ -91,11 +34,23 @@ if (_reveal <= 0.5) then } else { - switch (_supportType) do + switch (toupper _supportType) do { - case ("QRF"): + case ("MAJORATTACK"): + { + _text = format ["%1 just sent a major attack wave", _sideName]; + }; + case ("COUNTERATTACK"): { - _text = format ["%1 just sent a QRF", _sideName]; + _text = format ["%1 just sent a counterattack force", _sideName]; + }; + case ("QRFAIR"): + { + _text = format ["%1 just sent an airborne QRF", _sideName]; + }; + case ("QRFLAND"): + { + _text = format ["%1 just sent a land QRF", _sideName]; }; case ("AIRSTRIKE"): { @@ -105,11 +60,15 @@ else { _text = format ["%1 is setting up a mortar position", _sideName]; }; - case ("ORBSTRIKE"): + case ("ARTILLERY"): + { + _text = format ["%1 is preparing an artillery position", _sideName]; + }; + case ("ORBITALSTRIKE"): { _text = format ["A %1 satellite is preparing an orbital strike", _sideName]; }; - case ("MISSILE"): + case ("CRUISEMISSILE"): { _text = format ["A %1 cruiser is readying a cruise missile", _sideName]; }; @@ -117,9 +76,9 @@ else { _text = format ["%1 is setting up a SAM launcher", _sideName]; }; - case ("CARPETBOMB"): + case ("CARPETBOMBS"): { - _text = format ["A heavy %1 bomber is on the way", _sideName]; + _text = format ["A %1 heavy bomber is on the way", _sideName]; }; case ("ASF"): { @@ -133,6 +92,10 @@ else { _text = format ["%1 is loading up a heavy gunship", _sideName]; }; + case ("UAV"): + { + _text = format ["%1 is sending a spotting UAV", _sideName]; + }; default { _text = format ["%1 is setting up %2 support", _sideName, _supportType]; @@ -140,15 +103,19 @@ else }; }; +// Randomise setup time less with higher reveal value +_setupTime = _setupTime * (_reveal + random (2 - 2*_reveal)); +private _timeStr = if(_setupTime < 60) then { "<1" } else { str round (_setupTime / 60) }; + if(_reveal >= 0.8) then { - if(_supportType == "QRF") then + if(toupper _supportType in ["QRFLAND", "QRFAIR", "COUNTERATTACK", "MAJORATTACK"]) then { - _text = format ["%1. Estimated arrival in %2 to %3 minutes", _text, [_minSetupTime, true] call _fn_getTimeString, [_maxSetupTime, false] call _fn_getTimeString]; + _text = format ["%1. Estimated arrival in %2 minutes", _text, _timeStr]; } else { - _text = format ["%1. Estimated setup: %2 to %3 minutes", _text, [_minSetupTime, true] call _fn_getTimeString, [_maxSetupTime, false] call _fn_getTimeString]; + _text = format ["%1. Estimated setup: %2 minutes", _text, _timeStr]; }; }; diff --git a/A3A/addons/core/functions/Supports/fn_showInterceptedSupportCall.sqf b/A3A/addons/core/functions/Supports/fn_showInterceptedSupportCall.sqf index 619641a55b..ae07e24606 100644 --- a/A3A/addons/core/functions/Supports/fn_showInterceptedSupportCall.sqf +++ b/A3A/addons/core/functions/Supports/fn_showInterceptedSupportCall.sqf @@ -1,7 +1,3 @@ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -params ["_reveal", "_position", "_side", "_supportType", "_marker", "_textMarker"]; - /* Shows the intercepted radio message to the players Execution on: Server @@ -9,44 +5,26 @@ params ["_reveal", "_position", "_side", "_supportType", "_marker", "_textMarker Scope: Internal Parameters: - _reveal: NUMBER : Decides how much of the info will be revealed + _reveal: NUMBER : 0-1, determines how much info will be revealed _position: POSITION : The position where the support is called to _side: SIDE : The side which called in the support - _supportType: NAME : The name of the support (not the callsign!!) - _marker: MARKER : The marker which covers the area of the attack - _textMarker: MARKER : The marker which is holding the text of the support + _supportType: STRING : The type string of the support (not the support name) + _markerType: NUMBER or OBJECT : Either the radius (for area attacks) or target object for the marker + _markerLifeTime: NUMBER : Time in seconds for the marker to survive Returns: Nothing */ +#include "..\..\script_component.hpp" +FIX_LINE_NUMBERS() -//If you have found a key before, you get the full message if it is somewhere around your HQ -if(_position distance2D (getMarkerPos "Synd_HQ") < distanceMission) then -{ - if(_side == Occupants) then - { - if(occupantsRadioKeys > 0) then - { - occupantsRadioKeys = occupantsRadioKeys - 1; - publicVariable "occupantsRadioKeys"; - _reveal = 1; - }; - } - else - { - if(invaderRadioKeys > 0) then - { - invaderRadioKeys = invaderRadioKeys - 1; - publicVariable "invaderRadioKeys"; - _reveal = 1; - }; - }; -}; +params ["_reveal", "_position", "_side", "_supportType", "_markerType", "_markerLifeTime"]; //Nothing will be revealed if(_reveal <= 0.2) exitWith {}; private _text = ""; +private _markerText = ""; private _sideName = if(_side == Occupants) then {FactionGet(occ,"name")} else {FactionGet(inv,"name")}; if (_reveal <= 0.5) then { @@ -55,59 +33,120 @@ if (_reveal <= 0.5) then } else { - switch (_supportType) do + switch (toupper _supportType) do { - case ("QRF"): + case ("QRFLAND"): { - _text = format ["A %1 QRF just arrived", _sideName]; + _text = format ["A %1 land QRF just arrived", _sideName]; + _markerText = "Land QRF"; + }; + case ("QRFAIR"): + { + _text = format ["A %1 air QRF just arrived", _sideName]; + _markerText = "Air QRF"; }; case ("AIRSTRIKE"): { _text = format ["%1 is about to execute an airstrike", _sideName]; + _markerText = "Airstrike"; + }; + case ("ARTILLERY"): + { + _text = format ["A %1 artillery piece has opened fire", _sideName]; + _markerText = "Artillery strike"; }; case ("MORTAR"): { _text = format ["A %1 mortar has opened fire", _sideName]; + _markerText = "Mortar strike"; }; - case ("ORBSTRIKE"): + case ("ORBITALSTRIKE"): { _text = format ["A %1 satellite has fired the orbital strike", _sideName]; + _markerText = "Orbital strike"; }; - case ("MISSILE"): + case ("CRUISEMISSILE"): { _text = format ["%1 cruise missile launched", _sideName]; + _markerText = "Cruise missile"; }; case ("SAM"): { - _text = format ["%1 SAM missile launched", _sideName]; + _text = format ["%1 SAM launcher is acquiring a target", _sideName]; + _markerText = "SAM target"; }; - case ("CARPETBOMB"): + case ("CARPETBOMBS"): { - _text = format ["%1 bomber started to lay down a carpet bombing", _sideName]; + _text = format ["%1 bomber is carrying out a carpet bombing", _sideName]; + _markerText = "Carpet bombing"; }; case ("ASF"): { _text = format ["%1 fighter started chasing a target", _sideName]; + _markerText = "Air superiority target"; }; case ("CAS"): { - _text = format ["A %1 CAS bomber has locked onto a target", _sideName]; + _text = format ["A %1 CAS bomber is acquiring a target", _sideName]; + _markerText = "CAS target"; }; case ("GUNSHIP"): { - _text = format ["A %1 heavy gunship started cycling the area", _sideName]; + _text = format ["A %1 heavy gunship started circling the area", _sideName]; + _markerText = "Gunship"; }; default { _text = format ["%1 is executing %2 support now", _sideName, _supportType]; + _markerText = format ["%1 support", _supportType]; }; }; - if(_reveal > 0.8) then + + if(_reveal < 0.8) exitWith {}; + + _text = format ["%1. Target marked on map!", _text]; + private _targetMarker = format ["%1_target_%2", _supportType, A3A_supportMarkerCount]; + private _textMarker = format ["%1_text_%2", _supportType, A3A_supportMarkerCount]; + A3A_supportMarkerCount = A3A_supportMarkerCount + 1; + + if (_markerType isEqualType 0) then { - //Side, type, call and marker revealed - _text = format ["%1. Target marked on map!", _text]; - _marker setMarkerAlpha 0.75; - _textMarker setMarkerAlpha 1; + createMarkerLocal [_targetMarker, _position]; + _targetMarker setMarkerShapeLocal "ELLIPSE"; + _targetMarker setMarkerBrushLocal "Grid"; + _targetMarker setMarkerSizeLocal [_markerType, _markerType]; // actually a radius + _targetMarker setMarkerColorLocal (if(_side == Occupants) then { colorOccupants } else { colorInvaders }); + _targetMarker setMarkerAlpha 1; + + createMarkerLocal [_textMarker, _position]; + _textMarker setMarkerShapeLocal "ICON"; + _textMarker setMarkerTypeLocal "mil_dot"; + _textMarker setMarkerTextLocal _markerText; + _textMarker setMarkerAlpha 0.75; + + [_textMarker, _targetMarker, _markerLifeTime] spawn { + params ["_textMarker", "_targetMarker", "_lifeTime"]; + sleep _lifeTime; + deleteMarker _textMarker; + deleteMarker _targetMarker; + }; + } + else + { + createMarkerLocal [_textMarker, _position]; + _textMarker setMarkerShapeLocal "ICON"; + _textMarker setMarkerTypeLocal "mil_objective"; + _textMarker setMarkerTextLocal _markerText; + _textMarker setMarkerAlphaLocal 0.75; + + [_textMarker, _markerType, time + _markerlifeTime] spawn { + params ["_marker", "_target", "_timeout"]; + while { time < _timeout and alive _target } do { + _marker setMarkerPos getPos _target; + sleep 5; + }; + deleteMarker _marker; + }; }; }; diff --git a/A3A/addons/core/functions/Supports/fn_supportAvailable.sqf b/A3A/addons/core/functions/Supports/fn_supportAvailable.sqf deleted file mode 100644 index c2bbf3603c..0000000000 --- a/A3A/addons/core/functions/Supports/fn_supportAvailable.sqf +++ /dev/null @@ -1,105 +0,0 @@ -params ["_supportType", "_side", "_position"]; - -/* Checks if the given support is available for use - - Execution on: Server - - Scope: External - - Params: - _supportType: STRING : The type of support that should be checked - _side: SIDE : The side for which the availability should be checked - - Returns: - -1 if not available, the index of the timer otherwise -*/ -#include "..\..\script_component.hpp" -FIX_LINE_NUMBERS() -private _timerIndex = -1; -private _arrays = []; - -switch (_supportType) do -{ - case ("QRF"): //Normal quick responce force - { - _timerIndex = [_side, _position] call A3A_fnc_SUP_QRFAvailable; - }; - case ("AIRSTRIKE"): //Normal airstrike - { - _timerIndex = [_side] call A3A_fnc_SUP_airstrikeAvailable; - _arrays = if(_side == Occupants) then {occupantsAirstrikeTimer} else {invadersAirstrikeTimer}; - }; - case ("MORTAR"): //Normal mortar barrage - { - _timerIndex = [_side] call A3A_fnc_SUP_mortarAvailable; - _arrays = if(_side == Occupants) then {occupantsMortarTimer} else {invadersMortarTimer}; - }; - case ("ORBSTRIKE"): //Orbital strike - { - _timerIndex = [_side, _position] call A3A_fnc_SUP_orbitalStrikeAvailable; - _arrays = if(_side == Occupants) then {occupantsOrbitalStrikeTimer} else {invadersOrbitalStrikeTimer}; - }; - case ("MISSILE"): //Cruise missile - { - _timerIndex = [_side, _position] call A3A_fnc_SUP_cruiseMissileAvailable; - _arrays = if(_side == Occupants) then {occupantsCruiseMissileTimer} else {invadersCruiseMissileTimer}; - }; - case ("SAM"): //Surface to air missile - { - _timerIndex = [_side, _position] call A3A_fnc_SUP_SAMAvailable; - _arrays = if(_side == Occupants) then {occupantsSAMTimer} else {invadersSAMTimer}; - }; - case ("CARPETBOMB"): //Carpet bombing - { - _timerIndex = [_side] call A3A_fnc_SUP_carpetBombsAvailable; - _arrays = if(_side == Occupants) then {occupantsCarpetBombTimer} else {invadersCarpetBombTimer}; - }; - case ("CAS"): //Close air support - { - _timerIndex = [_side] call A3A_fnc_SUP_CASAvailable; - _arrays = if(_side == Occupants) then {occupantsCASTimer} else {invadersCASTimer}; - }; - case ("ASF"): //Air superiority fighters - { - _timerIndex = [_side] call A3A_fnc_SUP_ASFAvailable; - _arrays = if(_side == Occupants) then {occupantsASFTimer} else {invadersASFTimer}; - }; - case ("GUNSHIP"): //Heavily armed plane - { - _timerIndex = [_side] call A3A_fnc_SUP_gunshipAvailable; - _arrays = if(_side == Occupants) then {occupantsGunshipTimer} else {invadersGunshipTimer}; - }; - /* NOT YET IMPLEMENTED - - case ("CANNON"): //Long range artillery - { - - } - case ("EMP"): //Electromagnetic puls - { - - } - case ("AIRDROP"): //Airborne vehicle insertion - { - - } - case ("RECON"): //Airbased recon - { - - } - case ("SEAD"): //Suppression of Enemy Air Defense bomber - { - - } - */ - default - { - //If unknown, set not available - Debug_1("Unknown support %1, returning -1", _supportType); - _timerIndex = -1; - }; -}; - -Debug_3("Support check for %1 returns %2, array is %3", _supportType, _timerIndex, _arrays); - -_timerIndex; diff --git a/A3A/addons/core/functions/Supports/fn_useRadioKey.sqf b/A3A/addons/core/functions/Supports/fn_useRadioKey.sqf new file mode 100644 index 0000000000..79d024ba43 --- /dev/null +++ b/A3A/addons/core/functions/Supports/fn_useRadioKey.sqf @@ -0,0 +1,31 @@ +/* + Spend a radio key (if available) to boost reveal value + +Scope: Server +Arguments: + The side (occupants or invaders) which should send the support. + Target position of support/attack/whatever. + How much information to reveal about support, 0 low 1 high. + +Returns: + Modified reveal value +*/ + +params ["_side", "_position", "_reveal"]; + +// Don't waste a key if we already have max info +if (_reveal >= 0.8) exitWith { _reveal }; + +if(_position distance2D markerPos "Synd_HQ" < distanceMission) then +{ + if(_side == Occupants && occupantsRadioKeys > 0) then { + occupantsRadioKeys = occupantsRadioKeys - 1; + _reveal = 1; + }; + if(_side == Invaders && invaderRadioKeys > 0) then { + invaderRadioKeys = invaderRadioKeys - 1; + _reveal = 1; + }; +}; + +_reveal; diff --git a/A3A/addons/core/functions/Templates/Verification/fn_TV_verifyAssets.sqf b/A3A/addons/core/functions/Templates/Verification/fn_TV_verifyAssets.sqf index b0c56d2294..72d2c06643 100644 --- a/A3A/addons/core/functions/Templates/Verification/fn_TV_verifyAssets.sqf +++ b/A3A/addons/core/functions/Templates/Verification/fn_TV_verifyAssets.sqf @@ -158,6 +158,17 @@ private _handleUniqueCases = { //handles unique name cases that the stored value ["CfgMagazines",(_x#0),_entry] call _validClassCaseSensitive; } forEach _y; }; + case "attributesVehicles": { + if !(_y isEqualType []) exitWith {_invalidReasons pushBack ("Entry "+(str _entry)+" is not an array.")}; + { + if !(_x isEqualTypeParams ["", []]) then {_invalidReasons pushBack ("Entry: "+(str _entry)+" -> "+(str _x)+" has the wrong data type(s). Expected [Class, Attribute]"); continue}; + private _veh = _x#0; + { + if (_forEachIndex == 0) then {["CfgVehicles",_x,_entry] call _validClassCaseSensitive; continue}; + if !(_x isEqualTypeArray ["", 0]) then {_invalidReasons pushBack ("Vehicle attribute "+(str _x)+" for "+_veh+" has the wrong data types(s). Expected [Attribute, Value]")}; + } forEach _x; + } forEach _y; + }; case "diveGear"; //Mixed CFGVehicles and CFGGlasses case "flyGear"; case "voices"; //CfgVoice maybe later diff --git a/A3A/addons/core/functions/Templates/fn_compatibilityLoadFaction.sqf b/A3A/addons/core/functions/Templates/fn_compatibilityLoadFaction.sqf index c796a34223..f06845819d 100644 --- a/A3A/addons/core/functions/Templates/fn_compatibilityLoadFaction.sqf +++ b/A3A/addons/core/functions/Templates/fn_compatibilityLoadFaction.sqf @@ -70,11 +70,12 @@ private _allDefinitions = _faction get "loadouts"; [_faction, _side, _file] call A3A_fnc_TV_verifyAssets; #endif -//compile collection list of vehicles for occ and inv if (_side in [Occupants, Invaders]) then { - _faction set ["vehiclesLight", (_faction get "vehiclesLightArmed") + (_faction get "vehiclesLightUnarmed")]; - _faction set ["vehiclesAttack", (_faction get "vehiclesAPCs") + (_faction get "vehiclesTanks")]; - _faction set ["vehiclesBoats", (_faction get "vehiclesGunBoats") + (_faction get "vehiclesTransportBoats")]; + // Compile light armed that also have 4+ passenger seats + private _lightArmedTroop = (_faction get "vehiclesLightArmed") select { + ([_x, true] call BIS_fnc_crewCount) - ([_x, false] call BIS_fnc_crewCount) >= 4 + }; + _faction set ["vehiclesLightArmedTroop", _lightArmedTroop]; }; _faction; diff --git a/A3A/addons/core/functions/Templates/fn_compileGroups.sqf b/A3A/addons/core/functions/Templates/fn_compileGroups.sqf index f6a3790ea5..39e665d697 100644 --- a/A3A/addons/core/functions/Templates/fn_compileGroups.sqf +++ b/A3A/addons/core/functions/Templates/fn_compileGroups.sqf @@ -67,11 +67,11 @@ for "_i" from 1 to 5 do { _squads pushBack [ unit(military, "SquadLeader"), selectRandomWeighted [unit(military, "LAT"), 2, unit(military, "MachineGunner"), 1], - selectRandomWeighted [unit(military, "Rifleman"), 2, unit(military, "Grenadier"), 1], + selectRandomWeighted [unit(military, "Rifleman"), 1, unit(military, "Grenadier"), 2], selectRandomWeighted [unit(military, "MachineGunner"), 2, unit(military, "Marksman"), 1], - selectRandomWeighted [unit(military, "Rifleman"), 4, unit(military, "AT"), 1], - selectRandomWeighted [unit(military, "AA"), 1, unit(military, "Engineer"), 4], - unit(military, "Rifleman"), + selectRandomWeighted [unit(military, "Engineer"), 3, unit(military, "AT"), 1], + selectRandomWeighted [unit(military, "AA"), 1, unit(military, "Rifleman"), 3], + selectRandomWeighted [unit(military, "Rifleman"), 2, unit(military, "Marksman"), 1], unit(military, "Medic") ]; }; diff --git a/A3A/addons/core/functions/Templates/fn_compileMissionAssets.sqf b/A3A/addons/core/functions/Templates/fn_compileMissionAssets.sqf index de24bc2b61..e3cdbbc69d 100644 --- a/A3A/addons/core/functions/Templates/fn_compileMissionAssets.sqf +++ b/A3A/addons/core/functions/Templates/fn_compileMissionAssets.sqf @@ -63,16 +63,24 @@ setVar("vehiclesPolice", OccAndInv("vehiclesPolice")); setVar("vehiclesAttack", OccAndInv("vehiclesAttack") ); setVar("vehiclesUAVs", OccAndInv("uavsAttack")+ OccAndInv("uavsPortable") ); setVar("vehiclesAmmoTrucks", OccAndInv("vehiclesAmmoTrucks") ); +setVar("vehiclesLightAPCs", OccAndInv("vehiclesLightAPCs")); setVar("vehiclesAPCs", OccAndInv("vehiclesAPCs") ); +setVar("vehiclesIFVs", OccAndInv("vehiclesIFVs") ); setVar("vehiclesTanks", OccAndInv("vehiclesTanks")); -setVar("vehiclesAA", OccAndInv("vehiclesAA") ); +setVar("vehiclesAA", OccAndInv("vehiclesAA") + [Reb("vehicleAA")] - [""]); setVar("vehiclesArtillery", OccAndInv("vehiclesArtillery")); setVar("vehiclesTransportAir", OccAndInv("vehiclesHelisLight") + OccAndInv("vehiclesHelisTransport") + OccAndInv("vehiclesPlanesTransport") ); setVar("vehiclesHelisLight", OccAndInv("vehiclesHelisLight")); +setVar("vehiclesHelisLightAttack", OccAndInv("vehiclesHelisLightAttack")); setVar("vehiclesHelisAttack", OccAndInv("vehiclesHelisAttack")); setVar("vehiclesHelisTransport", OccAndInv("vehiclesHelisTransport")); +setVar("vehiclesPlanesAA", OccAndInv("vehiclesPlanesAA")); +setVar("vehiclesPlanesCAS", OccAndInv("vehiclesPlanesCAS")); setVar("vehiclesPlanesTransport", OccAndInv("vehiclesPlanesTransport")); setVar("staticMortars", OccAndInv("staticMortars") + [Reb("staticMortar")]); +setVar("staticAA", OccAndInv("staticAA") + [Reb("staticAA")]); +setVar("staticAT", OccAndInv("staticAT") + [Reb("staticAT")]); +setVar("staticMG", OccAndInv("staticMG") + [Reb("staticMG")]); private _vehMilitia = OccAndInv("vehiclesMilitiaCars") + OccAndInv("vehiclesMilitiaTrucks") @@ -86,6 +94,7 @@ setVar("vehiclesBoats", _vehBoats); //Occ&Inv helicopters private _vehHelis = OccAndInv("vehiclesHelisTransport") ++ OccAndInv("vehiclesHelisLightAttack") + OccAndInv("vehiclesHelisAttack") + OccAndInv("vehiclesHelisLight"); setVar("vehiclesHelis", _vehHelis); @@ -105,30 +114,31 @@ OccAndInv("vehiclesTrucks") + [Reb("vehicleTruck")]; setVar("vehiclesTrucks", _vehTrucks); +//Armed cars +private _carsArmed = +OccAndInv("vehiclesLightArmed") ++ OccAndInv("vehiclesMilitiaLightArmed") ++ [Reb("vehicleLightArmed")]; +setVar("vehiclesLightArmed", _carsArmed); + +//Unarmed cars +private _carsUnarmed = +OccAndInv("vehiclesLightUnarmed") // anything else? ++ OccAndInv("vehiclesMilitiaCars") ++ OccAndInv("vehiclesPolice") ++ [Reb("vehicleLightUnarmed")]; +setVar("vehiclesLightUnarmed", _carsUnarmed); +setVar("vehiclesLight", _carsArmed + _carsUnarmed); + //all Occ&Inv armor private _vehArmor = getVar("vehiclesTanks") + getVar("vehiclesAA") + getVar("vehiclesArtillery") + getVar("vehiclesAPCs"); ++ getVar("vehiclesIFVs"); setVar("vehiclesArmor", _vehArmor); -//vehicles that the AI have "unlimited" of -private _vehUnlimited = -OccAndInv("vehiclesLight") -+ OccAndInv("vehiclesTrucks") -+ OccAndInv("vehiclesAmmoTrucks") -+ OccAndInv("vehiclesRepairTrucks") -+ OccAndInv("vehiclesFuelTrucks") -+ OccAndInv("vehiclesMedical") -+ OccAndInv("vehiclesTransportBoats") -+ OccAndInv("vehiclesHelisLight") -+ OccAndInv("uavsAttack") -+ OccAndInv("uavsPortable") -+ OccAndInv("staticMGs") -+ OccAndInv("staticMortars"); -setVar("vehiclesUnlimited", _vehUnlimited); - //rebel vehicles private _vehReb = [ Reb("vehicleBasic"), Reb("vehicleTruck"), Reb("vehicleRepair"), Reb("vehicleBoat") diff --git a/A3A/addons/core/functions/Undercover/fn_canGoUndercover.sqf b/A3A/addons/core/functions/Undercover/fn_canGoUndercover.sqf index aad1224c05..f328b27c2e 100644 --- a/A3A/addons/core/functions/Undercover/fn_canGoUndercover.sqf +++ b/A3A/addons/core/functions/Undercover/fn_canGoUndercover.sqf @@ -18,7 +18,6 @@ Dependencies: outposts seaports undercoverVehicles - reportedVehs allArmoredHeadgear sidesX teamPlayer @@ -54,7 +53,7 @@ if !(isNull (objectParent player)) then ["Undercover", "You are not in a civilian vehicle."] call A3A_fnc_customHint; _result = [false, "In non civilian vehicle"]; }; - if ((objectParent player) in reportedVehs) then + if ((objectParent player) getVariable ["A3A_reported", false]) then { ["Undercover", "This vehicle has been reported to the enemy. Change or renew your vehicle in the Garage to go Undercover."] call A3A_fnc_customHint; _result = [false, "In reported vehicle"]; diff --git a/A3A/addons/core/functions/Undercover/fn_goUndercover.sqf b/A3A/addons/core/functions/Undercover/fn_goUndercover.sqf index 069e7972d5..7d3052f4cf 100644 --- a/A3A/addons/core/functions/Undercover/fn_goUndercover.sqf +++ b/A3A/addons/core/functions/Undercover/fn_goUndercover.sqf @@ -14,7 +14,6 @@ Public: Yes Dependencies: A3A_faction_civ A3A_faction_reb - reportedVehs controlsX airportsX outposts @@ -44,8 +43,7 @@ if(!(_result select 0)) exitWith { if !(isNull (objectParent player)) then { - reportedVehs pushBackUnique (objectParent player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; { if ((isPlayer _x) && (captive _x)) then { @@ -102,7 +100,7 @@ while {_reason == ""} do _reason = "VNoCivil" }; - if (_veh in reportedVehs) exitWith + if (_veh getVariable ["A3A_reported", false]) exitWith { _reason = "VCompromised" }; @@ -229,8 +227,7 @@ switch (_reason) do ["Undercover", "You have been reported or spotted by the enemy!"] call A3A_fnc_customHint; if (vehicle player != player) then { - reportedVehs pushBackUnique (objectParent player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; } else { @@ -248,14 +245,12 @@ switch (_reason) do case "SpotBombTruck": { ["Undercover", "Explosives have been spotted on your vehicle!"] call A3A_fnc_customHint; - reportedVehs pushBackUnique (objectParent player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; }; case "Highway": { ["Undercover", "You went too far away from any roads and have been spotted!"] call A3A_fnc_customHint; - reportedVehs pushBackUnique (objectParent player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; }; case "clothes": { @@ -284,8 +279,7 @@ switch (_reason) do ["Undercover", "You have gotten too close to an enemy Base, Outpost or Roadblock!"] call A3A_fnc_customHint; if !(isNull objectParent player) then { - reportedVehs pushBackUnique (objectParent player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; } else { @@ -297,15 +291,13 @@ switch (_reason) do private _veh = objectParent player; private _detectedBy = _veh getVariable "NoFlyZoneDetected"; ["Undercover", format ["You have violated the airspace of %1!", [_detectedBy] call A3A_fnc_localizar]] call A3A_fnc_customHint; - reportedVehs pushBackUnique _veh; - publicVariable "reportedVehs"; + _veh setVariable ["A3A_reported", true, true]; _veh setVariable ["NoFlyZoneDetected", nil, true]; }; case "Control": { ["Undercover", "The Installation Garrison has recognised you!"] call A3A_fnc_customHint; - reportedVehs pushBackUnique(vehicle player); - publicVariable "reportedVehs"; + (objectParent player) setVariable ["A3A_reported", true, true]; }; default { diff --git a/A3A/addons/core/functions/init/fn_clientIdleChecker.sqf b/A3A/addons/core/functions/init/fn_clientIdleChecker.sqf new file mode 100644 index 0000000000..aa320f8925 --- /dev/null +++ b/A3A/addons/core/functions/init/fn_clientIdleChecker.sqf @@ -0,0 +1,36 @@ +/* Persistent loop to check whether player is idle and pass that information to the server + +Scope: Client +Environment: Spawned + +Arguments: + None +*/ + +#define TIMEOUT_AFK 120 + +A3A_lastActiveTime = time; +A3A_lastPlayerDir = getDir player; + +// In case commander is just controlling HC squads on the map +addMissionEventHandler ["HCGroupSelectionChanged", { + if (player getVariable ["isAFK", false]) then { player setVariable ["isAFK", nil, [2, clientOwner]] }; + A3A_lastActiveTime = time; +}]; + +while {true} do { + sleep 10; + private _oldDir = A3A_lastPlayerDir; + A3A_lastPlayerDir = getDir player; + + // "speed player" return zero for sideways walking/crawling + if (A3A_lastPlayerDir != _oldDir or vectorMagnitude velocity player > 0.1) then { + A3A_lastActiveTime = time; + if (player getVariable ["isAFK", false]) then { player setVariable ["isAFK", nil, [2, clientOwner]] }; + continue; + }; + + if (time - A3A_lastActiveTime > TIMEOUT_AFK and !(player getVariable ["isAFK", false])) then { + player setVariable ["isAFK", true, [2, clientOwner]]; + }; +}; diff --git a/A3A/addons/core/functions/init/fn_initACEUnconsciousHandler.sqf b/A3A/addons/core/functions/init/fn_initACEUnconsciousHandler.sqf index 153ad52a5d..0c70240a08 100644 --- a/A3A/addons/core/functions/init/fn_initACEUnconsciousHandler.sqf +++ b/A3A/addons/core/functions/init/fn_initACEUnconsciousHandler.sqf @@ -1,3 +1,10 @@ +/* + Handler for the ACE medical unconscious event + + No arguments or return + Should be installed on every machine. +*/ + scriptName "initACEUnconsciousHandler.sqf"; #include "..\..\script_component.hpp" FIX_LINE_NUMBERS() @@ -5,50 +12,53 @@ Info("initACEUnconsciousHandler started"); ["ace_unconscious", { params["_unit", "_knockout"]; + if !(local _unit) exitWith {}; // handler runs everywhere, only process where unit is local private _realSide = side group _unit; // setUnconscious in ACE often breaks this otherwise - if (_knockout) exitWith { + + if (_knockout) exitWith + { _unit setVariable ["incapacitated", true, true]; // for canFight tests - //Make sure to pass group lead if unit is the leader + // Pass group lead if unit is the leader if (_unit == leader (group _unit)) then { - private _index = (units (group _unit)) findIf {[_x] call A3A_fnc_canFight}; - if(_index != -1) then - { - (group _unit) selectLeader ((units (group _unit)) select _index); + private _index = (units (group _unit)) findIf {_x call A3A_fnc_canFight}; + if(_index != -1) then { + group _unit selectLeader ((units group _unit) select _index); }; }; + + if (_realSide == Occupants || _realSide == Invaders) then { + [_unit, group _unit, _unit getVariable ["ace_medical_lastDamageSource", objNull]] spawn A3A_fnc_AIReactOnKill; + }; }; + // Unit woke up _unit setVariable ["incapacitated", false, true]; if !(_unit getVariable ["ACE_captives_isHandcuffed", false]) then { - [_unit, false] remoteExec ["setCaptive", _unit]; // match vanilla behaviour + _unit setCaptive false; // match vanilla behaviour }; if (isPlayer _unit) exitWith {}; // don't force surrender with players if (_realSide != Occupants && _realSide != Invaders) exitWith {}; - if (unit getVariable ["surrendered", false]) exitWith {}; // don't surrender twice + if (_unit getVariable ["surrendered", false]) exitWith {}; // don't surrender twice // surrender if we don't have a primary weapon - if (primaryWeapon _unit == "") exitWith { - [_unit] remoteExec ["A3A_fnc_surrenderAction", _unit]; // execute where unit is local - }; + if (primaryWeapon _unit == "") exitWith { [_unit] spawn A3A_fnc_surrenderAction }; // find closest fighting unit within 50m private _nearestUnit = objNull; private _minDist = 999; { private _dist = _x distance _unit; - if (side _x != civilian && _x != _unit && _dist < _minDist && {[_x] call A3A_fnc_canFight}) then { + if (side _x != civilian && _x != _unit && _dist < _minDist && {_x call A3A_fnc_canFight}) then { _minDist = _dist; _nearestUnit = _x; }; } forEach (_unit nearEntities ["Man", 50]); - if (side _nearestUnit == teamPlayer) then { - [_unit] remoteExec ["A3A_fnc_surrenderAction", _unit]; - }; + if (side _nearestUnit == teamPlayer) then { [_unit] spawn A3A_fnc_surrenderAction }; }] call CBA_fnc_addEventHandler; diff --git a/A3A/addons/core/functions/init/fn_initClient.sqf b/A3A/addons/core/functions/init/fn_initClient.sqf index 7f226dcc79..2713e593f3 100644 --- a/A3A/addons/core/functions/init/fn_initClient.sqf +++ b/A3A/addons/core/functions/init/fn_initClient.sqf @@ -24,9 +24,11 @@ if (!isServer) then { // Headless clients install some support functions, register with the server and bail out if (!hasInterface) exitWith { - call A3A_fnc_initFuncs; call A3A_fnc_initVar; + call A3A_fnc_initFuncs; call A3A_fnc_loadNavGrid; + waitUntil {(!isNil "serverInitDone")}; + call A3A_fnc_addNodesNearMarkers; // Needs marker lists from server Info_1("Headless client version: %1",QUOTE(VERSION)); [clientOwner] remoteExec ["A3A_fnc_addHC",2]; }; @@ -40,8 +42,8 @@ player setVariable ["canSave", false, true]; if (!isServer) then { waitUntil {!isNil "initParamsDone"}; - call A3A_fnc_initFuncs; call A3A_fnc_initVar; + call A3A_fnc_initFuncs; Info_1("MP client version: %1",QUOTE(VERSION)); } else { @@ -82,6 +84,7 @@ if (isMultiplayer && {playerMarkersEnabled}) then { [player] spawn A3A_fnc_initRevive; // with ACE medical, only used for helmet popping & TK checks [] spawn A3A_fnc_outOfBounds; [] spawn A3A_fnc_darkMapFix; +[] spawn A3A_fnc_clientIdleChecker; if (!A3A_hasACE) then { [] spawn A3A_fnc_tags; @@ -246,7 +249,7 @@ player addEventHandler ["GetInMan", { }; if (!_exit) then { if ((typeOf _veh) in undercoverVehicles) then { - if (!(_veh in reportedVehs)) then { + if !(_veh getVariable ["A3A_reported", false]) then { [] spawn A3A_fnc_goUndercover; }; }; @@ -415,10 +418,9 @@ mapX addAction ["Game Options", { [ "Game Options", "Version: "+ antistasiVersion + - "

Difficulty: "+ ( ["Easy","Normal","Hard"] select ((skillMult-1) min 2) ) + + "

Enemy resource balance: "+ (A3A_enemyBalanceMul toFixed 1) + "x" + "
Unlock Weapon Number: "+ str minWeaps + "
Limited Fast Travel: "+ (["No","Yes"] select limitedFT) + - "
AI Limit: "+ str maxUnits + "
Spawn Distance: "+ str distanceSPWN + "m" + "
Civilian Limit: "+ str civPerc + "
Time since GC: " + ([[serverTime-A3A_lastGarbageCleanTime] call A3A_fnc_secondsToTimeSpan,1,0,false,2,false,true] call A3A_fnc_timeSpan_format) diff --git a/A3A/addons/core/functions/init/fn_initFuncs.sqf b/A3A/addons/core/functions/init/fn_initFuncs.sqf index be51d7e235..50fcb9ed45 100644 --- a/A3A/addons/core/functions/init/fn_initFuncs.sqf +++ b/A3A/addons/core/functions/init/fn_initFuncs.sqf @@ -5,5 +5,6 @@ Info("initFuncs started"); [] call compile preprocessFileLineNumbers QPATHTOFOLDER(Scripts\Init_UPSMON.sqf); boxX call jn_fnc_arsenal_init; +if (A3A_hasACEMedical) then { call A3A_fnc_initACEUnconsciousHandler }; Info("initFuncs completed"); diff --git a/A3A/addons/core/functions/init/fn_initParams.sqf b/A3A/addons/core/functions/init/fn_initParams.sqf index 92ee7445fc..061af9a5b3 100644 --- a/A3A/addons/core/functions/init/fn_initParams.sqf +++ b/A3A/addons/core/functions/init/fn_initParams.sqf @@ -21,6 +21,7 @@ Info("Initializing global params"); // - "server" means that the var won't be broadcast to clients & HCs // - "override" means that the var's value will be overwritten by the default even if it already exists // - "oldsave" means that the var was saved separately with the same name in older versions +// - "div10" means that the value from config parameters will be divided by 10 // default can be either a number or bool. If bool, values from config params will be converted // params.hpp should be updated to match this table @@ -30,13 +31,19 @@ A3A_paramTable = [ ["autoSaveInterval", "autoSaveInterval", [], 3600], ["distanceMission", "mRadius", [], 4000], ["enemyNearDistance", "enemyNearDistanceLimit", [], 300], - ["skillMult", "AISkill", [], 2], ["civTraffic", "civTraffic", [], 2], ["limitedFT", "allowFT", [], true], // backwards naming... - ["napalmEnabled", "napalmEnabled", [], false], ["playerMarkersEnabled", "pMarkers", [], true], - ["allowUnfairSupports", "allowUnfairSupports", [], false], - ["allowFuturisticSupports", "allowFuturisticSupports", [], false], + + ["allowUnfairSupports", "allowUnfairSupports", ["server"], false], + ["allowFuturisticSupports", "allowFuturisticSupports", ["server"], false], + ["A3A_enemybalanceMul", "enemyBalanceMul", ["server", "div10"], 1.0], + ["A3A_enemyAttackMul", "enemyAttackMul", ["server", "div10"], 1.0], + ["A3A_invaderBalanceMul", "invaderBalanceMul", ["server", "div10"], 1.2], + ["A3A_attackMissionDistMul", "attackMissionDistMul", ["server"], 2], + ["A3A_enemySkillMul", "enemySkillMul", [], 2], + ["A3A_rebelSkillMul", "rebelSkillMul", [], 2], + ["napalmEnabled", "napalmEnabled", [], true], ["allowDLCKart", "Kart", ["server"], false], ["allowDLCMark", "Mark", ["server"], false], @@ -97,7 +104,7 @@ A3A_paramTable = [ // Not visible parameters yet, but otherwise handled the same way ["distanceSPWN", "", ["oldsave"], 1000], ["civPerc", "", ["oldsave"], 5], - ["maxUnits", "", ["oldsave"], 140], + ["maxUnits", "", ["oldsave"], 140], // hopefully dead ["minPlayersRequiredForPVP", "", [], 2] // beware of the comma @@ -125,13 +132,13 @@ if (loadLastSave) then Info("No params array found in saved game, treating as legacy save"); // Special case for legacy difficultyX + SP, ugh - private _difficultyX = ["difficultyX"] call A3A_fnc_returnSavedStat; +/* private _difficultyX = ["difficultyX"] call A3A_fnc_returnSavedStat; if (!isMultiplayer && !(isNil "_difficultyX")) then { skillMult = _difficultyX; if (skillMult == 1) then {minWeaps = 15}; if (skillMult == 3) then {minWeaps = 40}; }; - +*/ // Load the other legacy saved params { _x params ["_varName", "_paramName", "_options", "_default"]; @@ -175,8 +182,8 @@ if (isMultiplayer) then { }; if (_val == 9999) exitWith {}; // "Default (xxx)" option, do nothing here - // conversion to bool - if (_default isEqualType true) then { _val = _val isEqualTo 1 }; + if (_default isEqualType true) then { _val = _val isEqualTo 1 }; // conversion to bool + if ("div10" in _options) then { _val = _val / 10 }; missionNamespace setVariable [_varName, _val]; }; if !("server" in _options) then { publicVariable _varName }; diff --git a/A3A/addons/core/functions/init/fn_initServer.sqf b/A3A/addons/core/functions/init/fn_initServer.sqf index ec16926391..dbfe9295f7 100644 --- a/A3A/addons/core/functions/init/fn_initServer.sqf +++ b/A3A/addons/core/functions/init/fn_initServer.sqf @@ -76,20 +76,20 @@ publicVariable "campaignID"; // Now load all other parameters, loading from save if available call A3A_fnc_initParams; -//JNA, JNL and UPSMON. Shouldn't have any Antistasi dependencies except on parameters. -call A3A_fnc_initFuncs; - //Initialise variables needed by the mission. _nul = call A3A_fnc_initVar; call A3A_fnc_logistics_initNodes; +//JNA, JNL and UPSMON. Shouldn't have any Antistasi dependencies except on parameters. +call A3A_fnc_initFuncs; + savingServer = true; #define MODE_ARRAY ["SP","MP"] Info_2("%1 server version: %2", MODE_ARRAY select isMultiplayer, QUOTE(VERSION)); bookedSlots = floor ((memberSlots/100) * (playableSlotsNumber teamPlayer)); publicVariable "bookedSlots"; -if (A3A_hasACEMedical) then { call A3A_fnc_initACEUnconsciousHandler }; -call A3A_fnc_loadNavGrid; call A3A_fnc_initZones; +call A3A_fnc_loadNavGrid; +call A3A_fnc_addNodesNearMarkers; // Needs data from both the above if (gameMode != 1) then { // probably shouldn't be here... Occupants setFriend [Invaders,1]; Invaders setFriend [Occupants,1]; @@ -104,6 +104,7 @@ waitUntil {({(isPlayer _x) and (!isNull _x) and (_x == _x)} count allUnits) == ( [] spawn A3A_fnc_modBlacklist; call A3A_fnc_initGarrisons; +call A3A_fnc_initSupports; if (loadLastSave) then { [] call A3A_fnc_loadServer; @@ -159,6 +160,7 @@ if !(loadLastSave) then { _x call A3A_fnc_unlockEquipment; } foreach FactionGet(reb,"initialRebelEquipment"); Info("Initial arsenal unlocks completed"); + call A3A_fnc_checkRadiosUnlocked; }; call A3A_fnc_generateRebelGear; call A3A_fnc_createPetros; @@ -205,7 +207,6 @@ Info("HQ Placed, continuing init"); distanceXs = [] spawn A3A_fnc_distance; [] spawn A3A_fnc_resourcecheck; [] spawn A3A_fnc_aggressionUpdateLoop; -[] spawn A3A_fnc_initSupportCooldowns; [] execVM QPATHTOFOLDER(Scripts\fn_advancedTowingInit.sqf); savingServer = false; diff --git a/A3A/addons/core/functions/init/fn_initVarServer.sqf b/A3A/addons/core/functions/init/fn_initVarServer.sqf index 57b99e45ae..a3e222b506 100644 --- a/A3A/addons/core/functions/init/fn_initVarServer.sqf +++ b/A3A/addons/core/functions/init/fn_initVarServer.sqf @@ -47,34 +47,18 @@ DECLARE_SERVER_VAR(distanceSPWN2, distanceSPWN*0.5); DECLARE_SERVER_VAR(distanceForAirAttack, 10000); //The furthest distance the AI can attack from using trucks and armour DECLARE_SERVER_VAR(distanceForLandAttack, if (A3A_hasIFA) then {5000} else {3000}); -//Max units we aim to spawn in. It's not very strictly adhered to. +//Max units we aim to spawn in. Still declared in initParams and modifiable in game options, but unused //DECLARE_SERVER_VAR(maxUnits, 140); //Disabled DLC according to server parameters DECLARE_SERVER_VAR(disabledMods, call A3A_fnc_initDisabledMods); -//Legacy tool for scaling AI difficulty. Could use a rewrite. -DECLARE_SERVER_VAR(difficultyCoef, if !(isMultiplayer) then {0} else {floor ((({side group _x == teamPlayer} count (call A3A_fnc_playableUnits)) - ({side group _x != teamPlayer} count (call A3A_fnc_playableUnits))) / 5)}); - +//Legacy tool for scaling AI difficulty. Should die. +DECLARE_SERVER_VAR(difficultyCoef, 0); //Mostly state variables, used by various parts of Antistasi. DECLARE_SERVER_VAR(bigAttackInProgress, false); DECLARE_SERVER_VAR(AAFpatrols,0); -DECLARE_SERVER_VAR(smallCAmrk, []); -DECLARE_SERVER_VAR(smallCApos, []); - -DECLARE_SERVER_VAR(attackPos, []); -DECLARE_SERVER_VAR(attackMrk, []); -DECLARE_SERVER_VAR(airstrike, []); - -//Variables used for the internal support system -DECLARE_SERVER_VAR(occupantsSupports, []); -DECLARE_SERVER_VAR(invadersSupports, []); - -DECLARE_SERVER_VAR(supportTargetsChanging, false); - -DECLARE_SERVER_VAR(occupantsRadioKeys, 0); -DECLARE_SERVER_VAR(invaderRadioKeys, 0); //Vehicles currently in the garage DECLARE_SERVER_VAR(vehInGarage, []); @@ -103,9 +87,7 @@ DECLARE_SERVER_VAR(A3A_taskCount, 0); //List of statics (MGs, AA, etc) that will be saved and loaded. DECLARE_SERVER_VAR(staticsToSave, []); //Whether the players have access to radios. -DECLARE_SERVER_VAR(haveRadio, call A3A_fnc_checkRadiosUnlocked); -//List of vehicles that are reported (I.e - Players can't go undercover in them) -DECLARE_SERVER_VAR(reportedVehs, []); +DECLARE_SERVER_VAR(haveRadio, false); //Currently destroyed buildings. //DECLARE_SERVER_VAR(destroyedBuildings, []); //Initial HR @@ -125,12 +107,40 @@ Info("Setting server only variables"); playerStartingMoney = 100; // should probably be a parameter +// horrible naming prestigeOPFOR = [75, 50] select cadetMode; //Initial % support for NATO on each city prestigeBLUFOR = 0; //Initial % FIA support on each city -// Indicates time in seconds before next counter attack. -attackCountdownOccupants = 600; -attackCountdownInvaders = 600; +// Don't need to be distributed +occupantsRadioKeys = 0; +invaderRadioKeys = 0; + +// Recent casualties/damage taken by enemies, format [X, Y, time * 1000 + value] +A3A_recentDamageOcc = []; +A3A_recentDamageInv = []; + +// Balance params updated by aggressionUpdateLoop +A3A_activePlayerCount = 1; +A3A_balancePlayerScale = 1; // Important due to load/save scaling to 1 playerScale +A3A_balanceVehicleCost = 110; +A3A_balanceResourceRate = A3A_balancePlayerScale * A3A_balanceVehicleCost; + +// Current resources, overwritten by saved game +A3A_resourcesDefenceOcc = A3A_balanceResourceRate * 3; // 30% of max +A3A_resourcesDefenceInv = A3A_balanceResourceRate * A3A_invaderBalanceMul * 6; // 60% of max +A3A_resourcesAttackOcc = -10 * A3A_balanceResourceRate * A3A_enemyattackMul; // ~100 min to attack +A3A_resourcesAttackInv = -10 * A3A_balanceResourceRate * A3A_enemyattackMul * A3A_invaderbalanceMul * 0.5; // ~50 min to attack + +// HQ knowledge values +A3A_curHQInfoOcc = 0; // 0-1 ranges for current HQ +A3A_curHQInfoInv = 0; +A3A_oldHQInfoOcc = []; // arrays of [xpos, ypos, knowledge] +A3A_oldHQInfoInv = []; + +// Used by createAIAction for... something +attackMrk = []; + +// These are silly, should be nil/true and local-defined only cityIsSupportChanging = false; resourcesIsChanging = false; savingServer = false; @@ -356,6 +366,54 @@ private _vehFastRope = ["O_Heli_Light_02_unarmed_F","B_Heli_Transport_01_camo_F" DECLARE_SERVER_VAR(vehFastRope, _vehFastRope); DECLARE_SERVER_VAR(A3A_vehClassToCrew,call A3A_fnc_initVehClassToCrew); + +// Default vehicle resource costs +private _vehicleResourceCosts = createHashMap; + +{ _vehicleResourceCosts set [_x, 20] } forEach FactionGet(all, "vehiclesLightUnarmed") + FactionGet(all, "vehiclesTrucks"); +{ _vehicleResourceCosts set [_x, 50] } forEach FactionGet(all, "vehiclesLightArmed"); +{ _vehicleResourceCosts set [_x, 60] } forEach FactionGet(all, "vehiclesLightAPCs"); +{ _vehicleResourceCosts set [_x, 100] } forEach FactionGet(all, "vehiclesAPCs"); +{ _vehicleResourceCosts set [_x, 150] } forEach FactionGet(all, "vehiclesAA") + FactionGet(all, "vehiclesArtillery") + FactionGet(all, "vehiclesIFVs"); +{ _vehicleResourceCosts set [_x, 230] } forEach FactionGet(all, "vehiclesTanks"); + +{ _vehicleResourceCosts set [_x, 70] } forEach FactionGet(all, "vehiclesHelisLight"); +{ _vehicleResourceCosts set [_x, 100] } forEach FactionGet(all, "vehiclesHelisTransport"); +{ _vehicleResourceCosts set [_x, 130] } forEach FactionGet(all, "vehiclesHelisLightAttack") + FactionGet(all, "vehiclesPlanesTransport"); +{ _vehicleResourceCosts set [_x, 250] } forEach FactionGet(all, "vehiclesPlanesCAS") + FactionGet(all, "vehiclesPlanesAA"); +{ _vehicleResourceCosts set [_x, 250] } forEach FactionGet(all, "vehiclesHelisAttack"); + + +// Threat table +private _groundVehicleThreat = createHashMap; + +{ _groundVehicleThreat set [_x, 40] } forEach FactionGet(all, "staticMG"); +{ _groundVehicleThreat set [_x, 80] } forEach FactionGet(all, "vehiclesLightArmed") + FactionGet(all, "vehiclesLightAPCs"); +{ _groundVehicleThreat set [_x, 80] } forEach FactionGet(all, "staticAA") + FactionGet(all, "staticAT") + FactionGet(all, "staticMortars") + [FactionGet(Reb, "vehicleAT")]; + +{ _groundVehicleThreat set [_x, 120] } forEach FactionGet(all, "vehiclesAPCs"); +{ _groundVehicleThreat set [_x, 200] } forEach FactionGet(all, "vehiclesAA") + FactionGet(all, "vehiclesArtillery") + FactionGet(all, "vehiclesIFVs"); +{ _groundVehicleThreat set [_x, 300] } forEach FactionGet(all, "vehiclesTanks"); + + +// Template overrides +private _overrides = FactionGet(Occ, "attributesVehicles") + FactionGet(Inv, "attributesVehicles"); +{ + private _vehType = _x select 0; + if !(_vehType in _vehicleResourceCosts) then { continue }; + { + if !(_x isEqualType []) then { continue }; // first entry is classname + _x params ["_attr", "_val"]; + call { + if (_attr == "threat") then { _groundVehicleThreat set [_vehType, _val] }; + if (_attr == "cost") exitWith { _vehicleResourceCosts set [_vehType, _val] }; + }; + } forEach _x; +} forEach _overrides; + +DECLARE_SERVER_VAR(A3A_vehicleResourceCosts, _vehicleResourceCosts); +DECLARE_SERVER_VAR(A3A_groundVehicleThreat, _groundVehicleThreat); + /////////////////////////// // MOD TEMPLATES /// /////////////////////////// @@ -387,29 +445,6 @@ Info("Creating pricelist"); {server setVariable [_x,100,true]} forEach [FactionGet(reb,"unitMedic"), FactionGet(reb,"unitExp"), FactionGet(reb,"unitEng")]; {server setVariable [_x,150,true]} forEach [FactionGet(reb,"unitSL"), FactionGet(reb,"unitSniper")]; -{timer setVariable [_x,3,true]} forEach (FactionGet(occ,"staticAT") + FactionGet(occ,"staticAA")); -{timer setVariable [_x,6,true]} forEach (FactionGet(inv,"staticAT") + FactionGet(inv,"staticAA")); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesAPCs"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesAPCs"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesTanks"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesTanks"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesAA"); -{timer setVariable [_x,3,true]} forEach FactionGet(inv,"vehiclesAA"); -{timer setVariable [_x,3,true]} forEach FactionGet(occ,"vehiclesGunBoats"); -{timer setVariable [_x,3,true]} forEach FactionGet(inv,"vehiclesGunBoats"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesPlanesCAS"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesPlanesCAS"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesPlanesAA"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesPlanesAA"); -{timer setVariable [_x,1,true]} forEach FactionGet(occ,"vehiclesPlanesTransport"); -{timer setVariable [_x,1,true]} forEach FactionGet(occ,"vehiclesHelisTransport"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesPlanesTransport"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesHelisTransport"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ,"vehiclesHelisAttack"); -{timer setVariable [_x,10,true]} forEach FactionGet(inv,"vehiclesHelisAttack"); -{timer setVariable [_x,0,true]} forEach FactionGet(occ, "vehiclesArtillery"); -{timer setVariable [_x,5,true]} forEach FactionGet(inv, "vehiclesArtillery"); - server setVariable [FactionGet(reb,"vehicleCivCar"),200,true]; server setVariable [FactionGet(reb,"vehicleCivTruck"),600,true]; if (FactionGet(reb,"vehicleCivHeli") isNotEqualTo "") then { diff --git a/A3A/addons/core/functions/init/fn_prepareMarkerArrays.sqf b/A3A/addons/core/functions/init/fn_prepareMarkerArrays.sqf index e2d65bd118..359a78dbd4 100644 --- a/A3A/addons/core/functions/init/fn_prepareMarkerArrays.sqf +++ b/A3A/addons/core/functions/init/fn_prepareMarkerArrays.sqf @@ -103,9 +103,18 @@ fnc_sortPlacementMarker = //DebugArray("Marker setup done, placement marker are", _placementMarker); { - [_x select 0, _x select 1] spawn A3A_fnc_initSpawnPlaces; + [_x select 0, _x select 1] call A3A_fnc_initSpawnPlaces; } forEach _placementMarker; +// Autogenerate stuff like helipad placements for markers that don't have any defined spawn places +{ + private _spawnStr = format ["%1_spawns", _x]; + if (isNil { spawner getVariable _spawnStr }) then { + Debug_1("Generating additional spawn places for %1", _x); + [_x, []] call A3A_fnc_initSpawnPlaces; + }; +} forEach (airportsX + resourcesX + factories + outposts + seaports); + //TEMPORARY FIX TO DETECT SPAWN MARKERS { _nearestMarker = [spawnPoints, getMarkerPos _x] call BIS_fnc_nearestPosition; diff --git a/A3A/addons/core/functions/init/fn_resourcecheck.sqf b/A3A/addons/core/functions/init/fn_resourcecheck.sqf index eb6e023db4..073b4f5b4a 100644 --- a/A3A/addons/core/functions/init/fn_resourcecheck.sqf +++ b/A3A/addons/core/functions/init/fn_resourcecheck.sqf @@ -6,10 +6,11 @@ if (!isServer) exitWith { while {true} do { + // what's wrong with sleep 600, really? //sleep 600;//600 nextTick = time + 600; waitUntil {sleep 15; time >= nextTick}; - if (isMultiplayer) then {waitUntil {sleep 10; isPlayer theBoss}}; + waitUntil {sleep 10; A3A_activePlayerCount > 0}; private _resAdd = 25;//0 private _hrAdd = 0;//0 @@ -67,14 +68,6 @@ while {true} do garrison setVariable [_city,[],true]; sleep 5; {_nul = [_city,_x] spawn A3A_fnc_deleteControls} forEach controlsX; - if (!("CONVOY" in A3A_activeTasks) and (!bigAttackInProgress)) then - { - _base = [_city] call A3A_fnc_findBasesForConvoy; - if (_base != "") then - { - [[_city,_base],"A3A_fnc_convoy"] call A3A_fnc_scheduler; - }; - }; [] call A3A_fnc_tierCheck; }; if ((_supportGov > _supportReb) and (sidesX getVariable [_city,sideUnknown] == teamPlayer)) then @@ -116,18 +109,28 @@ while {true} do [] call A3A_fnc_generateRebelGear; [] call A3A_fnc_FIAradio; - [] call A3A_fnc_economicsAI; [] call A3A_fnc_cleanConvoyMarker; + // Random-walk the defence multipliers for markers to add some persistent variation + // Maybe add some logic to this later +/* { + private _r = _x#4 - 0.1 + random 0.2; + _x set [4, 0.5 max _r min 1.0]; + } forEach A3A_supportMarkerTypes; +*/ if (isMultiplayer) then { [] spawn A3A_fnc_promotePlayer; [] call A3A_fnc_assignBossIfNone; - difficultyCoef = floor ((({side group _x == teamPlayer} count (call A3A_fnc_playableUnits)) - ({side group _x != teamPlayer} count (call A3A_fnc_playableUnits))) / 5); - publicVariable "difficultyCoef"; }; - private _missionChance = 5 * count (allPlayers - (entities "HeadlessClient_F")); + // Decrease HQ knowledge values, old ones faster than current + if (A3A_curHQInfoOcc < 1) then { A3A_curHQInfoOcc = 0 max (A3A_curHQInfoOcc - 0.01) }; + if (A3A_curHQInfoInv < 1) then { A3A_curHQInfoInv = 0 max (A3A_curHQInfoInv - 0.01) }; + A3A_oldHQInfoOcc = A3A_oldHQInfoOcc select { _x set [2, _x#2 - 0.1]; _x#2 > 0 }; // arrays of [xpos, ypos, knowledge] + A3A_oldHQInfoInv = A3A_oldHQInfoInv select { _x set [2, _x#2 - 0.1]; _x#2 > 0 }; + + private _missionChance = 5 * A3A_activePlayerCount; if ((!bigAttackInProgress) and (random 100 < _missionChance)) then {[] spawn A3A_fnc_missionRequest}; //Removed from scheduler for now, as it errors on Headless Clients. //[[],"A3A_fnc_reinforcementsAI"] call A3A_fnc_scheduler; diff --git a/A3A/addons/maps/MissionDescription/params.hpp b/A3A/addons/maps/MissionDescription/params.hpp index 861898a27d..184073ca4e 100644 --- a/A3A/addons/maps/MissionDescription/params.hpp +++ b/A3A/addons/maps/MissionDescription/params.hpp @@ -109,13 +109,6 @@ class Params texts[] = {"Load from save (Default: 300)", "100", "200", "300", "400", "500"}; default = 9999; }; - class AISkill - { - title = "Mission Difficulty"; - values[] = {9999,1,2,3}; - texts[] = {"Load from save (Default: Normal)","Easy","Normal","Hard"}; - default = 9999; - }; class unlockItem { title = "Number of the same item required to unlock"; @@ -158,13 +151,6 @@ class Params texts[] = {"Load from save (Default: Airports & HQ)","Any friendly position","Only Airports & HQ"}; default = 9999; }; - class napalmEnabled - { - title = "Enable Napalm Bombing for AI"; - values[] = {9999,0,1}; - texts[] = {"Load from save (Default: No)","No","Yes"}; - default = 9999; - }; class unlockedUnlimitedAmmo { title = "Do Unlocked Weapons Automatically Unlock Their Standard Magazine?"; @@ -228,6 +214,83 @@ class Params texts[] = {"Load from save (Default: Disabled)", "Disabled", "Enabled"}; default = 9999; }; + class SpacerBalance + { + title = ""; + values[] = {""}; + texts[] = {""}; + default = ""; + }; + class BalanceOptions + { + title = "BALANCE OPTIONS"; + values[] = {""}; + texts[] = {""}; + default = ""; + }; + class enemyBalanceMul + { + title = "Overall enemy resource balance"; + values[] = {9999,3,5,7,10,14,20,28}; + texts[] = {"Load from save (Default: Normal)","Trivial","Very Easy","Easy","Normal","Hard","Very Hard","Extreme"}; + default = 9999; + }; + class enemyAttackMul + { + title = "Enemy attack resource balance (relative to overall balance)"; + values[] = {9999,3,5,7,10,14,20,28}; + texts[] = {"Load from save (Default: Normal)","Trivial","Very Easy","Easy","Normal","Hard","Very Hard","Extreme"}; + default = 9999; + }; + class invaderBalanceMul + { + title = "Resource multiplier for invaders relative to occupants"; + values[] = {9999,10,11,12,13,14,15}; + texts[] = {"Load from save (Default: 1.2x)","1.0x","1.1x","1.2x","1.3x","1.4x","1.5x"}; + default = 9999; + }; + class attackMissionDistMul + { + title = "Enemy preference for attacking rebel targets within mission distance"; + values[] = {9999,1,2,3,5}; + texts[] = {"Load from save (Default: 2x)","No change","2x","3x","5x"}; + default = 9999; + }; + class enemySkillMul + { + title = "Enemy AI skill (also affected by server skill)"; + values[] = {9999,0,1,2,3,4}; + texts[] = {"Load from save (Default: Normal)","Very low","Low","Normal","High","Very high"}; + default = 9999; + }; + class rebelSkillMul + { + title = "Friendly AI skill (also affected by server skill)"; + values[] = {9999,0,1,2,3,4}; + texts[] = {"Load from save (Default: Normal)","Very low","Low","Normal","High","Very high"}; + default = 9999; + }; + class napalmEnabled + { + title = "Enable Napalm Bombing for AI"; + values[] = {9999,0,1}; + texts[] = {"Load from save (Default: Yes)","No","Yes"}; + default = 9999; + }; + class allowUnfairSupports + { + title = "Allow unfair supports to be used by the enemy"; + values[] = {9999, 0, 1}; + texts[] = {"Load from save (Default: Not Allowed)", "Not allowed", "Allowed"}; + default = 9999; + }; + class allowFuturisticSupports + { + title = "[Experimental - Use at own risk](Requires unfair supports) Allow futuristic supports to be used by the enemy"; + values[] = {9999, 0, 1}; + texts[] = {"Load from save (Default: Not Allowed)", "Not allowed", "Allowed"}; + default = 9999; + }; class Spacer11 { title = ""; @@ -354,27 +417,13 @@ class Params texts[] = {"Load from save (Default: No)", "No", "Yes"}; default = 9999; }; - class SupportOptions + class SpacerCrate { - title = "SUPPORT OPTIONS"; + title = ""; values[] = {""}; texts[] = {""}; default = ""; }; - class allowUnfairSupports - { - title = "[Experimental - Use at own risk] Allow unfair supports to be used by the enemy"; - values[] = {9999, 0, 1}; - texts[] = {"Load from save (Default: Not Allowed)", "Not allowed", "Allowed"}; - default = 9999; - }; - class allowFuturisticSupports - { - title = "[Experimental - Use at own risk](Requires unfair supports) Allow futuristic supports to be used by the enemy"; - values[] = {9999, 0, 1}; - texts[] = {"Load from save (Default: Not Allowed)", "Not allowed", "Allowed"}; - default = 9999; - }; class CrateOptions { title = "LOOT CRATE OPTIONS";