diff --git a/Missionname.MapName/VEMFr_client/gui/RscDisplayVEMFrClient.hpp b/Missionname.MapName/VEMFr_client/gui/RscDisplayVEMFrClient.hpp new file mode 100644 index 0000000..3460117 --- /dev/null +++ b/Missionname.MapName/VEMFr_client/gui/RscDisplayVEMFrClient.hpp @@ -0,0 +1,128 @@ +class RscDisplayVEMFrClient +{ + idd = 2991; + fadeIn = 0.2; + fadeOut = 1; + duration = 99999; + onLoad = "uiNamespace setVariable ['RscDisplayVEMFrClient', _this select 0]; ExecVM 'VEMFr_client\sqf\onLoad.sqf'"; + onUnLoad = "uiNamespace setVariable ['RscDisplayVEMFrClient', displayNull]"; + movingEnable = 0; + class RscBackground + { + access = 0; + colorBackground[] = {0.48,0.5,0.35,1}; + colorShadow[] = {0,0,0,0.5}; + colorText[] = {0.1,0.1,0.1,1}; + deletable = 0; + fade = 0; + fixedWidth = 0; + font = "PuristaLight"; + h = 1; + idc = -1; + linespacing = 1; + shadow = 0; + SizeEx = 1; + style = 512; + text = ""; + tooltipColorBox[] = {1,1,1,1}; + tooltipColorShade[] = {0,0,0,0.65}; + tooltipColorText[] = {1,1,1,1}; + type = 0; + w = 1; + x = 0; + y = 0; + }; + class RscPictureKeepAspect + { + access = 0; + colorBackground[] = {0,0,0,1}; + colorText[] = {1,1,1,1}; + deletable = 0; + fade = 0; + fixedWidth = 0; + font = "PuristaMedium"; + h = 0.15; + idc = -1; + lineSpacing = 0; + shadow = 0; + sizeEx = 0; + style = "0x30 + 0x800"; + text = ""; + tooltipColorBox[] = {1,1,1,1}; + tooltipColorShade[] = {0,0,0,0.65}; + tooltipColorText[] = {1,1,1,1}; + type = 0; + w = 0.2; + x = 0; + y = 0; + }; + class RscText + { + access = 0; + colorBackground[] = {0.071,0.078,0.094,1}; + colorShadow[] = {0,0,0,0.5}; + colorText[] = {0.22,0.745,0.882,1}; + deletable = 0; + fade = 0; + fixedWidth = 0; + font = "PuristaMedium"; + h = 0.037; + idc = -1; + linespacing = 1; + shadow = 1; + sizeEx = "( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + style = 0; + text = ""; + tooltipColorBox[] = {1,1,1,1}; + tooltipColorShade[] = {0,0,0,0.65}; + tooltipColorText[] = {1,1,1,1}; + type = 0; + w = 0.3; + x = 0; + y = 0; + }; + class controls + { + class icon:RscPictureKeepAspect + { + x = 0.25 * safezoneW + safezoneX; + y = 0.825 * safezoneH + safezoneY; + w = 0.025 * safezoneW; + h = 0.05 * safezoneH; + + fade = 1; + idc = 10; + text = "\A3\ui_f\data\map\markers\nato\o_unknown.paa"; + }; + class txtTitle: RscText + { + x = 0.285 * safezoneW + safezoneX; + y = 0.825 * safezoneH + safezoneY; + w = 0 * safezoneW; + h = 0.02 * safezoneH; + + colorBackground[] = {1,1,1,0.7}; + colorText[] = {0,0,0,1}; + fade = 1; + idc = 11; + shadow = 0; + sizeEx = "( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.85)"; + text = ""; + }; + class txtMsg: RscText + { + x = 0.285 * safezoneW + safezoneX; + y = 0.845 * safezoneH + safezoneY; + w = 0 * safezoneW; + h = 0.03 * safezoneH; + + colorBackground[] = {1,1,1,0.7}; + colorText[] = {0,0,0,1}; + fade = 1; + idc = 12; + shadow = 0; + sizeEx = "( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1.25)"; + text = ""; + }; + }; +}; diff --git a/Missionname.MapName/VEMFr_client/sqf/initClient.sqf b/Missionname.MapName/VEMFr_client/sqf/initClient.sqf new file mode 100644 index 0000000..9e51410 --- /dev/null +++ b/Missionname.MapName/VEMFr_client/sqf/initClient.sqf @@ -0,0 +1,45 @@ +if hasInterface then + { + uiNamespace setVariable ["VEMFrMsgQueue", []]; + uiNamespace setVariable ["RscDisplayVEMFrClient", displayNull]; + // custom addPublicVariableEventHandler. Those bloody BE filters..... + if isMultiplayer then + { + _handleMessage = + { + _data = _this; + _msg = param [0, "", [[],format[""]]]; + _mode = param [1, "", ["", -1]]; + if (_mode isEqualTo "sys") then + { + systemChat _msg; + } else + { + (uiNamespace getVariable ["VEMFrMsgQueue", []]) pushBack _msg; + if isNull(uiNamespace getVariable ["RscDisplayVEMFrClient", displayNull]) then + { + (["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutRsc["RscDisplayVEMFrClient", "PLAIN", 0, true] + }; + }; + }; + while {true} do + { + if not isNil"VEMFrMsgToClient" then + { + VEMFrMsgToClient spawn _handleMessage; + VEMFrMsgToClient = nil; + } else + { + uiSleep 0.05; + }; + }; + } else + { + _arr = uiNamespace getVariable ["VEMFrMsgQueue",[]]; + _arr pushBack [0,"NEW TAKEOVER","Raiders have taken over ..."]; + _arr pushBack [1,"NEW POLICE RAID", format["%1 Police forces are raiding ...", worldName]]; + _arr pushBack [2,"NEW S.W.A.T. RAID", format["%1's S.W.A.T. teams are raiding ...", worldName]]; + waitUntil { if not(isNull(findDisplay 46)) then {true} else {uiSleep 0.5; false} }; + player addAction ["Trigger VEMFr Message",{(["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutRsc["RscDisplayVEMFrClient", "PLAIN", 0, true]},"",-1,false,true,"User2","alive player"]; + }; + }; diff --git a/Missionname.MapName/VEMFr_client/sqf/onLoad.sqf b/Missionname.MapName/VEMFr_client/sqf/onLoad.sqf new file mode 100644 index 0000000..def44a8 --- /dev/null +++ b/Missionname.MapName/VEMFr_client/sqf/onLoad.sqf @@ -0,0 +1,110 @@ +disableSerialization; +_dsp = uiNamespace getVariable ["RscDisplayVEMFrClient", displayNull]; +if not isNull _dsp then + { + if (count (uiNamespace getVariable ["VEMFrMsgQueue", []]) isEqualTo 0) then + { + (["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutFadeOut 0; + systemChat "[VEMFrClient] No messages to display"; + } else + { + playSound "HintExpand"; + // do stuff + _ctrlPic = _dsp displayCtrl 10; + _ctrlTitle = _dsp displayCtrl 11; + _ctrlMsg = _dsp displayCtrl 12; + { + [_dsp, _x] spawn + { + disableSerialization; + _dsp = _this select 0; + _data = _this select 1; + _ctrlPic = _dsp displayCtrl 10; + if (ctrlFade _ctrlPic < 1) then + { + _ctrlPic ctrlSetFade 1; + _ctrlPic ctrlCommit 0.5; + uiSleep 0.75; + }; + _ctrlPic ctrlSetTextColor call + { + private ["_return"]; + if (_data select 0 isEqualTo 0) then + { + _return = [0.5,0,0,1]; + }; + if (_data select 0 isEqualTo 1) then + { + _return = [0,0.3,0.6,1]; + }; + if (_data select 0 isEqualTo 2) then + { + _return = [0,0,0,1]; + }; + if isNil"_return" then + { + _return = [1,1,1,1]; + }; + _return + }; + _ctrlPic ctrlSetFade 0; + _ctrlPic ctrlCommit 0.5; + }; + + if (_ctrlTitle getVariable ["expanded",false] AND _ctrlMsg getVariable ["expanded", false]) then + { + _ctrlPos = ctrlPosition _ctrlTitle; + _ctrlTitle ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0 * safezoneW, _ctrlPos select 3]; + _ctrlTitle ctrlSetFade 1; + _ctrlTitle ctrlCommit 0.5; + _ctrlTitle setVariable ["expanded", false]; + uiSleep 0.75; + _ctrlTitle ctrlSetText toUpper (_x select 1); + _ctrlPos = ctrlPosition _ctrlTitle; + _ctrlTitle ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0.1 * safezoneW, _ctrlPos select 3]; + _ctrlTitle ctrlSetFade 0; + _ctrlTitle ctrlCommit 0.5; + _ctrlTitle setVariable ["expanded", true]; + + _ctrlPos = ctrlPosition _ctrlMsg; + _ctrlMsg ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0 * safezoneW, _ctrlPos select 3]; + _ctrlMsg ctrlSetFade 1; + _ctrlMsg ctrlCommit 0.5; + _ctrlMsg setVariable ["expanded", false]; + uiSleep 0.75; + _ctrlMsg ctrlSetText (_x select 2); + _ctrlPos = ctrlPosition _ctrlMsg; + _ctrlMsg ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0.45 * safezoneW, _ctrlPos select 3]; + _ctrlMsg ctrlSetFade 0; + _ctrlMsg ctrlCommit 0.5; + _ctrlMsg setVariable ["expanded", true]; + + uiSleep (count (_x select 2) / 5); + } else + { + _ctrlTitle ctrlSetText toUpper (_x select 1); + _ctrlPos = ctrlPosition _ctrlTitle; + _ctrlTitle ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0.1 * safezoneW, _ctrlPos select 3]; + _ctrlTitle ctrlSetFade 0; + _ctrlTitle ctrlCommit 0.5; + _ctrlTitle setVariable ["expanded", true]; + + _ctrlMsg ctrlSetText (_x select 2); + _ctrlPos = ctrlPosition _ctrlMsg; + _ctrlMsg ctrlSetPosition [_ctrlPos select 0, _ctrlPos select 1, 0.45 * safezoneW, _ctrlPos select 3]; + _ctrlMsg ctrlSetFade 0; + _ctrlMsg ctrlCommit 0.5; + _ctrlMsg setVariable ["expanded", true]; + + uiSleep (count (_x select 2) / 5); + }; + } forEach (uiNamespace getVariable ["VEMFrMsgQueue",[]]); + uiNamespace setVariable ["VEMFrMsgQueue", []]; + (["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutFadeOut 0.5; + }; + } else + { + systemChat "Nope."; + }; + +//(uiNamespace getVariable ["VEMFrMsgQueue", []]) pushBack ["title","message"]; diff --git a/Missionname.MapName/description.ext b/Missionname.MapName/description.ext new file mode 100644 index 0000000..bea5e25 --- /dev/null +++ b/Missionname.MapName/description.ext @@ -0,0 +1,4 @@ +class RscTitles +{ + #include "VEMFr_client\gui\RscDisplayVEMFrClient.hpp" +}; diff --git a/Missionname.MapName/init.sqf b/Missionname.MapName/init.sqf new file mode 100644 index 0000000..f8cd472 --- /dev/null +++ b/Missionname.MapName/init.sqf @@ -0,0 +1,5 @@ +// Put this somewhere in your own init.sqf outside of any other brackets and if statements +if hasInterface then +{ + [] ExecVM "VEMFr_client\sqf\initClient.sqf"; // Client-side part of VEMFr +}; diff --git a/a3_vemf_reloaded.7z b/a3_vemf_reloaded.7z new file mode 100644 index 0000000..bb89450 Binary files /dev/null and b/a3_vemf_reloaded.7z differ diff --git a/a3_vemf_reloaded/config.cpp b/a3_vemf_reloaded/config.cpp new file mode 100644 index 0000000..533ea57 --- /dev/null +++ b/a3_vemf_reloaded/config.cpp @@ -0,0 +1,400 @@ +/* + Author: IT07 + + Description: + cpp config file for a3_vemf_reloaded + + What is a3_vemf_reloaded? (short: VEMFr) + It is a complete rebuild/remake of VEMF (for Epoch) made by TheVampire. + a3_vemf_reloaded was originally called VEMF but because the original creator (TheVampire) wanted to continue his work on VEMF, + this remade version of VEMF had its name changed into a3_vemf_reloaded. +*/ + +/////////////// +/// NOTE: settings that are set to 0 means they are DISABLED | settings set to 1 (or higher) are either enabled or have a specific function +/////////////// + +class CfgVemfReloaded +{ + /////// Debugging/learning/logging /////// + debugMode = 3; // 0 = no debugging | 1 = ERRORS only | 2 = INFO only | 3 = ERRORS & INFO + overridesToRPT = 1; // Enable/disable logging of override settings to .RPT + /////////////////////////////////////// + + // Global settings + addons[] = {}; // Not used for now + allowTWS = 0; // Enable/disable the usage of TWS scopes by AI + headLessClientSupport = 0; + headLessClientNames[] = {"HC1"}; + housesBlackList[] = {"Land_Pier_F"}; + killPercentage = 100; // How much of total AI has to be killed for mission completion (in percentage) + logCowardKills = 1; // Enable/disable logging of who killed AI whilst it was parachuting down + maxGlobalMissions = 10; // Enable/disable global mission amount limit + maxNew = 2; // Enable/disable MAXIMUM time (in minutes) before new mission can run + minNew = 1; // Enable/disable MINIMUM time (in minutes) before new mission can run + minPlayers = 1; // Enable/disable minimal required player count for (new) missions to (start) spawn(ing) + minServerFPS = 20; // Enable/disable minimum server FPS for VEMF to keep spawning missions + missionDistance = 2000; // Enable/disable minimum distance between missions + missionList[] = {"DynamicLocationInvasion","BaseAttack"}; // Each entry should represent an .sqf file in the missions folder + noMissionPos[] = {{{2998.62,18175.4,0.00143886},500},{{14601.3,16799.3,0.00143814},800},{{23334.8,24189.5,0.00132132},600}}; // Format: {{position},radius} | Default: Exile Altis safezones + nonPopulated = 1; // Enable/disable allowance of missions at locations WITHOUT (enterable) buildings + punishRoadKills = 1; // Enable/disable respect deduction if player roadkills AI + removeAllAssignedItems = 0; // Enable/disable removal of Map, Compass, Watch and Radio from all AI + sayKilled = 1; // Enable/disable AI kill messages + sayKilledName = 0; // Enable/disable the usage of AI's names instead of just "AI" + timeOutTime = 25; // Enable/disable mission timeOutTime (in minutes) + validateLoot = 1; // Enable/disable validation of all defined loot classnames. Checks if classnames exist in server's game configFile + + class Exile // Exile specific settings + { + aiMode = 1; // 0 = normal soldier AI | 1 = regular police AI | 2 = S.W.A.T. AI + respectReward = 20; // 0 = no respect for killing AI | respectReward > 0 = amount of minimum respect reward for player + respectRoadKillDeduct = 20; // 0 = no deduction for roadkilling AI | respectRoadKillDeduct > 0 = amount of respect to take from player; + // AI Unit settings + unitClass = "O_G_Sharpshooter_F"; // Default: "O_G_Sharpshooter_F" | optional: "B_G_Soldier_AR_F" + // NOTE: VEMFr will automatically adjust to the AI's side that belongs to the unit of given unitClass + }; + + class Epoch // Epoch specific settings + { + aiMode = 0; // 0 = normal soldier AI | 1 = regular police AI + cryptoReward = 5; // Minimal crypto gain. VEMFr dynamically adds more depending on shooting skills + cryptoRoadKillPunish = 20; // 0 = no punishment for road-killing AI | energyRoadKillPunish > 0 = amount of energy to take from player + unitClass = "I_G_Soldier_lite_F"; // Default: "I_G_Soldier_lite_F" + // NOTE: VEMFr will automatically adjust to the AI's side that belongs to the unit of given unitClass + }; + + + class locationBlackLists + { + // NOTE 1: If the map you use is not listed below, simply add it by yourself or put the locations you want to blacklist into the locations array of the Other class + // NOTE 2: If not sure about capital letters, just type all names in lowercase + class Altis + { + locations[] = {"almyra","atsalis","cap makrinos","chelonisi","fournos","kavala","makrynisi","monisi","polemista","pyrgos","pyrgi","sagonisi","savri","selakano","sofia","surf club","syrta","zaros"}; + }; + class Stratis + { + locations[] = {"jay cove","kamino bay","keiros bay","kyfi bay","limeri bay","marina bay","nisi bay","strogos bay","tsoukala bay"}; + }; + class Namalsk + { + locations[] = {"brensk bay","lubjansk bay","nemsk bay","seraja bay","sebjan mine","tara strait"}; + }; + class Other + { + locations[] = {}; + }; + class Tanoa + { + locations[] = {"banana plantations","forest clearing","ferry","galili","roadhouse"}; + }; + }; + + class BaseAttack + { // BaseAttack (mission) settings + aiMode = 1; // 0 = "military" | 1 = Police | 2 = S.W.A.T. (NOT AVAILABLE ON EPOCH) + aiSetup[] = {2,5}; // format: {amountOfGroups,unitsInEachGroup}; + allowLaunchers = 1; // Allow/disallow AI to have rocket launchers + hasLauncherChance = 25; // In percentage. How big the chance that each AI gets a launcher + maxAttacks = 5; // Maximum amount of active attacks at the same time | can not be turned off + minimumLevel = 2; // Minimum required level of base before it can get attacked + /* + NOTES: + 1) every territory flag can only be attacked once every restart + 2) only players within a certain range of the attacked territory can see the mission announcement + 3) as a "punishment" for killing AI, players do NOT get any respect increase/decrease for killing AI + */ + }; + + class DynamicLocationInvasion + { // DynamicLocationInvasion (mission) settings + allowCrateLift = 0; // Allow/disallow the loot crate to be lifted with helicopter + allowLaunchers = 1; // Allow/disallow AI to have rocket launchers + allowRepeat = 0; // Allow/disallow re-invading of a previously invaded city/town/location + announce = 1; // Enable/disable mission notificatons + cal50s = 3; // Max amount of .50 caliber machineguns at mission | Needs to be lower than total unit count per mission + cal50sDelete = 1; // Enable/disable the removal of .50cal | 2 = destroy (not remove) + class crateParachute + { + enabled = 0; // Enable/disable parachute of the loot crate + altitude = 250; // loot crate spawn-altitude in meters + }; + crateTypes[] = {"I_CargoNet_01_ammo_F","O_CargoNet_01_ammo_F","B_CargoNet_01_ammo_F","I_supplyCrate_F","Box_East_AmmoVeh_F","Box_NATO_AmmoVeh_F"}; + flairTypes[] = {"Chemlight_green","Chemlight_red","Chemlight_yellow","Chemlight_blue"}; + groupCount[] = {2,4}; // In format: {minimum, maximum}; VEMF will pick a random number between min and max. If you want the same amount always, use same numbers for minimum and maximum. + groupUnits[] = {4,6}; // How much units in each group. Works the same like groupCount + hasLauncherChance = 25; // In percentage. How big the chance that each AI gets a launcher + class heliPatrol + { + enabled = 1; + classes[] = {"B_Heli_Light_01_armed_F","B_Heli_Attack_01_F","B_Heli_Transport_03_F","B_Heli_Transport_01_F","B_Heli_Transport_01_camo_F"}; // the types of heli(s) + locked = 0; // Enable/disable heli lock to prevent/allow players from flying it + }; + useMarker = 1; // Enable/disable mission markers + markCrateOnMap = 1; // Enable/disable loot crate marker on map called "Loot" + markCrateVisual = 1; // Enable/disable loot crate VISUAL marker (smoke and/or chem) + /* maxDistance NOTE: make sure to keep this number very high. 15000 is for Altis */ + maxDistancePrefered = 7000; // Prefered maximum mission distance from player + maxInvasions = 7; // Max amount of active uncompleted invasions allowed at the same time + mines = 0; // Enable/disable mines at mission | 1 = anti-Armor mines | 2 = anti-Personell mines | 3 = both anti-Armor and anti-Personell mines + minesAmount = 20; // Ignore if mines = 0; + minesCleanup = 1; // Enable/disable the removal of mines once mission has been completed | 2 = explode mines + nonPopulated = -1; // Allow/disallow this mission type being placed at locations without buildings | using -1 will ignore this setting and use the global settting + randomModes = 1; // Enable/disable randomization of AI types (linked to aiMode setting) + skipDistance = 800; // No missions at locations which have players within this range (in meters) + skipDistanceReversed = 0; // If set higher than 0, missions will only spawn if player is at least given amount (in meters) away from a location whilst at the same time not be further away than twice the given number (in meters) + smokeTypes[] = {"SmokeShell","SmokeShellBlue","SmokeShellGreen","SmokeShellOrange","SmokeShellRed","SmokeShellYellow"}; + spawnCrateFirst = 0; // Enable/disable the spawning of loot crate before mission has been completed + streetLights = 0; // Enable/disable street lights at mission location + streetLightsRestore = 1; // Enable/disable restoration of street lights after mission completion + streetLightsRange = 500; // Affects streetlights within this distance from mission's center + }; + + class aiStatic + { // Simply spawns units at desired positions + amount[] = {10,20,12,11,40,21,19}; // How much AI units on each seperate position. Example: 1st location, 10. 2nd location, 20. 3rd location, 12. And so on.... + enabled = 0; // Enable/disable static AI spawning + positions[] = {}; // Add positions here. Each position must have {} around it and must be seperated with a comma if multiple positions present. Last position in list should NOT have a comma behind it! + random = 1; // Enable/disable randomization of AI units amount + }; + + class aiCleanUp + { // Contains settings for removal of items from each AI that gets eliminated + aiDeathRemovalEffect = 0; // Enable/disable the "death effect" from Virtual Arsenal. Flashes AI and deletes it after being eliminated + removeHeadGear = 0; // Enable/disable removal of headgear after AI has been eliminated, obviously + removeLaunchers = 0; // Enable/disable removal of rocket launchers from AI after they are eliminated + }; + + + class aiSkill // Minimum: 0 | Maximum: 1 + { // Global AI skill settings. They affect each VEMF unit for any default VEMF mission + difficulty = "Veteran"; // Options: "Easy" "Normal" "Veteran" "Hardcore" | Default: Veteran + class Easy // AI looks stupid with this setting xD + { + accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.85; courage = 1; reloadSpeed = 0.3; commanding = 1; general = 0.3; + }; + class Normal + { + accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.85; courage = 1; reloadSpeed = 0.3; commanding = 1; general = 0.4; + }; + class Veteran + { + accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.85; courage = 1; reloadSpeed = 0.3; commanding = 1; general = 0.5; + }; + class Hardcore // Also known as Aimbots + { + accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.85; courage = 1; reloadSpeed = 0.3; commanding = 1; general = 0.7; + }; + }; + + class policeConfig + { + backpacks[] = { + "B_AssaultPack_khk","B_AssaultPack_dgtl","B_AssaultPack_rgr","B_AssaultPack_sgg","B_AssaultPack_cbr", + "B_AssaultPack_mcamo","B_TacticalPack_rgr","B_TacticalPack_mcamo","B_TacticalPack_ocamo","B_TacticalPack_blk", + "B_TacticalPack_oli","B_FieldPack_khk","B_FieldPack_ocamo","B_FieldPack_oucamo","B_FieldPack_cbr", + "B_FieldPack_blk","B_Carryall_ocamo","B_Carryall_oucamo","B_Carryall_mcamo","B_Carryall_khk","B_Carryall_cbr", + "B_Parachute","B_FieldPack_oli","B_Carryall_oli","B_Kitbag_Base","B_Kitbag_cbr","B_Kitbag_mcamo", + "B_Kitbag_rgr","B_Kitbag_sgg","B_OutdoorPack_Base","B_OutdoorPack_blk","B_OutdoorPack_blu", + "B_OutdoorPack_tan" + }; + headGear[] = { + "H_Cap_police","H_Beret_blk_POLICE","H_Cap_blk_ION","H_Cap_khaki_specops_UK","H_Cap_tan_specops_US","H_Cap_brn_SPECOPS","H_Cap_blk_CMMG","H_Cap_blk","H_Cap_blu","H_Cap_red", + "H_Cap_press","H_Cap_usblack","H_Beret_brn_SF","H_Beret_Colonel" + }; + pistols[] = {"hgun_ACPC2_F","hgun_P07_F","hgun_Pistol_heavy_01_F","hgun_Pistol_heavy_02_F","hgun_Rook40_F"}; + rifles[] = { + "arifle_Katiba_F","arifle_Katiba_C_F","arifle_Katiba_GL_F","arifle_Mk20_F","arifle_Mk20_plain_F","arifle_Mk20C_F","arifle_Mk20C_plain_F","arifle_Mk20_GL_F","arifle_Mk20_GL_plain_F", + "arifle_MXC_F","arifle_MX_F","arifle_MX_SW_F","arifle_MXC_Black_F","arifle_MX_Black_F","arifle_TRG21_F","arifle_TRG20_F","arifle_TRG21_GL_F","hgun_PDW2000_F","SMG_01_F","SMG_02_F" + }; + uniforms[] = {"U_C_Journalist","U_Rangemaster","U_Marshal","U_Competitor"}; + vests[] = {"V_TacVest_blk_POLICE","V_PlateCarrierSpec_blk","V_PlateCarrierGL_blk","V_TacVestCamo_khk","V_TacVest_blk","V_BandollierB_blk","V_Rangemaster_belt"}; + }; + + class crateLoot + { // Loot crate configuration + primarySlotsMax = 7; // Maximum primary weapons in each loot crate + primarySlotsMin = 2; // Minimum primary weapons in each loot crate + primaryWeaponLoot[] = + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"srifle_DMR_01_F",2},{"srifle_EBR_F",3},{"srifle_GM6_F",1},{"LMG_Mk200_F",3},{"LMG_Zafir_F",3},{"arifle_Katiba_F",3},{"arifle_Katiba_GL_F",2},{"arifle_Mk20_F",2}, + {"arifle_Mk20_plain_F",2},{"arifle_Mk20C_F",2},{"arifle_Mk20C_plain_F",2},{"arifle_Mk20_GL_F",2},{"arifle_Mk20_GL_plain_F",2},{"arifle_MXC_F",2},{"arifle_MX_F",2}, + {"arifle_MX_GL_F",2},{"arifle_MX_SW_F",2},{"arifle_MXM_F",2},{"arifle_MXC_Black_F",2},{"arifle_MX_Black_F",2},{"arifle_MX_GL_Black_F",2},{"arifle_MX_SW_Black_F",2}, + {"arifle_MXM_Black_F",2},{"arifle_SDAR_F",2},{"arifle_TRG21_F",2},{"arifle_TRG20_F",2},{"arifle_TRG21_GL_F",2},{"SMG_01_F",2},{"SMG_02_F",2},{"srifle_GM6_camo_F",2}, + {"srifle_LRR_camo_F",2},{"srifle_DMR_02_F",2},{"srifle_DMR_02_camo_F",2},{"srifle_DMR_02_sniper_F",2},{"srifle_DMR_03_F",2},{"srifle_DMR_03_khaki_F",2},{"srifle_DMR_03_tan_F",2}, + {"srifle_DMR_03_multicam_F",2},{"srifle_DMR_03_woodland_F",2},{"srifle_DMR_04_F",2},{"srifle_DMR_04_Tan_F",2},{"srifle_DMR_05_blk_F",2},{"srifle_DMR_05_hex_F",2},{"srifle_DMR_05_tan_f",2},{"srifle_DMR_06_camo_F",2},{"srifle_DMR_06_olive_F",2},{"MMG_01_hex_F",2},{"MMG_01_tan_F",2},{"MMG_02_camo_F",2}, + {"MMG_02_black_F",2},{"MMG_02_sand_F",2} + }; + + secondarySlotsMax = 3; // Maximum number of secondary weapons to be in each loot crate + secondarySlotsMin = 1; // Minimum number of secondary weapons to be in each loot crate + secondaryWeaponLoot[] = + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"hgun_ACPC2_F",3},{"hgun_P07_F",3},{"hgun_Pistol_heavy_01_F",3},{"hgun_Pistol_heavy_02_F",3},{"hgun_Rook40_F",3} + }; + + magSlotsMax = 8; // Maximum number of magazine slots in each loot crate + magSlotsMin = 6; // Minimum number of magazine slots in each loot crate + magLoot[] = + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"30Rnd_556x45_Stanag",20},{"30Rnd_556x45_Stanag_Tracer_Red",20},{"30Rnd_556x45_Stanag_Tracer_Green",20}, + {"30Rnd_556x45_Stanag_Tracer_Yellow",20},{"30Rnd_65x39_caseless_mag",20},{"30Rnd_65x39_caseless_green",20},{"30Rnd_65x39_caseless_mag_Tracer",20}, + {"30Rnd_65x39_caseless_green_mag_Tracer",20},{"20Rnd_762x51_Mag",20},{"7Rnd_408_Mag",20},{"5Rnd_127x108_Mag",20},{"100Rnd_65x39_caseless_mag",20}, + {"100Rnd_65x39_caseless_mag_Tracer",20},{"200Rnd_65x39_cased_Box",20},{"200Rnd_65x39_cased_Box_Tracer",20},{"30Rnd_9x21_Mag",20},{"16Rnd_9x21_Mag",20}, + {"30Rnd_45ACP_Mag_SMG_01",20},{"30Rnd_45ACP_Mag_SMG_01_Tracer_Green",20},{"9Rnd_45ACP_Mag",20},{"150Rnd_762x51_Box",20},{"150Rnd_762x51_Box_Tracer",20}, + {"150Rnd_762x54_Box",20},{"150Rnd_762x54_Box_Tracer",20},{"11Rnd_45ACP_Mag",20},{"6Rnd_45ACP_Cylinder",20},{"10Rnd_762x51_Mag",20},{"10Rnd_762x54_Mag",20}, + {"5Rnd_127x108_APDS_Mag",20},{"10Rnd_338_Mag",20},{"130Rnd_338_Mag",20},{"10Rnd_127x54_Mag",20},{"150Rnd_93x64_Mag",20},{"10Rnd_93x64_DMR_05_Mag",20} + }; + + attSlotsMax = 4; // Maximum number of attachment slots in each loot crate + attSlotsMin = 2; // Minimum number of attachment slots in each loot crate + attLoot[] = + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"ItemGPS",5},{"ItemRadio",4},{"ItemMap",6},{"MineDetector",1},{"Binocular",4},{"Rangefinder",2},{"muzzle_snds_H",2}, + {"muzzle_snds_L",2},{"muzzle_snds_M",2},{"muzzle_snds_B",2},{"muzzle_snds_H_MG",2},{"muzzle_snds_H_SW",2}, + {"optic_Arco",3},{"optic_Aco",3},{"optic_ACO_grn",3},{"optic_Aco_smg",3},{"optic_ACO_grn_smg",3},{"optic_Holosight",3}, + {"optic_Holosight_smg",3},{"optic_SOS",3},{"acc_flashlight",3},{"acc_pointer_IR",3},{"optic_MRCO",3},{"muzzle_snds_acp",3}, + {"optic_NVS",3},{"optic_DMS",3},{"optic_Yorris",2},{"optic_MRD",2},{"optic_LRPS",3},{"muzzle_snds_338_black",3},{"muzzle_snds_338_green",3}, + {"muzzle_snds_338_sand",3},{"muzzle_snds_93mmg",3},{"muzzle_snds_93mmg_tan",3},{"optic_AMS",3},{"optic_AMS_khk",3},{"bipod_03_F_oli",3}, + {"optic_AMS_snd",3},{"optic_KHS_blk",3},{"optic_KHS_hex",3},{"optic_KHS_old",3},{"optic_KHS_tan",3},{"bipod_01_F_snd",3}, + {"bipod_01_F_blk",3},{"bipod_01_F_mtp",3},{"bipod_02_F_blk",3},{"bipod_02_F_tan",3},{"bipod_02_F_hex",3},{"bipod_03_F_blk",3} + }; + + itemSlotsMax = 4; // Maximum number of attachment slots in each loot crate + itemSlotsMin = 2; // Minimum number of attachment slots in each loot crate + itemLoot[] = + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"Exile_Item_Flag",3},{"Exile_Item_FuelCanisterFull",2},{"Exile_Item_FuelCanisterEmpty",1},{"Exile_Item_InstaDoc",4},{"Exile_Item_Matches",3},{"Exile_Item_PlasticBottleFreshWater",5} + }; + + vestSlotsMax = 3; // Maximum number of vest slots in each loot crate + vestSlotsMin = 1; // Minimum number of vest slots in each loot crate + vestLoot[] = // NOTE ABOUT VESTS: it is recommended to keep amount for each vest at 1 because vests do not stack unlike weapons, items and magazines + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"V_PlateCarrier1_rgr",1},{"V_PlateCarrier2_rgr",1},{"V_PlateCarrier3_rgr",1},{"V_PlateCarrierGL_rgr",1},{"V_PlateCarrier1_blk",1}, + {"V_PlateCarrierSpec_rgr",1},{"V_Chestrig_khk",1},{"V_Chestrig_rgr",1},{"V_Chestrig_blk",1},{"V_Chestrig_oli",1},{"V_TacVest_khk",1}, + {"V_TacVest_brn",1},{"V_TacVest_oli",1},{"V_TacVest_blk",1},{"V_TacVest_camo",1},{"V_TacVest_blk_POLICE",1},{"V_TacVestIR_blk",1},{"V_TacVestCamo_khk",1}, + {"V_HarnessO_brn",1},{"V_HarnessOGL_brn",1},{"V_HarnessO_gry",1},{"V_HarnessOGL_gry",1},{"V_HarnessOSpec_brn",1},{"V_HarnessOSpec_gry",1}, + {"V_PlateCarrierIA1_dgtl",1},{"V_PlateCarrierIA2_dgtl",1},{"V_PlateCarrierIAGL_dgtl",1},{"V_RebreatherB",1},{"V_RebreatherIR",1},{"V_RebreatherIA",1}, + {"V_PlateCarrier_Kerry",1},{"V_PlateCarrierL_CTRG",1},{"V_PlateCarrierH_CTRG",1},{"V_I_G_resistanceLeader_F",1},{"V_Press_F",1} + }; + + headGearSlotsMax = 3; // Maximum number of headGear slots in each loot crate + headGearSlotsMin = 1; // Minimum number of headGear slots in each loot crate + headGearLoot[] = // NOTE ABOUT HEADGEAR: it is recommended to keep amount for each headGear item at 1 because headGear items do not stack unlike weapons, items and magazines + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"H_HelmetB",1},{"H_HelmetB_camo",1},{"H_HelmetB_paint",1},{"H_HelmetB_light",1},{"H_Booniehat_khk",1},{"H_Booniehat_oli",1},{"H_Booniehat_indp",1}, + {"H_Booniehat_mcamo",1},{"H_Booniehat_grn",1},{"H_Booniehat_tan",1},{"H_Booniehat_dirty",1},{"H_Booniehat_dgtl",1},{"H_Booniehat_khk_hs",1},{"H_HelmetB_plain_mcamo",1}, + {"H_HelmetB_plain_blk",1},{"H_HelmetSpecB",1},{"H_HelmetSpecB_paint1",1},{"H_HelmetSpecB_paint2",1},{"H_HelmetSpecB_blk",1},{"H_HelmetIA",1},{"H_HelmetIA_net",1}, + {"H_HelmetIA_camo",1},{"H_Helmet_Kerry",1},{"H_HelmetB_grass",1},{"H_HelmetB_snakeskin",1},{"H_HelmetB_desert",1},{"H_HelmetB_black",1},{"H_HelmetB_sand",1}, + {"H_Cap_red",1},{"H_Cap_blu",1},{"H_Cap_oli",1},{"H_Cap_headphones",1},{"H_Cap_tan",1},{"H_Cap_blk",1},{"H_Cap_blk_CMMG",1},{"H_Cap_brn_SPECOPS",1},{"H_Cap_tan_specops_US",1}, + {"H_Cap_khaki_specops_UK",1},{"H_Cap_grn",1},{"H_Cap_grn_BI",1},{"H_Cap_blk_Raven",1},{"H_Cap_blk_ION",1},{"H_Cap_oli_hs",1},{"H_Cap_press",1},{"H_Cap_usblack",1},{"H_Cap_police",1}, + {"H_HelmetCrew_B",1},{"H_HelmetCrew_O",1},{"H_HelmetCrew_I",1},{"H_PilotHelmetFighter_B",1},{"H_PilotHelmetFighter_O",1},{"H_PilotHelmetFighter_I",1}, + {"H_PilotHelmetHeli_B",1},{"H_PilotHelmetHeli_O",1},{"H_PilotHelmetHeli_I",1},{"H_CrewHelmetHeli_B",1},{"H_CrewHelmetHeli_O",1},{"H_CrewHelmetHeli_I",1},{"H_HelmetO_ocamo",1}, + {"H_HelmetLeaderO_ocamo",1},{"H_MilCap_ocamo",1},{"H_MilCap_mcamo",1},{"H_MilCap_oucamo",1},{"H_MilCap_rucamo",1},{"H_MilCap_gry",1},{"H_MilCap_dgtl",1}, + {"H_MilCap_blue",1},{"H_HelmetB_light_grass",1},{"H_HelmetB_light_snakeskin",1},{"H_HelmetB_light_desert",1},{"H_HelmetB_light_black",1},{"H_HelmetB_light_sand",1},{"H_BandMask_blk",1}, + {"H_BandMask_khk",1},{"H_BandMask_reaper",1},{"H_BandMask_demon",1},{"H_HelmetO_oucamo",1},{"H_HelmetLeaderO_oucamo",1},{"H_HelmetSpecO_ocamo",1},{"H_HelmetSpecO_blk",1}, + {"H_Bandanna_surfer",1},{"H_Bandanna_khk",1},{"H_Bandanna_khk_hs",1},{"H_Bandanna_cbr",1},{"H_Bandanna_sgg",1},{"H_Bandanna_sand",1},{"H_Bandanna_surfer_blk",1},{"H_Bandanna_surfer_grn",1}, + {"H_Bandanna_gry",1},{"H_Bandanna_blu",1},{"H_Bandanna_camo",1},{"H_Bandanna_mcamo",1},{"H_Shemag_khk",1},{"H_Shemag_tan",1},{"H_Shemag_olive",1},{"H_Shemag_olive_hs",1}, + {"H_ShemagOpen_khk",1},{"H_ShemagOpen_tan",1},{"H_Beret_blk",1},{"H_Beret_blk_POLICE",1},{"H_Beret_red",1},{"H_Beret_grn",1},{"H_Beret_grn_SF",1},{"H_Beret_brn_SF",1}, + {"H_Beret_ocamo",1},{"H_Beret_02",1},{"H_Beret_Colonel",1},{"H_Watchcap_blk",1},{"H_Watchcap_cbr",1},{"H_Watchcap_khk",1},{"H_Watchcap_camo",1},{"H_Watchcap_sgg",1}, + {"H_TurbanO_blk",1},{"H_Cap_marshal",1} + }; + + bagSlotsMax = 2; + bagSlotsMin = 1; + backpackLoot[] = // NOTE ABOUT BACKPACKS: it is recommended to keep amount for each bag at 1 because bags do not stack unlike weapons, items and magazines + { // The number after each classname means how much of that type will be put in crate. WARNING: DO NOT USE NUMBERS WITH DECIMALS. + {"B_AssaultPack_khk",1},{"B_AssaultPack_dgtl",1},{"B_AssaultPack_rgr",1},{"B_AssaultPack_sgg",1},{"B_AssaultPack_cbr",1}, + {"B_AssaultPack_mcamo",1},{"B_TacticalPack_rgr",1},{"B_TacticalPack_mcamo",1},{"B_TacticalPack_ocamo",1},{"B_TacticalPack_blk",1}, + {"B_TacticalPack_oli",1},{"B_FieldPack_khk",1},{"B_FieldPack_ocamo",1},{"B_FieldPack_oucamo",1},{"B_FieldPack_cbr",1}, + {"B_FieldPack_blk",1},{"B_Carryall_ocamo",1},{"B_Carryall_oucamo",1},{"B_Carryall_mcamo",1},{"B_Carryall_khk",1},{"B_Carryall_cbr",1}, + {"B_Parachute",1},{"B_FieldPack_oli",1},{"B_Carryall_oli",1},{"B_Kitbag_Base",1},{"B_Kitbag_cbr",1},{"B_Kitbag_mcamo",1}, + {"B_Kitbag_rgr",1},{"B_Kitbag_sgg",1},{"B_OutdoorPack_Base",1},{"B_OutdoorPack_blk",1},{"B_OutdoorPack_blu",1}, + {"B_OutdoorPack_tan",1} + }; + + blackListLoot[] = + { + "DemoCharge_Remote_Mag","SatchelCharge_Remote_Mag","ATMine_Range_Mag","ClaymoreDirectionalMine_Remote_Mag", + "APERSMine_Range_Mag","APERSBoundingMine_Range_Mag","SLAMDirectionalMine_Wire_Mag","APERSTripMine_Wire_Mag", + "ChainSaw","srifle_DMR_03_spotter_F" + }; + // End of loot crate configuration + }; + class aiGear + { // Configuration of what AI have + aiHeadGear[] = + { + "H_HelmetB","H_HelmetB_camo","H_HelmetB_paint","H_HelmetB_light","H_Booniehat_khk","H_Booniehat_oli","H_Booniehat_indp", + "H_Booniehat_mcamo","H_Booniehat_grn","H_Booniehat_tan","H_Booniehat_dirty","H_Booniehat_dgtl","H_Booniehat_khk_hs","H_HelmetB_plain_mcamo", + "H_HelmetB_plain_blk","H_HelmetSpecB","H_HelmetSpecB_paint1","H_HelmetSpecB_paint2","H_HelmetSpecB_blk","H_HelmetIA","H_HelmetIA_net", + "H_HelmetIA_camo","H_Helmet_Kerry","H_HelmetB_grass","H_HelmetB_snakeskin","H_HelmetB_desert","H_HelmetB_black","H_HelmetB_sand", + "H_Cap_red","H_Cap_blu","H_Cap_oli","H_Cap_headphones","H_Cap_tan","H_Cap_blk","H_Cap_blk_CMMG","H_Cap_brn_SPECOPS","H_Cap_tan_specops_US", + "H_Cap_khaki_specops_UK","H_Cap_grn","H_Cap_grn_BI","H_Cap_blk_Raven","H_Cap_blk_ION","H_Cap_oli_hs","H_Cap_press","H_Cap_usblack","H_Cap_police", + "H_HelmetCrew_B","H_HelmetCrew_O","H_HelmetCrew_I","H_PilotHelmetFighter_B","H_PilotHelmetFighter_O","H_PilotHelmetFighter_I", + "H_PilotHelmetHeli_B","H_PilotHelmetHeli_O","H_PilotHelmetHeli_I","H_CrewHelmetHeli_B","H_CrewHelmetHeli_O","H_CrewHelmetHeli_I","H_HelmetO_ocamo", + "H_HelmetLeaderO_ocamo","H_MilCap_ocamo","H_MilCap_mcamo","H_MilCap_oucamo","H_MilCap_rucamo","H_MilCap_gry","H_MilCap_dgtl", + "H_MilCap_blue","H_HelmetB_light_grass","H_HelmetB_light_snakeskin","H_HelmetB_light_desert","H_HelmetB_light_black","H_HelmetB_light_sand","H_BandMask_blk", + "H_BandMask_khk","H_BandMask_reaper","H_BandMask_demon","H_HelmetO_oucamo","H_HelmetLeaderO_oucamo","H_HelmetSpecO_ocamo","H_HelmetSpecO_blk", + "H_Bandanna_surfer","H_Bandanna_khk","H_Bandanna_khk_hs","H_Bandanna_cbr","H_Bandanna_sgg","H_Bandanna_sand","H_Bandanna_surfer_blk","H_Bandanna_surfer_grn", + "H_Bandanna_gry","H_Bandanna_blu","H_Bandanna_camo","H_Bandanna_mcamo","H_Shemag_khk","H_Shemag_tan","H_Shemag_olive","H_Shemag_olive_hs", + "H_ShemagOpen_khk","H_ShemagOpen_tan","H_Beret_blk","H_Beret_blk_POLICE","H_Beret_red","H_Beret_grn","H_Beret_grn_SF","H_Beret_brn_SF", + "H_Beret_ocamo","H_Beret_02","H_Beret_Colonel","H_Watchcap_blk","H_Watchcap_cbr","H_Watchcap_khk","H_Watchcap_camo","H_Watchcap_sgg", + "H_TurbanO_blk","H_Cap_marshal" + }; + aiUniforms[] = + { + "U_I_CombatUniform","U_I_CombatUniform_tshirt","U_I_CombatUniform_shortsleeve","U_I_pilotCoveralls", + "U_I_GhillieSuit","U_I_OfficerUniform","U_IG_Guerilla1_1","U_IG_Guerilla2_1","U_IG_Guerilla2_2","U_IG_Guerilla2_3", + "U_IG_Guerilla3_1","U_IG_Guerilla3_2","U_IG_leader","U_BG_Guerilla1_1","U_BG_Guerilla2_1","U_BG_Guerilla2_3", + "U_BG_Guerilla3_1","U_BG_Guerilla3_2","U_BG_leader","U_OG_Guerilla1_1","U_OG_Guerilla2_1","U_OG_Guerilla2_2", + "U_OG_Guerilla2_3","U_OG_Guerilla3_1","U_OG_Guerilla3_2","U_C_WorkerCoveralls","U_C_HunterBody_grn", + "U_C_HunterBody_brn","U_B_CTRG_1","U_B_CTRG_2","U_B_CTRG_3","U_B_survival_uniform","U_I_G_Story_Protagonist_F", + "U_I_G_resistanceLeader_F","U_IG_Guerrilla_6_1","U_BG_Guerrilla_6_1","U_OG_Guerrilla_6_1","U_B_FullGhillie_lsh", + "U_B_FullGhillie_sard","U_B_FullGhillie_ard","U_O_FullGhillie_lsh","U_O_FullGhillie_sard","U_O_FullGhillie_ard", + "U_I_FullGhillie_lsh","U_I_FullGhillie_sard","U_I_FullGhillie_ard" + }; + aiVests[] = + { + "V_PlateCarrier1_rgr","V_PlateCarrier2_rgr","V_PlateCarrier3_rgr","V_PlateCarrierGL_rgr","V_PlateCarrier1_blk", + "V_PlateCarrierSpec_rgr","V_Chestrig_khk","V_Chestrig_rgr","V_Chestrig_blk","V_Chestrig_oli","V_TacVest_khk", + "V_TacVest_brn","V_TacVest_oli","V_TacVest_blk","V_TacVest_camo","V_TacVest_blk_POLICE","V_TacVestIR_blk","V_TacVestCamo_khk", + "V_HarnessO_brn","V_HarnessOGL_brn","V_HarnessO_gry","V_HarnessOGL_gry","V_HarnessOSpec_brn","V_HarnessOSpec_gry", + "V_PlateCarrierIA1_dgtl","V_PlateCarrierIA2_dgtl","V_PlateCarrierIAGL_dgtl","V_RebreatherB","V_RebreatherIR","V_RebreatherIA", + "V_PlateCarrier_Kerry","V_PlateCarrierL_CTRG","V_PlateCarrierH_CTRG","V_I_G_resistanceLeader_F","V_Press_F" + }; + aiRifles[] = + { + "srifle_EBR_F","srifle_DMR_01_F","arifle_Katiba_F","arifle_Katiba_C_F","arifle_Katiba_GL_F","arifle_MXC_F", + "arifle_MX_F","arifle_MX_GL_F","arifle_MXM_F","arifle_SDAR_F","arifle_TRG21_F","arifle_TRG20_F", + "arifle_TRG21_GL_F","arifle_Mk20_F","arifle_Mk20C_F","arifle_Mk20_GL_F","arifle_Mk20_plain_F", + "arifle_Mk20C_plain_F","arifle_Mk20_GL_plain_F","SMG_01_F","SMG_02_F","hgun_PDW2000_F","arifle_MXM_Black_F", + "arifle_MX_GL_Black_F","arifle_MX_Black_F","arifle_MXC_Black_F","LMG_Mk200_F","arifle_MX_SW_F", + "LMG_Zafir_F","arifle_MX_SW_Black_F" + }; + aiBackpacks[] = + { + "B_AssaultPack_khk","B_AssaultPack_dgtl","B_AssaultPack_rgr","B_AssaultPack_sgg","B_AssaultPack_cbr", + "B_AssaultPack_mcamo","B_TacticalPack_rgr","B_TacticalPack_mcamo","B_TacticalPack_ocamo","B_TacticalPack_blk", + "B_TacticalPack_oli","B_FieldPack_khk","B_FieldPack_ocamo","B_FieldPack_oucamo","B_FieldPack_cbr", + "B_FieldPack_blk","B_Carryall_ocamo","B_Carryall_oucamo","B_Carryall_mcamo","B_Carryall_khk","B_Carryall_cbr", + "B_Parachute","B_FieldPack_oli","B_Carryall_oli","B_Kitbag_Base","B_Kitbag_cbr","B_Kitbag_mcamo", + "B_Kitbag_rgr","B_Kitbag_sgg","B_OutdoorPack_Base","B_OutdoorPack_blk","B_OutdoorPack_blu", + "B_OutdoorPack_tan" + }; + aiLaunchers[] = + { + "launch_NLAW_F","launch_RPG32_F","launch_B_Titan_F","launch_B_Titan_short_F" + }; + aiPistols[] = + { + "hgun_ACPC2_F","hgun_Rook40_F","hgun_P07_F","hgun_Pistol_heavy_01_F","hgun_Pistol_heavy_02_F" + }; + }; +}; + +#include "cpp\CfgPatches.cpp" +#include "cpp\CfgFunctions.cpp" +#include "cpp\CfgVemfrScripts.cpp" diff --git a/a3_vemf_reloaded/cpp/CfgFunctions.cpp b/a3_vemf_reloaded/cpp/CfgFunctions.cpp new file mode 100644 index 0000000..5f3c9e8 --- /dev/null +++ b/a3_vemf_reloaded/cpp/CfgFunctions.cpp @@ -0,0 +1,26 @@ +class CfgFunctions +{ + class a3_vemf_reloaded + { + tag = "VEMFr"; + class serverFunctions + { + file = "a3_vemf_reloaded\fn"; + class checkSide {}; + class config {}; + class findPos {}; + class giveAmmo {}; + class giveWeaponItems {}; + class hc {}; + class launch { postInit = 1; }; + class loadInv {}; + class mines {}; + class playerNear {}; + class scriptPath {}; + class spawnInvasionAI {}; + class spawnVEMFrAI {}; + class waitForPlayers {}; + class whichMod {}; + }; + }; +}; diff --git a/a3_vemf_reloaded/cpp/CfgPatches.cpp b/a3_vemf_reloaded/cpp/CfgPatches.cpp new file mode 100644 index 0000000..9a99a3c --- /dev/null +++ b/a3_vemf_reloaded/cpp/CfgPatches.cpp @@ -0,0 +1,12 @@ +class CfgPatches +{ + class a3_vemf_reloaded + { + units[] = {}; + requiredAddons[] = {}; + fileName = "a3_vemf_reloaded.pbo"; + requiredVersion = 1.60; // VEMFr does not work on older versions due to use of the latest scripting commands + version = "0750.0"; // Do NOT change + author = "IT07"; + }; +}; diff --git a/a3_vemf_reloaded/cpp/CfgVemfrScripts.cpp b/a3_vemf_reloaded/cpp/CfgVemfrScripts.cpp new file mode 100644 index 0000000..52c36c0 --- /dev/null +++ b/a3_vemf_reloaded/cpp/CfgVemfrScripts.cpp @@ -0,0 +1,17 @@ +class CfgVemfrScripts +{ + aiKilled = "a3_vemf_reloaded\sqf\aiKilled.sqf"; + broadCast = "a3_vemf_reloaded\sqf\broadCast.sqf"; + checkLoot = "a3_vemf_reloaded\sqf\checkLoot.sqf"; + killedMonitor = "a3_vemf_reloaded\sqf\killedMonitor"; + loadLoot = "a3_vemf_reloaded\sqf\loadLoot.sqf"; + log = "a3_vemf_reloaded\sqf\log.sqf"; + missionTimer = "a3_vemf_reloaded\sqf\missionTimer.sqf"; + notificationToClient = "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + REMOTEguard = "a3_vemf_reloaded\sqf\REMOTEguard.sqf"; + sayKilledWeapon = "a3_vemf_reloaded\sqf\sayKilledWeapon.sqf"; + setGroupOwner = "a3_vemf_reloaded\sqf\setGroupOwner.sqf"; + signAI = "a3_vemf_reloaded\sqf\signAI.sqf"; + spawnStaticAI = "a3_vemf_reloaded\sqf\spawnStaticAI.sqf"; + systemChatToClient = "a3_vemf_reloaded\sqf\systemChatToClient.sqf"; +}; diff --git a/a3_vemf_reloaded/fn/fn_checkSide.sqf b/a3_vemf_reloaded/fn/fn_checkSide.sqf new file mode 100644 index 0000000..c495532 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_checkSide.sqf @@ -0,0 +1,49 @@ +/* + Author: IT07 + + Description: checks the side of given unit and returns it + + Params: + _this: STRING - unit classname + + Returns: SIDE - unit's side +*/ + +private ["_r","_f"]; +_f = getText (configFile >> "CfgVehicles" >> _this >> "faction"); +if not(_f isEqualTo "") then + { + scopeName "isNull"; + if (_f isEqualTo "BLU_G_F") then + { + _r = WEST; + breakOut "isNull"; + }; + if (_f isEqualTo "CIV_F") then + { + _r = civilian; + breakOut "isNull"; + }; + if (_f isEqualTo "IND_F") then + { + _r = independent; + breakOut "isNull"; + }; + if (_f isEqualTo "IND_G_F") then + { + _r = resistance; + breakOut "isNull"; + }; + if (_f isEqualTo "OPF_G_F") then + { + _r = EAST; + }; + } else + { + ["fn_checkSide", 0, format["Failed to find faction of %1", _this]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + +if not(isNil "_r") then + { + _r + }; diff --git a/a3_vemf_reloaded/fn/fn_config.sqf b/a3_vemf_reloaded/fn/fn_config.sqf new file mode 100644 index 0000000..4a5238b --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_config.sqf @@ -0,0 +1,83 @@ +/* + Author: IT07 + + Description: + gets config value of given var from VEMF config OR cfgPath + + Params: + method 1: + _this: STRING - SINGLE config value to get from root of CfgVemfReloaded + method 2: + _this select 0: ARRAY of STRINGS - MULTIPLE config values to get from root of VEMFconfig + method 3: + _this select 0: ARRAY of STRINGS - config path to get value from. Example: "root","subclass" + _this select 1: ARRAY of STRINGS - MULTIPLE config values to get from given path + + Returns: + ARRAY - Result +*/ + +private["_r","_chck","_v","_cfg"]; +_r = []; +_chck = + { + if (isNumber _cfg) then { _v = getNumber _cfg }; + if (isText _cfg) then { _v = getText _cfg }; + if (isArray _cfg) then { _v = getArray _cfg }; + if (isNil "_v") then { _v = "nil" }; + }; + +if (_this isEqualType "") then + { + if (isNull (configFile >> "CfgVemfReloadedOverrides" >> _this)) then + { + _cfg = configFile >> "CfgVemfReloaded" >> _this; + } else + { + _cfg = configFile >> "CfgVemfReloadedOverrides" >> _this; + }; + call _chck; + _r = _v; + }; + +if (_this isEqualType []) then + { + if (_this isEqualTypeArray [[],[]]) then + { + private ["_p","_b"]; + _p = _this select 0; + _b = + { + { + _cfg = _cfg >> _x; + } forEach _p; + }; + { + _cfg = configFile >> "CfgVemfReloadedOverrides"; + call _b; + _cfg = _cfg >> _x; + if (isNull _cfg) then + { + _cfg = configFile >> "CfgVemfReloaded"; + call _b; + _cfg = _cfg >> _x; + }; + call _chck; + _r pushBack _v; + } forEach (_this select 1); + }; + if (_this isEqualTypeArray [[]]) then + { + { + _cfg = configFile >> "CfgVemfReloadedOverrides" >> _x; + if (isNull _cfg) then + { + _cfg = configFile >> "CfgVemfReloaded" >> _x; + }; + call _chck; + _r pushBack _v; + } forEach (_this select 0); + }; + }; + +_r diff --git a/a3_vemf_reloaded/fn/fn_findPos.sqf b/a3_vemf_reloaded/fn/fn_findPos.sqf new file mode 100644 index 0000000..67093ea --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_findPos.sqf @@ -0,0 +1,139 @@ +/* + Author: IT07 + + Description: + can find a location or pos randomly on the map where there are no players + + Params: + _this select 0: STRING - Mode to use. Options: "loc" or "pos" + _this select 1: BOOLEAN - True if _pos needs to be a road + _this select 2: POSITION - Center for nearestLocations check + _this select 3: SCALAR - Distance in meters. Locations closer than given position will be excluded/included + _this select 4: SCALAR - Max prefered distance in meters from center. If not achievable, further dest will be selected + _this select 5: SCALAR - Distance in meters to check from _this2 for players + _this select 6: STRING (optional) - Exact config name of mission override settings to load + + Returns: + if mode == loc: LOCATION + if mode == pos: POSITION +*/ + +private [ + "_r","_this0","_this1","_this2","_this3","_this4","_this5","_this6", + "_s0","_s1","_s2","_s3", + "_ms0","_arr","_bin","_used","_fltr","_badNames","_maps","_bad", + "_pos","_xx","_pos","_hi","_low","_dist","_loc" +]; + +params [ + ["_this0", "", [""]], + ["_this1", false, [false]], + ["_this2", [], [[]]], + ["_this3", -1, [0]], + ["_this4", -1, [0]], + ["_this5", -1, [0]], + ["_this6", "", [""]] +]; + +([["nonPopulated","noMissionPos","missionDistance","missionList"]] call VEMFr_fnc_config) params ["_s0","_s1","_s2","_s3"]; +_ms0 = ([[_this6],["skipDistanceReversed"]] call VEMFr_fnc_config) select 0; +if (_this6 in _s3) then { _s0 = ([[_this6],["nonPopulated"]] call VEMFr_fnc_config) select 0 }; + +if (_this0 isEqualTo "loc") then + { + // Get a list of locations close to _this2 (position of player) + _arr = nearestLocations [_this2, ["CityCenter","Strategic","StrongpointArea","NameVillage","NameCity","NameCityCapital", if (_s0 isEqualTo 1) then {"nameLocal","Area","BorderCrossing","Hill","fakeTown","Name","RockArea","ViewPoint"}], if (_ms0 > 0) then {_ms0*2} else {worldSize}]; + if ((count _arr) > 0) then + { + _maps = "isClass _x" configClasses (configFile >> "CfgVemfReloaded" >> "locationBlackLists"); + { // Make a list of locationBlackLists's children + _maps set [_forEachIndex, toLower (configName _x)]; + } forEach _maps; + + if ((toLower worldName) in _maps) then + { + _bad = ([["locationBlackLists", worldName],["locations"]] call VEMFr_fnc_config) select 0 + } else + { + _bad = ([["locationBlackLists","Other"],["locations"]] call VEMFr_fnc_config) select 0 + }; + + _bin = []; + _used = uiNamespace getVariable ["VEMFrUsedLocs",[]]; + + _fltr = + { + scopeName "filter"; + _xx = _x; + { + if (((_x select 0) distance (locationPosition _xx)) <= (_x select 1)) then { _bin pushBack _xx; breakOut "filter" }; + } forEach _s1; + + if (_x in _used) then { _bin pushBack _x } + else + { + { + if (((locationPosition _xx) distance (locationPosition _x)) < _s2) then { _bin pushBack _xx; breakOut "filter" }; + } forEach _used; + }; + + if (((text _x) in _bad) OR ((toLower (text _x)) in _bad)) then { _bin pushBack _x }; + }; + { + _dist = _this2 distance (locationPosition _x); + if (_ms0 > 0) then + { + if ((_dist <= (_ms0*2)) AND (_dist > _ms0)) then { call _fltr } + else { _bin pushBack _x }; + } else + { + if (_dist > _this3) then { call _fltr } + else { _bin pushBack _x }; + }; + } forEach _arr; + + { // Remove all invalid locations from _arr + _arr deleteAt (_arr find _x); + } forEach _bin; + + // Check what kind of distances we have + _low = []; // Closer then _this4 + _hi = []; // Further than _this4 + { + _dist = _this2 distance (locationPosition _x); + if (_dist > _this4) then { _hi pushBack _x }; + if (_dist <= _this4) then { _low pushBack _x }; + } forEach _arr; + + // Check if there are any prefered locations. If yes, randomly select one + if ((count _low) > 0) then + { + _loc = selectRandom _low; + _r = _loc; + _used pushBackUnique _loc; + } else + { + if ((count _hi) > 0) then + { + _loc = selectRandom _hi; + _r = _loc; + _used pushBackUnique _loc; + }; + }; + }; + }; + +if (_this0 isEqualTo "pos") then + { + for "_p" from 1 to 10 do + { + _pos = [_this2, _this3, -1, 2, 0, 50, 0] call BIS_fnc_findSafePos; + if _this1 then { _pos = position (nearRoads select 0) }; + if not([_pos, _this5] call VEMFr_fnc_playerNear) then + { + _r = _pos; + }; + }; + }; + +if not(isNil "_r") then { _r }; diff --git a/a3_vemf_reloaded/fn/fn_giveAmmo.sqf b/a3_vemf_reloaded/fn/fn_giveAmmo.sqf new file mode 100644 index 0000000..995baa8 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_giveAmmo.sqf @@ -0,0 +1,64 @@ +/* + Author: IT07 + + Description: + Adds magazines to given unit's vest/backpack if it flairTypes + + Params: + _this: ARRAY + _this select 0: OBJECT - unit to give ammo to + _this select 1: STRING - primaryWeapon classname + _this select 2: STRING - secondaryWeapon classname + _this select 3: STRING - handGunWeapon classname + + Returns: + BOOLEAN - true if successful +*/ + +private ["_r","_this0","_m"]; +params [ + ["_this0", objNull, [objNull]], + ["_this1", "", [""]], + ["_this2", "", [""]], + ["_this3", "", [""]] +]; + +_r = []; +if not(_this1 isEqualTo "") then + { + _m = selectRandom (getArray (configFile >> "CfgWeapons" >> _this1 >> "magazines")); + for "_l" from 1 to 5 do + { + if not(_this0 canAdd _m) exitWith {}; + _this0 addItem _m; + }; + _r pushBack true; + }; + +if not(_this2 isEqualTo "") then + { + if not((backPack _this0) isEqualTo "") then + { + _m = selectRandom (getArray (configFile >> "CfgWeapons" >> _this2 >> "magazines")); + for "_l" from 1 to 3 do + { + if not(_this0 canAdd _m) exitWith {}; + _this0 addItem _m; + }; + _r pushBack true; + }; + }; + +if not(_this3 isEqualTo "") then + { + _m = selectRandom (getArray (configFile >> "CfgWeapons" >> _this3 >> "magazines")); + for "_l" from 1 to 4 do + { + if not(_this0 canAdd _m) exitWith {}; + _this0 addItem _m; + }; + _r pushBack true; + }; + +if ((count _r) > 0) then { _r = true } else { _r = nil }; +_r diff --git a/a3_vemf_reloaded/fn/fn_giveWeaponItems.sqf b/a3_vemf_reloaded/fn/fn_giveWeaponItems.sqf new file mode 100644 index 0000000..923af40 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_giveWeaponItems.sqf @@ -0,0 +1,64 @@ +/* + Author: IT07 + + Description: + Gives random weapon attachments to given unit + + Params: + _this: ARRAY + _this select 0: OBJECT - unit + + Returns: BOOLEAN - true if no errors occured +*/ + +private ["_r","_p","_w","_a","_bin"]; +_u = param [0,objNull,[objNull]]; +if not (isNull _u) then + { + _p = [1,0,1,0,1,1,1,1,0,0,1,1,1]; + _w = primaryWeapon _u; + if ((selectRandom _p) isEqualTo 1) then + { // Select random scope + _a = getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems"); + if (("allowTWS" call VEMFr_fnc_config) isEqualTo 0) then + { + _bin = []; + { + if (((toLower _x) find "tws") > -1) then + { + _bin pushBack _x; + }; + } forEach _a; + { + _a deleteAt (_a find _x); + } forEach _bin; + }; + _u addPrimaryWeaponItem (selectRandom _a); + }; + if ((selectRandom _p) isEqualTo 1) then + { // Select random muzzle + _u addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems"))); + }; + if ((selectRandom _p) isEqualTo 1) then + { // Select random pointer + _u addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "PointerSlot" >> "compatibleItems"))); + }; + if ((selectRandom _p) isEqualTo 1) then + { // Select random bipod + _u addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "UnderbarrelSlot" >> "compatibleItems"))); + }; + + // handgunWeapon items + _w = handgunWeapon _u; + _p = [1,0,1,0,0,1,0,0,0,0,1,1,1]; + if ((selectRandom _p) isEqualTo 1) then + { // Select random scope + _u addHandgunItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems"))); + }; + if ((selectRandom _p) isEqualTo 1) then + { // Select random muzzle + _u addHandgunItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _w >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems"))); + }; + _r = true; + }; +_r diff --git a/a3_vemf_reloaded/fn/fn_hc.sqf b/a3_vemf_reloaded/fn/fn_hc.sqf new file mode 100644 index 0000000..c0fb971 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_hc.sqf @@ -0,0 +1,38 @@ +/* + Author: IT07 + + Description: + selects a headless client with least (VEMFr) load + + Params: + None + + Returns: + OBJECT - the headless client +*/ + +private ["_r","_n","_arr","_gl"]; +_n = "headLessClientNames" call VEMFr_fnc_config; +_arr = []; +_gl = uiNamespace getVariable "VEMFrHcLoad"; +{ + if (((side _x) isEqualTo sideLogic) AND ((name _x) in _n)) then + { + _arr pushBackUnique _x; + if not(_x in (_gl select 0)) then + { + _i = (_gl select 0) pushBack _x; + (_gl select 1) set [_i, 0]; + }; + }; +} forEach playableUnits; + +_l = 99999; +{ + if (_x <= _l) then { _l = _x }; +} forEach (_gl select 1); + +_r = (_gl select 0) select ((_gl select 1) find _l); +(_gl select 1) set [(_gl select 0) find _r, _l + 1]; + +_r diff --git a/a3_vemf_reloaded/fn/fn_launch.sqf b/a3_vemf_reloaded/fn/fn_launch.sqf new file mode 100644 index 0000000..39c68c2 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_launch.sqf @@ -0,0 +1,64 @@ +/* + Author: IT07 + + Description: + launches VEMFr (You don't say?) +*/ + +if isNil "VEMFrHasStarted" then + { + VEMFrHasStarted = call compileFinal "true"; + ["Launcher", 2, format["/// STARTING VEMFr v%1 (%2) \\\", getText (configFile >> "CfgPatches" >> "a3_vemf_reloaded" >> "version"), call VEMFr_fnc_whichMod]] ExecVM ("log" call VEMFr_fnc_scriptPath); + uiNamespace setVariable ["VEMFrUsedLocs", []]; + uiNamespace setVariable ["VEMFrAttackedFlags", []]; + uiNamespace setVariable ["VEMFrHcLoad", [[],[]]]; + + [] spawn + { + if (("overridesToRPT" call VEMFr_fnc_config) isEqualTo 1) then + { + _r = configProperties [configFile >> "CfgVemfReloadedOverrides", "true", false]; + { + if (isClass _x) then + { + _c1 = configName _x; + _l1 = configProperties [configFile >> "CfgVemfReloadedOverrides" >> _c1, "true", false]; + { + if (isClass _x) then + { + _c2 = configName _x; + _l2 = configProperties [configFile >> "CfgVemfReloadedOverrides" >> _c1 >> _c2, "true", false]; + { + if not(isClass _x) then + { + ["overridesToRPT", 1, format["Overriding 'CfgVemfReloaded >> %1 >> %2 >> %3'", _c1, _c2, configName _x]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _l2; + } else + { + ["overridesToRPT", 1, format["Overriding 'CfgVemfReloaded >> %1 >> %2", _c1, configName _x]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _l1; + } else + { + ["overridesToRPT", 1, format["Overriding 'CfgVemfReloaded >> %1'", configName _x]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _r; + }; + + _s = ["checkLoot","missionTimer","REMOTEguard","spawnStaticAI"]; + { + ExecVM format["a3_vemf_reloaded\sqf\%1.sqf", _x]; + } forEach _s; + + + if ((call VEMFr_fnc_whichMod) isEqualTo "Epoch") then + { + west setFriend [independent, 0]; + independent setFriend [west, 0]; + }; + }; + } else + { + ["Launcher", 0, format["a3_vemf_reloaded FAILED to launch! VEMFrHasStarted (%1) is already defined!", VEMFrHasStarted]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; diff --git a/a3_vemf_reloaded/fn/fn_loadInv.sqf b/a3_vemf_reloaded/fn/fn_loadInv.sqf new file mode 100644 index 0000000..2c1650c --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_loadInv.sqf @@ -0,0 +1,211 @@ +/* + Author: IT07 + + Description: + gives inventory to given units + + Param: + _this: ARRAY + _this select 0: ARRAY - units to load inventory for + _this select 1: STRING - must be in missionList + _this select 2: SCALAR - inventory mode + + Returns: + BOOLEAN - true if nothing failed +*/ + +private ["_r","_this0","_this1","_this2"]; +params [ + ["_this0", [], [[]]], + ["_this1", "", [""]], + ["_this2", 0, [0]] +]; + +if ((_this1 in ("missionList" call VEMFr_fnc_config)) OR (_this1 isEqualTo "Static")) then + { + scopeName "this"; + if (_this2 isEqualTo 0) then // "Militia" + { + private ["_s","_unifs","_headG","_vests","_packs","_lnchers","_rfles","_pstls","_ls","_lc","_a"]; + // Define settings + _s = [["aiGear"],["aiUniforms","aiHeadGear","aiVests","aiBackpacks","aiLaunchers","aiRifles","aiPistols"]] call VEMFr_fnc_config; + _s params ["_unifs","_headG","_vests","_packs","_lnchers","_rfles","_pstls"]; + { + private ["_xx","_g","_a","_pw","_hw"]; + _xx = _x; + // Strip it + removeAllWeapons _xx; + removeAllItems _xx; + if ("removeAllAssignedItems" call VEMFr_fnc_config isEqualTo 1) then + { + removeAllAssignedItems _xx; + }; + removeVest _xx; + removeBackpack _xx; + removeGoggles _xx; + removeHeadGear _xx; + if (count _unifs > 0) then + { + removeUniform _xx; + _g = selectRandom _unifs; + _xx forceAddUniform _g; // Give the poor naked guy some clothing :) + }; + if (_this1 isEqualTo "BaseAttack") then + { + _xx addBackpack "B_Parachute"; + }; + _g = selectRandom _headG; + _xx addHeadGear _g; + _g = selectRandom _vests; + _xx addVest _g; + _ls = [[_this1],["allowLaunchers","hasLauncherChance"]] call VEMFr_fnc_config; + if ((_ls select 0) isEqualTo 1) then + { + _lc = _ls select 1; + if ((_lc isEqualTo 100) OR ((ceil random (100 / _lc) isEqualTo (ceil random (100 / _lc))))) then + { + if not(_this1 isEqualTo "BaseAttack") then + { + _g = selectRandom _packs; + _xx addBackpack _g; + }; + _g = selectRandom _lnchers; + _a = getArray (configFile >> "cfgWeapons" >> _g >> "magazines"); + if (count _a > 2) then + { + _a resize 2; + }; + for "_i" from 0 to (2 + (round random 1)) do + { + _xx addMagazine (selectRandom _a); + }; + _xx addWeapon _g; + }; + }; + + // Select a random weapon + _pw = selectRandom _rfles; + _hw = selectRandom _pstls; + // Give this guy some ammo + _g = [_xx, _pw, "", _hw] call VEMFr_fnc_giveAmmo; + if (isNil "_g") then + { + ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + _xx addWeapon _pw; + _xx selectWeapon _pw; + _xx addWeapon _hw; + // Give this guy some weaponItems + _g = [_xx] call VEMFr_fnc_giveWeaponItems; + if not _g then + { + ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _this0; + _r = true; + breakOut "this"; + }; + + if (_this2 isEqualTo 1) then // Regular police + { + private ["_s","_headG","_vests","_unifs","_rfles","_pstls","_packs"]; + _s = [["policeConfig"],["headGear","vests","uniforms","rifles","pistols","backpacks"]] call VEMFr_fnc_config; + _s params ["_headG","_vests","_unifs","_rfles","_pstls","_packs"]; + { + private ["_xx","_g","_pw","_hw"]; + _xx = _x; + // Strip it + removeAllWeapons _xx; + removeAllItems _xx; + if ("removeAllAssignedItems" call VEMFr_fnc_config isEqualTo 1) then + { + removeAllAssignedItems _xx; + }; + removeUniform _xx; + removeVest _xx; + removeBackpack _xx; + removeGoggles _xx; + removeHeadGear _xx; + _g = selectRandom _headG; + _xx addHeadGear _g; + _g = selectRandom _vests; + _xx addVest _g; + _g = selectRandom _unifs; + _xx forceAddUniform _g; + + _pw = selectRandom _rfles; + _hw = selectRandom _pstls; + // Give this guy some ammo + _g = [_xx, _pw, "", _hw] call VEMFr_fnc_giveAmmo; + if (isNil "_g") then + { + ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + _xx addWeapon _pw; + _xx selectWeapon _pw; + _xx addWeapon _hw; + if not(_this1 isEqualTo "BaseAttack") then + { + _xx addBackPack (selectRandom _packs); + } else + { + _xx addBackpack "B_Parachute"; + }; + // Give this guy some weaponItems + _g = [_xx] call VEMFr_fnc_giveWeaponItems; + if (isNil "_g") then + { + ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _this0; + _r = true; + breakOut "this"; + }; + + if (_this2 isEqualTo 2) then // S.W.A.T. + { + private ["_s","_rfles","_pstls"]; + _s = [["policeConfig"],["rifles","pistols"]] call VEMFr_fnc_config; + _s params ["_rfles","_pstls"]; + { + private ["_xx","_g","_pw","_hw"]; + _xx = _x; + // Strip it + if ("removeAllAssignedItems" call VEMFr_fnc_config isEqualTo 1) then { removeAllAssignedItems _xx }; + removeAllItems _xx; + removeAllWeapons _xx; + removeBackpack _xx; + removeGoggles _xx; + removeHeadGear _xx; + removeUniform _xx; + removeVest _xx; + _xx addHeadGear "H_HelmetB_light_black"; + _xx addGoggles "G_Balaclava_blk"; + _xx addVest "V_PlateCarrier2_blk"; + _xx forceAddUniform "Exile_Uniform_ExileCustoms"; + + _pw = selectRandom _rfles; + _hw = selectRandom _pstls; + // Give this guy some ammo + _g = [_xx, _pw, "", _hw] call VEMFr_fnc_giveAmmo; + if (isNil "_g") then + { + ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + _xx addWeapon _pw; + _xx selectWeapon _pw; + _xx addWeapon _hw; + + if (_this1 isEqualTo "BaseAttack") then { _xx addBackpack "B_Parachute" }; + + // Give this guy some weaponItems + _g = [_xx] call VEMFr_fnc_giveWeaponItems; + if (isNil "_g") then + { + ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _xx]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } forEach _this0; + _r = true; + }; + }; +_r diff --git a/a3_vemf_reloaded/fn/fn_mines.sqf b/a3_vemf_reloaded/fn/fn_mines.sqf new file mode 100644 index 0000000..0a37caa --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_mines.sqf @@ -0,0 +1,47 @@ +/* + Author: IT07 + + Description: + places mines around given position within given radius + + Params: + _this select 0: POSITION - center of area to place mines around + _this select 1: SCALAR - the minimum distance + _this select 2: SCALAR - the maximum distance (must be higher than minimum of course) + _this select 3: STRING - exact config name of mission + + Returns: + ARRAY - array containing all mine objects +*/ + +scopeName "mines"; +private ["_r","_this0","_this1","_this2","_this3","_s","_ms","_a","_mt"]; +params [ + ["_this0",[],[[]]], + ["_this1",-1,[0]], + ["_this2",-1,[0]], + ["_this3", "", [""]] +]; + +_s = [[_this3],["mines","minesAmount"]] call VEMFr_fnc_config; +_s params ["_ms","_a"]; +if ((_this3 in ("missionList" call VEMFr_fnc_config)) AND (_ms > 0) AND ((count _this0) isEqualTo 3) AND (_this1 > -1) AND (_this2 > _this1) AND (_a > -1)) then + { + if (_ms isEqualTo 1) then { _mt = ["ATMine"] }; + if (_ms isEqualTo 2) then { _mt = ["APERSMine"] }; + if (_ms isEqualTo 3) then { _mt = ["ATMine","APERSMine"] }; + if (_ms < 1 OR _ms > 3) then + { + ["fn_mines", 0, "Invalid mines mode!"] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "mines" + }; + _r = []; + ["fn_mines", 1, format["Placing %1 mines at %2", _a, _this0]] ExecVM ("log" call VEMFr_fnc_scriptPath); + for "_m" from 1 to _a do + { + _r pushBack (createMine [selectRandom _mt, ([_this0, _this1, _this2, 2, 0, 20, 0] call BIS_fnc_findSafePos), [], 0]); + uiSleep 0.1; + }; + }; + +_r diff --git a/a3_vemf_reloaded/fn/fn_playerNear.sqf b/a3_vemf_reloaded/fn/fn_playerNear.sqf new file mode 100644 index 0000000..f5013a7 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_playerNear.sqf @@ -0,0 +1,33 @@ +/* + Author: IT07 + + Description: + checks for players within given distance of given location/position + + Params: + _this select 0: POSITION - center of area to check around + _this select 1: SCALAR - radius around the position to check for players + + Returns: + BOOL - true if player(s) found +*/ + +private ["_r","_this0","_this1"]; +// By default, we assume that there are no players close. The distance check below should prove otherwise if there are players close +_r = false; +params [ + ["_this0", [], [[]]], + ["_this1", -1, [0]] +]; +if (((count _this0) isEqualTo 3) AND (_this1 > -1)) then + { + scopeName "find"; + { + if ((isPlayer _x) AND ((speed _x) < 250)) then + { + if ((position _x distance _this0) < _this1) then { _r = true; breakOut "find" }; + }; + } forEach allPlayers; + }; + +_r diff --git a/a3_vemf_reloaded/fn/fn_scriptPath.sqf b/a3_vemf_reloaded/fn/fn_scriptPath.sqf new file mode 100644 index 0000000..c15b2b9 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_scriptPath.sqf @@ -0,0 +1,13 @@ +/* + Author: IT07 + + Description: + returns the script path of given string + + Returns: + STRING - path to sqf file +*/ + +private "_r"; +_r = getText (configFile >> "CfgVemfrScripts" >> (param [0,"",[""]])); +_r diff --git a/a3_vemf_reloaded/fn/fn_spawnInvasionAI.sqf b/a3_vemf_reloaded/fn/fn_spawnInvasionAI.sqf new file mode 100644 index 0000000..0c5d056 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_spawnInvasionAI.sqf @@ -0,0 +1,183 @@ +/* + Author: IT07 + + Description: + spawns AI using given _this0 and unit/group count. + + Params: + _this select 0: POSITION - where to spawn the units around + _this select 1: SCALAR - how many groups to spawn + _this select 2: SCALAR - how many units to put in each group + _this select 3: SCALAR - AI mode + _this select 4: STRING - exact config name of mission + _this select 5: SCALAR (optional) - maximum spawn distance from center + + Returns: + ARRAY format [[groups],[50cals]] +*/ + +private ["_r","_this0","_this1","_this2","_this3","_this4","_this5"]; +params [ + ["_this0", [], [[]]], + ["_this1", 1, [0]], + ["_this2", 1, [0]], + ["_this3", -1, [0]], + ["_this4", "", [""]], + ["_this5", 175, [0]] +]; + +if (_this4 in ("missionList" call VEMFr_fnc_config)) then + { + private [ + "_grps","_s","_ccrcy","_mShk","_mSpd","_stmna","_sptDst","_sptTme", + "_crge","_rldSpd","_cmmndng","_gnrl","_notTheseHouses","_gdHss","_nHss","_cl50s","_nts" + ]; + _r = [[],[]]; + _grps = []; + _s = [["aiSkill", ([["aiSkill"],["difficulty"]] call VEMFr_fnc_config) select 0],["accuracy","aimingShake","aimingSpeed","endurance","spotDistance","spotTime","courage","reloadSpeed","commanding","general"]] call VEMFr_fnc_config; + _s params ["_ccrcy","_mShk","_mSpd","_stmna","_sptDst","_sptTme","_crge","_rldSpd","_cmmndng","_gnrl"]; + _notTheseHouses = "housesBlackList" call VEMFr_fnc_config; + _gdHss = []; + { // Filter the houses that are too small for one group + if not(typeOf _x in _notTheseHouses) then + { + if ([_x, _this2] call BIS_fnc_isBuildingEnterable) then + { + _gdHss pushBack _x; + }; + }; + } forEach (nearestTerrainObjects [_this0,["House"],_this5]); + + _gdHss = _gdHss call BIS_fnc_arrayShuffle; + _nHss = false; + if (count _gdHss < _this1) then + { + _nHss = true; + }; + + _cl50s = ([["DynamicLocationInvasion"],["cal50s"]] call VEMFr_fnc_config) select 0; + + _nts = []; // Define units array. the for loops below will fill it with units + for "_g" from 1 to _this1 do // Spawn Groups near Position + { + if not _nHss then + { + if (count _gdHss < 1) then + { + _nHss = true + }; + }; + + private ["_grp","_hs","_hsPstns","_plcd50","_i"]; + _grp = createGroup ((([[call VEMFr_fnc_whichMod],["unitClass"]] call VEMFr_fnc_config) select 0) call VEMFr_fnc_checkSide); + (_r select 0) pushBack _grp; + _grp allowFleeing 0; + if not _nHss then + { + _hs = selectRandom _gdHss; + _hsID = _gdHss find _hs; + _gdHss deleteAt _hsID; + _hsPstns = [_hs] call BIS_fnc_buildingPositions; + }; + + _plcd50 = false; + for "_u" from 1 to _this2 do + { + private ["_spwnPs","_hmg","_nt"]; + if _nHss then + { + _spwnPs = [_this0,20,_this5,1,0,200,0] call BIS_fnc_findSafePos; // Find Nearby Position + } else + { + _spwnPs = selectRandom _hsPstns; + if not _plcd50 then + { + _plcd50 = true; + if (_cl50s > 0) then + { + _hmg = createVehicle ["O_HMG_01_high_F", _spwnPs, [], 0, "CAN_COLLIDE"]; + _hmg setVehicleLock "LOCKEDPLAYER"; + (_r select 1) pushBack _hmg; + }; + }; + }; + + _nt = _grp createUnit [([[call VEMFr_fnc_whichMod],["unitClass"]] call VEMFr_fnc_config) select 0, _spwnPs, [], 0, "CAN_COLLIDE"]; // Create Unit There + if ((not _nHss) AND (_cl50s > 0)) then + { + if not(isNil "_hmg") then + { + if not(isNull _hmg) then + { + _nt moveInGunner _hmg; + _hmg = nil; + _cl50s = _cl50s - 1; + }; + }; + _hsPstns deleteAt (_hsPstns find _spwnPs); + }; + + _nt addMPEventHandler ["mpkilled","if (isDedicated) then { [[(_this select 0),(name(_this select 0))],[(_this select 1),(name(_this select 1))]] ExecVM 'a3_vemf_reloaded\sqf\aiKilled.sqf' }"]; + + // Set skills + _nt setSkill ["aimingAccuracy", _ccrcy]; + _nt setSkill ["aimingShake", _mShk]; + _nt setSkill ["aimingSpeed", _mSpd]; + _nt setSkill ["endurance", _stmna]; + _nt setSkill ["spotDistance", _sptDst]; + _nt setSkill ["spotTime", _sptTme]; + _nt setSkill ["courage", _crge]; + _nt setSkill ["reloadSpeed", _rldSpd]; + _nt setSkill ["commanding", _cmmndng]; + _nt setSkill ["general", _gnrl]; + + _nt enableAI "TARGET"; + _nt enableAI "AUTOTARGET"; + _nt enableAI "MOVE"; + _nt enableAI "ANIM"; + _nt enableAI "TEAMSWITCH"; + _nt enableAI "FSM"; + _nt enableAI "AIMINGERROR"; + _nt enableAI "SUPPRESSION"; + _nt enableAI "CHECKVISIBLE"; + _nt enableAI "COVER"; + _nt enableAI "AUTOCOMBAT"; + _nt enableAI "PATH"; + }; + + _i = [units _grp, _this4, _this3] call VEMFr_fnc_loadInv; // Load the AI's inventory + if isNil "_i" then + { + ["fn_spawnInvasionAI", 0, "failed to load AI's inventory..."] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + _grps pushBack _grp; // Push it into the _grps array + }; + + if (((count _grps) isEqualTo _this1) AND _nHss) then + { + private ["_wypnts","_wp","_cyc"]; + _wypnts = + [ + [(_this0 select 0), (_this0 select 1)+50, 0], + [(_this0 select 0)+50, (_this0 select 1), 0], + [(_this0 select 0), (_this0 select 1)-50, 0], + [(_this0 select 0)-50, (_this0 select 1), 0] + ]; + { // Make them Patrol + for "_z" from 1 to (count _wypnts) do + { + _wp = _x addWaypoint [(_wypnts select (_z-1)), 10]; + _wp setWaypointType "SAD"; + _wp setWaypointCompletionRadius 20; + }; + _cyc = _x addWaypoint [_this0,10]; + _cyc setWaypointType "CYCLE"; + _cyc setWaypointCompletionRadius 20; + } forEach _grps; + }; + } else + { + ["fn_spawnInvasionAI",0,format["'%1' is not in missionList", _this4]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + +_r diff --git a/a3_vemf_reloaded/fn/fn_spawnVEMFrAI.sqf b/a3_vemf_reloaded/fn/fn_spawnVEMFrAI.sqf new file mode 100644 index 0000000..cbac61a --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_spawnVEMFrAI.sqf @@ -0,0 +1,90 @@ +/* + Author: original by Vampire, completely rewritten by IT07 + + Description: + spawns VEMFr AI using given _this0 and unit/group count. Handles their inventory and transfers them to a client + + Params: + _this select 0: POSITION - where to spawn the units around + _this select 1: SCALAR - how many groups to spawn + _this select 2: SCALAR - how many units to put in each group + _this select 3: SCALAR - AI mode + _this select 4: STRING - exact config name of mission + _this select 5: SCALAR - (optional) altitude to create units at + _this select 6: SCALAR - (optional) spawn radius + + Returns: + ARRAY with group(s) +*/ + +private ["_r","_allUnits","_this0","_this1","_this2","_this3","_this4"]; +_allUnits = []; +params [ + ["_this0", [], [[]]], + ["_this1", 1, [0]], + ["_this2", 1, [0]], + ["_this3", -1, [0]], + ["_this4", "", [""]], + ["_this5", 0, [0]], + ["_this6", 20, [0]] +]; + +if ((_this4 in ("missionList" call VEMFr_fnc_config)) OR (_this4 isEqualTo "Static")) then + { + scopeName "outer"; + _r = []; + _this0 = [_this0 select 0, _this0 select 1, _this5]; + private ["_s","_ccrcy","_mshk","_mspd","_stmn","_sptDst","_sptTm","_crg","_rldSpd","_cmmndng","_gnrl","_i","_grp","_unit"]; + + _s = [["aiSkill", ([["aiSkill"],["difficulty"]] call VEMFr_fnc_config) select 0],["accuracy","aimingShake","aimingSpeed","endurance","spotDistance","spotTime","courage","reloadSpeed","commanding","general"]] call VEMFr_fnc_config; + _s params ["_ccrcy","_mshk","_mspd","_stmn","_sptDst","_sptTm","_crg","_rldSpd","_cmmndng","_gnrl"]; + for "_g" from 1 to _this1 do + { + _grp = createGroup ((([[call VEMFr_fnc_whichMod],["unitClass"]] call VEMFr_fnc_config) select 0) call VEMFr_fnc_checkSide); + _grp allowFleeing 0; + for "_u" from 1 to _this2 do + { + _unit = _grp createUnit [(([[call VEMFr_fnc_whichMod],["unitClass"]] call VEMFr_fnc_config) select 0), _this0, [], _this6, "FORM"]; // Create Unit There + _allUnits pushBack _unit; + _unit addMPEventHandler ["mpkilled","if (isDedicated) then { [[(_this select 0),(name(_this select 0))],[(_this select 1),(name(_this select 1))]] ExecVM 'a3_vemf_reloaded\sqf\aiKilled.sqf' }"]; + // Set skills + _unit setSkill ["aimingAccuracy", _ccrcy]; + _unit setSkill ["aimingShake", _mshk]; + _unit setSkill ["aimingSpeed", _mspd]; + _unit setSkill ["endurance", _stmn]; + _unit setSkill ["spotDistance", _sptDst]; + _unit setSkill ["spotTime", _sptTm]; + _unit setSkill ["courage", _crg]; + _unit setSkill ["reloadSpeed", _rldSpd]; + _unit setSkill ["commanding", _cmmndng]; + _unit setSkill ["general", _gnrl]; + + _unit enableAI "TARGET"; + _unit enableAI "AUTOTARGET"; + _unit enableAI "MOVE"; + _unit enableAI "ANIM"; + _unit enableAI "TEAMSWITCH"; + _unit enableAI "FSM"; + _unit enableAI "AIMINGERROR"; + _unit enableAI "SUPPRESSION"; + _unit enableAI "CHECKVISIBLE"; + _unit enableAI "COVER"; + _unit enableAI "AUTOCOMBAT"; + _unit enableAI "PATH"; + }; + _r pushBack _grp; + }; + + _i = [_allUnits, _this4, _this3] call VEMFr_fnc_loadInv; // Load the AI's inventory + if (isNil "_i") then + { + _r = nil; + ["fn_spawnVEMFrAI", 0, "failed to load AI's inventory..."] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + } else + { + ["fn_spawnVEMFrAI", 0, format["'%1' is not in missionList or is not equal to 'Static'", _this4]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + +_r diff --git a/a3_vemf_reloaded/fn/fn_waitForPlayers.sqf b/a3_vemf_reloaded/fn/fn_waitForPlayers.sqf new file mode 100644 index 0000000..204fb64 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_waitForPlayers.sqf @@ -0,0 +1,36 @@ +/* + Author: IT07 + + Description: + fn_waitForPlayers - waits for player to be nearby given pos + + Params: + _this select 0: POSITION - center of area to check for players + _this select 1: SCALAR - radius to check around POSITION + + Returns: + BOOL - true if there is a player present +*/ + +private ["_r","_this0","_this1"]; +params [ + ["_this0", [], [[]]], + ["_this1", -1, [0]] +]; + +_r = false; +if ([_this0, _this1] call VEMFr_fnc_playerNear) then + { + _r = true; + } else + { + private ["_t","_tot"]; + _t = round time; + _tot = ("timeOutTime" call VEMFr_fnc_config)*60; + waitUntil { if (([_this0, _this1] call VEMFr_fnc_playerNear) OR (round time - _t > _tot)) then {true} else {uiSleep 4; false} }; + if ([_this0, _this1] call VEMFr_fnc_playerNear) then + { + _r = true; + }; + }; +_r diff --git a/a3_vemf_reloaded/fn/fn_whichMod.sqf b/a3_vemf_reloaded/fn/fn_whichMod.sqf new file mode 100644 index 0000000..14eb338 --- /dev/null +++ b/a3_vemf_reloaded/fn/fn_whichMod.sqf @@ -0,0 +1,16 @@ +/* + Author: IT07 + + Description: + returns the current server mod (Exile or Epoch) + + Returns: + STRING - the name of the current server mod +*/ + +private "_r"; + +if not(isNull(configFile >> "CfgPatches" >> "exile_server")) then { _r = "Exile" }; +if not(isNull(configFile >> "CfgPatches" >> "a3_epoch_server")) then { _r = "Epoch" }; + +_r diff --git a/a3_vemf_reloaded/missions/BaseAttack.sqf b/a3_vemf_reloaded/missions/BaseAttack.sqf new file mode 100644 index 0000000..16be324 --- /dev/null +++ b/a3_vemf_reloaded/missions/BaseAttack.sqf @@ -0,0 +1,131 @@ +/* + Author: IT07 + + Description: + A simple mission for VEMFr that sends a chopper to a player's territory and paradrops all units inside +*/ + +VEMFrMissionCount = VEMFrMissionCount + 1; +_mn = param [0, "", [""]]; +if (isNil "VEMFrAttackCount") then { VEMFrAttackCount = 0 }; +VEMFrAttackCount = VEMFrAttackCount + 1; +_s = [[_mn],["maxAttacks","aiSetup","minimumLevel"]] call VEMFr_fnc_config; +_s params ["_s0","_s1","_s2"]; +if (VEMFrAttackCount <= _s0) then +{ + scopeName "outer"; + if (_mn in ("missionList" call VEMFr_fnc_config)) then + { + if (((_s1 select 0) > 0) AND ((_s1 select 1) > 0)) then + { + _hst = uiNamespace getVariable ["VEMFrAttackedFlags",[]]; + _objs = []; + { + if (((speed _x) < 25) AND ((vehicle _x) isEqualTo _x)) then + { + { + if (not(_x in _hst) AND ((_x getVariable ["ExileTerritoryLevel",0]) > _s2)) then { _objs pushBack _x }; + } forEach (nearestObjects [position _x, ["Exile_Construction_Flag_Static"], 150]); + }; + } forEach allPlayers; + + if (count _objs > 0) then + { + _flg = selectRandom _objs; + _hst pushBack _flg; + _pos = position _flg; + _nrPlyr = selectRandom (nearestObjects [_pos, ["Exile_Unit_Player"], 150]); + if not(isNil "_nrPlyr") then + { + _flgNm = _flg getVariable ["exileterritoryname", "ERROR: UNKNOWN NAME"]; + _prGrps = [_pos, _s1 select 0, _s1 select 1, ([[_mn],["aiMode"]] call VEMFr_fnc_config select 0), _mn, 1000 + (random 1000), 150] call VEMFr_fnc_spawnVEMFrAI; + if not(isNil "_prGrps") then + { + _ntCnt = 0; + { + if (count (units _x) isEqualTo (_s1 select 1)) then + { + _ntCnt = _ntCnt + (count(units _x)); + }; + } forEach _prGrps; + if (_ntCnt isEqualTo ((_s1 select 0) * (_s1 select 1))) then + { + _wyPnts = []; + _nts = []; + { + _wp = _x addWaypoint [_pos, 50, 1]; + _wp setWaypointBehaviour "COMBAT"; + _wp setWaypointCombatMode "RED"; + _wp setWaypointCompletionRadius 10; + _wp setWaypointFormation "DIAMOND"; + _wp setWaypointSpeed "FULL"; + _wp setWaypointType "SAD"; + _x setCurrentWaypoint _wp; + _wyPnts pushback _wp; + { + _nts pushback _x; + } forEach (units _x); + [_x] ExecVM "a3_vemf_reloaded\sqf\signAI.sqf"; + } forEach _prGrps; + _plyrs = nearestObjects [_pos, ["Exile_Unit_Player"], 275]; + [-1, "NEW BASE ATTACK", format["A para team is on the way to %1 @ %2's location!", _flgNm, name _nrPlyr], _plyrs] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + ["BaseAttack", 1, format["A para team is on the way to %1 @ %2's location!", _flgNm, name _nrPlyr]] ExecVM ("log" call VEMFr_fnc_scriptPath); + + while {true} do + { + scopeName "loop"; + _ddCnt = 0; + { + if (damage _x isEqualTo 1 OR isNull _x) then + { + _ddCnt = _ddCnt + 1; + }; + } forEach _nts; + if (_ddCnt isEqualTo _ntCnt) then + { + breakOut "loop"; + } else + { + uiSleep 4; + }; + }; + _plyrs = nearestObjects [_pos, ["Exile_Unit_Player"], 275]; + [-1, "DEFEATED", format["Base attack on %1 has been defeated!", _flgNm], _plyrs] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + breakOut "outer"; + } else + { + { + { + deleteVehicle _x; + } forEach (units _x); + } forEach _prGrps; + ["BaseAttack", 0, format["Incorrect amount of total units (%1). Should be %2", _ntCnt, (_s1 select 0) * (_s1 select 1)]] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + } else + { + ["BaseAttack", 0, format["Incorrect spawned group count (%1). Should be %2", count _prGrps, _s1 select 0]] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + } else + { + _hst deleteAt (_hst find _flg); + ["BaseAttack", 0, "Can not find player near flag!"] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + } else + { + breakOut "outer"; + }; + } else + { + ["BaseAttack", 0, format["invalid aiSetup setting! (%1)", _s1]] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + } else + { + ["BaseAttack", 0, format["Failed to start mission. Given _mn (%1) is not in active missionList", _mn]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; +}; +VEMFrAttackCount = VEMFrAttackCount - 1; +VEMFrMissionCount = VEMFrMissionCount - 1; diff --git a/a3_vemf_reloaded/missions/DynamicLocationInvasion.sqf b/a3_vemf_reloaded/missions/DynamicLocationInvasion.sqf new file mode 100644 index 0000000..d57afbe --- /dev/null +++ b/a3_vemf_reloaded/missions/DynamicLocationInvasion.sqf @@ -0,0 +1,362 @@ +/* + DynamicLocationInvasion by IT07 +*/ + +VEMFrMissionCount = VEMFrMissionCount + 1; +if isNil "VEMFrInvasionCount" then { VEMFrInvasionCount = 0; }; +VEMFrInvasionCount = VEMFrInvasionCount + 1; +_this0 = param [0, "", [""]]; +if (VEMFrInvasionCount <= (([[_this0],["maxInvasions"]] call VEMFr_fnc_config) select 0)) then +{ + scopeName "outer"; + _mod = call VEMFr_fnc_whichMod; + + // Define the settings + _ms = [ + [_this0], + ["groupCount","groupUnits","maxDistancePrefered","skipDistance","useMarker","markCrateVisual","markCrateOnMap","announce","streetLights","streetLightsRestore","streetLightsRange","allowCrateLift","allowRepeat","randomModes","spawnCrateFirst","mines","flairTypes","smokeTypes","minesCleanup","skipDistanceReversed"] + ] call VEMFr_fnc_config; + _ms params [ + "_ms0","_ms1","_ms2","_ms3","_ms4","_ms5","_ms6","_ms7","_ms8","_ms9","_ms10","_ms11","_ms12","_ms13","_ms14","_ms15","_ms16","_ms17","_ms18","_ms19" + ]; + + ([[_this0,"crateParachute"],["enabled","altitude"]] call VEMFr_fnc_config) params ["_cp0","_cp1"]; + + _l = ["loc", false, position (selectRandom allPlayers), if (_ms19 > 0) then {_ms19} else {_ms3}, _ms2, if (_ms19 > 0) then {_ms19} else {_ms3}, _this0] call VEMFr_fnc_findPos; + if not(isNil "_l") then + { + _ln = text _l; + _lp = position _l; + if (_ln isEqualTo "") then { _ln = "Area"; }; + [_this0, 1, format["Invading %1...", _ln]] ExecVM ("log" call VEMFr_fnc_scriptPath); + + _m = ([[_mod],["aiMode"]] call VEMFr_fnc_config) select 0; + if (_ms13 isEqualTo 1) then { _m = selectRandom [0,1]; if ((call VEMFr_fnc_whichMod) isEqualTo "Exile") then { _m pushBack 2 } }; + if (_ms7 isEqualTo 1) then + { + if (_m isEqualTo 0) then { [_m, "NEW INVASION", format["Raiders have invaded %1 @ %2", _ln, mapGridPosition _lp]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf" }; + if (_m isEqualTo 1) then { [_m, "NEW POLICE RAID", format["%1 Police forces are now controlling %2 @ %3", worldName, _ln, mapGridPosition _lp]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf" }; + if (_m isEqualTo 2) then { [_m, "NEW S.W.A.T. RAID", format["%1 S.W.A.T. teams are now raiding %2 @ %3", worldName, _ln, mapGridPosition _lp]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf" }; + }; + + private "_mrkr"; + if (_ms4 isEqualTo 1) then + { // Create/place the marker if enabled + _mrkr = createMarker [format["VEMFr_DynaLocInva_ID%1", random 9000], _lp]; + _mrkr setMarkerShape "ICON"; + _mrkr setMarkerType "o_unknown"; + _mrkr setMarkerSize [0.85,0.85]; + + if (_m < 0 OR _m > 2) then + { + ["DynamicLocationInvasion", 0, format["Invalid aiMode (%1) detected, failed to setMarkerColor!", _m]] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + if (_m isEqualTo 0) then { _mrkr setMarkerColor "ColorEAST" }; + if (_m isEqualTo 1) then { _mrkr setMarkerColor "ColorWEST" }; + if (_m isEqualTo 2) then { _mrkr setMarkerColor "ColorBlack" }; + }; + + // If enabled, kill all the lights + if (_ms8 isEqualTo 0) then + { + { + if (damage _x < 0.95) then + { + _x setDamage 0.95; + uiSleep 0.1; + }; + } forEach (nearestObjects [_lp, ["Lamps_Base_F","PowerLines_base_F","Land_PowerPoleWooden_L_F"], _ms10]); + }; + + private "_crate"; + _dSpwnCrt = { + // Choose a box + _bx = selectRandom (([[_this0],["crateTypes"]] call VEMFr_fnc_config) select 0); + _ps = [_lp, 0, 200, 0, 0, 300, 0] call bis_fnc_findSafePos; + if (_cp0 > 0) then + { + _cht = createVehicle ["I_Parachute_02_F", _ps, [], 0, "FLY"]; + if (_mod isEqualTo "Epoch") then { _cht call EPOCH_server_setVToken }; + _cht setPos [getPos _cht select 0, getPos _cht select 1, _cp1]; + _cht enableSimulationGlobal true; + + if not(isNull _cht) then + { + _crate = createVehicle [_bx, getPos _cht, [], 0, "NONE"]; + _crate allowDamage false; + _crate enableSimulationGlobal true; + _crate attachTo [_cht, [0,0,0]]; + [_this0, 1, format ["Crate parachuted at: %1 / Grid: %2", (getPosATL _crate), mapGridPosition (getPosATL _crate)]] ExecVM ("log" call VEMFr_fnc_scriptPath); + [_crate, _ln, _lp] ExecVM "a3_vemf_reloaded\sqf\loadLoot.sqf"; + waitUntil { if (((getPos _crate) select 2) < 7) then {true} else {uiSleep 1; false} }; + detach _crate; + } else + { + [_this0, 0, "Where is the chute??"] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } else + { + _crate = createVehicle [_bx, _ps, [], 0, "NONE"]; + _crate allowDamage false; + [_crate, _ln, _lp] ExecVM "a3_vemf_reloaded\sqf\loadLoot.sqf"; + }; + + if (_ms11 > 0) then { _crate enableRopeAttach false } else { _crate enableRopeAttach true }; + }; + + if ([_lp, 800] call VEMFr_fnc_waitForPlayers) then + { + _spwnd = [_lp, ((_ms0 select 0) + round random ((_ms0 select 1) - (_ms0 select 0))), ((_ms1 select 0) + round random ((_ms1 select 1) - (_ms1 select 0))), _m, _this0, 200] call VEMFr_fnc_spawnInvasionAI; + _nts = []; + { + [_x] ExecVM "a3_vemf_reloaded\sqf\signAI.sqf"; + { + _nts pushBack _x; + } forEach (units _x); + } forEach (_spwnd select 0); + + _cl50s = _spwnd select 1; + + ([[_this0,"heliPatrol"],["enabled","classes","locked"]] call VEMFr_fnc_config) params ["_hp0","_hp1","_hp2"]; + if (_hp0 > 0) then + { + [_this0, 1, format["Adding a heli patrol to the invasion of %1 at %2", _ln, mapGridPosition _lp]] ExecVM ("log" call VEMFr_fnc_scriptPath); + _heli = createVehicle [(selectRandom _hp1), _lp, [], 5, "FLY"]; + if (_mod isEqualTo "Epoch") then { _heli call EPOCH_server_setVToken }; + _heli setPosATL [(getPos _heli) select 0, (getPos _heli) select 1, 750]; + _heli flyInHeight 80; + if (_hp2 isEqualTo 1) then + { + _heli lock true; + }; + + _trrts = allTurrets [_heli, false]; + + _hlGrp = ([_lp, 1, ((count _trrts) + (_heli emptyPositions "commander") + 1), _m, _this0] call VEMFr_fnc_spawnVEMFrAI) select 0; + { + if (((_heli emptyPositions "driver") isEqualTo 1) AND (_x isEqualTo (leader(group _x)))) then + { + _x moveInDriver _heli; + } else + { + private "_path"; + { + if (isNull (_heli turretUnit _x)) then + { + _path = _x; + }; + } forEach _trrts; + + if not(isNil "_path") then + { + _x moveInTurret [_heli, _path]; + } else + { + if ((_heli emptyPositions "commander") > 0) then + { + _x moveInCommander _heli; + }; + }; + }; + + if not(backPack _x isEqualTo "") then + { + removeBackpack _x; + }; + _x addBackpack "B_Parachute"; + _nts pushBack _x; + } forEach (units _hlGrp); + + _wp = _hlGrp addWaypoint [[_lp select 0, _lp select 1, 50], 0, 2]; + _wp setWaypointType "SAD"; + _wp setWaypointSpeed "NORMAL"; + _wp setWaypointBehaviour "AWARE"; + _wp setWaypointCombatMode "RED"; + //_wp setWaypointLoiterType "CIRCLE"; + //_wp setWaypointLoiterRadius 200; + _hlGrp setCurrentWaypoint _wp; + + [_hlGrp] ExecVM "a3_vemf_reloaded\sqf\signAI.sqf"; + }; + + // Place the crate if enabled + if (_ms14 isEqualTo 1) then + { + call _dSpwnCrt; + }; + + // Place mines if enabled + private ["_mnsPlcd","_mines"]; + if (_ms15 > 0) then + { + _mnsPlcd = [_lp, 5, 100, _this0] call VEMFr_fnc_mines; + if ((count _mnsPlcd) > 0) then + { + [_this0, 1, format["%1 mines placed at %2", count _mnsPlcd, _ln]] ExecVM ("log" call VEMFr_fnc_scriptPath); + } else + { + [_this0, 0, format["Failed to place %1 mines at %2", count _mnsPlcd, _ln]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + }; + + // Wait for Mission Completion + _h = [_nts] ExecVM "a3_vemf_reloaded\sqf\killedMonitor.sqf"; + waitUntil { if (scriptDone _h) then {true} else {uiSleep 1; false} }; + + ["DynamicLocationInvasion", 1, format["mission in %1 has been completed!", _ln]] ExecVM ("log" call VEMFr_fnc_scriptPath); + + if (_ms12 isEqualTo 1) then + { + _u = uiNamespace getVariable "VEMFrUsedLocs"; + _u deleteAt (_u find _l); + }; + + // Broadcast + if (_ms7 isEqualTo 1) then + { + if (_m isEqualTo 0) then + { + [_m ,"RAIDERS KILLED", format["%1 @ %2 is now clear of %3 raiders", _ln, mapGridPosition (_lp), worldName]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + }; + if (_m isEqualTo 1) then + { + [_m, "RAID ENDED", format["%1 @ %2 is now clear of %3 Police", _ln, mapGridPosition (_lp), worldName]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + }; + if (_m isEqualTo 2) then + { + [_m, "S.W.A.T. RAID ENDED", format["%1 @ %2 is now clear of %3 S.W.A.T. teams", _ln, mapGridPosition (_lp)]] ExecVM "a3_vemf_reloaded\sqf\notificationToClient.sqf"; + }; + }; + + // Deal with the 50s + if not(isNil "_cl50s") then + { + _d = ([[_this0],["cal50sDelete"]] call VEMFr_fnc_config) select 0; + if (_d > 0) then + { + { + if (_d isEqualTo 1) then { deleteVehicle _x }; + if (_d isEqualTo 2) then { _x setDamage 1 }; + } forEach _cl50s; + }; + }; + + if not(isNil "_mrkr") then + { + deleteMarker _mrkr + }; + + if ((([["DynamicLocationInvasion"],["spawnCrateFirst"]] call VEMFr_fnc_config) select 0) isEqualTo 0) then + { + call _dSpwnCrt; + }; + + // Put a marker on the crate if enabled + if not(isNil "_crate") then + { + if not(isNull _crate) then + { + if not ([getPos _crate, 3] call VEMFr_fnc_playerNear) then + { + if (_ms5 isEqualTo 1) then + { + // If night, attach a chemlight + if (sunOrMoon <= 0.35) then + { + [_this0, 1, "attaching a chemlight to the _crate"] ExecVM ("log" call VEMFr_fnc_scriptPath); + _lightType = selectRandom _ms16; + (_lightType createVehicle (position _crate)) attachTo [_crate,[0,0,0]]; + } else + { + [_this0, 1, "attaching smoke to the _crate"] ExecVM ("log" call VEMFr_fnc_scriptPath); + // Attach smoke + _rndmColor = selectRandom _ms17; + (createVehicle [_rndmColor, getPos _crate, [], 0, "CAN_COLLIDE"]) attachTo [_crate,[0,0,0]]; + }; + }; + + if (_ms6 isEqualTo 1) then + { + private "_mrkr"; + _mrkr = createMarker [format["VEMF_lootCrate_ID%1", random 9000], position _crate]; + _mrkr setMarkerShape "ICON"; + _mrkr setMarkerType "mil_box"; + _mrkr setMarkerColor "colorBlack"; + _mrkr setMarkerText " Loot"; + [_crate, _mrkr] spawn + { + _crate = _this select 0; + _mrkr = _this select 1; + waitUntil { if ([getPos _crate, 3] call VEMFr_fnc_playerNear) then {true} else {uiSleep 4; false} }; + deleteMarker _mrkr; + }; + }; + }; + } else + { + [_this0, 0, "isNull _crate!"] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + } else + { + [_this0, 0, "isNil _crate!"] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + + + // Explode or remove the mines + if not(isNil "_mnsPlcd") then + { + if (_ms18 isEqualTo 2) then + { + [_this0, _ln, _mnsPlcd] spawn + { + uiSleep (5 + (random 2)); + [(_this select 0), 1, format["Starting to explode all %1 mines at %2", count (_this select 2), (_this select 1)]] ExecVM ("log" call VEMFr_fnc_scriptPath); + { + if not(isNull _x) then + { + _x setDamage 1; + uiSleep (1.25 + (random 3.5)); + }; + } forEach (_this select 2); + [(_this select 0), 1, format["Successfully exploded all %1 mines at %2", count (_this select 2), (_this select 1)]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + + _mnsPlcd = nil; + }; + if (_ms18 isEqualTo 1) then + { + [_mnsPlcd] spawn + { + { + if not(isNull _x) then { deleteVehicle _x }; + } forEach (_this select 0); + }; + + [_this0, 1, format["Successfully deleted all %1 mines at %2", count _mnsPlcd, _ln]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + }; + + // If enabled, fix all the lights + if (_ms9 isEqualTo 1) then + { + { + if (damage _x > 0.94) then + { + _x setDamage 0; + uiSleep (1 + (random 2)); + }; + } forEach (nearestObjects [_lp, ["Lamps_Base_F","PowerLines_base_F","Land_PowerPoleWooden_L_F"], _ms10]); + }; + } else + { // If done waiting, and no players were detected + [_this0, 1, format["Invasion of %1 @ %2 timed out.", _ln, mapGridPosition _lp]] ExecVM ("log" call VEMFr_fnc_scriptPath); + if not(isNil "_mrkr") then { deleteMarker _mrkr }; + _arr = uiNamespace getVariable "VEMFrUsedLocs"; + _arr deleteAt (_arr find _l); + }; + }; +}; + +VEMFrInvasionCount = VEMFrInvasionCount - 1; +VEMFrMissionCount = VEMFrMissionCount - 1; diff --git a/a3_vemf_reloaded/sqf/REMOTEguard.sqf b/a3_vemf_reloaded/sqf/REMOTEguard.sqf new file mode 100644 index 0000000..019a7c1 --- /dev/null +++ b/a3_vemf_reloaded/sqf/REMOTEguard.sqf @@ -0,0 +1,37 @@ +/* + Author: IT07 + + Description: + this function makes sure that AI spawned by VEMF does NOT become local to the server. + On detection of a local group, it will reassign it to a client or Headless Client if enabled. + + Params: + none, this is a Standalone function + + Returns: + nothing +*/ + +while {true} do + { + if ((count playableUnits) > 0) then + { + waitUntil {if ((count allGroups) > 0) then {uiSleep 0.25; true} else {uiSleep 0.5; false} }; + { + if ((local _x) AND (_x getVariable ["isVEMFrGroup",false])) then + { + if ((count (units _x)) > 0) then + { + //["REMOTEguard",1,format["Attempting to transfer group: %1", _x]] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + // Group still has units, check if there is anyone that can be the owner + _h = [_x] ExecVM "a3_vemf_reloaded\sqf\setGroupOwner.sqf"; + waitUntil { if (scriptDone _h) then {true} else {uiSleep 0.1; false} }; + //["REMOTEguard",1,format["Transfer attempted. Group (%1) is %2", _x, if (local _x) then {"still local!"} else {"now REMOTE"}]] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + } else + { + deleteGroup _x; + }; + }; + } forEach allGroups; + } else { uiSleep 5 }; + }; diff --git a/a3_vemf_reloaded/sqf/aiKilled.sqf b/a3_vemf_reloaded/sqf/aiKilled.sqf new file mode 100644 index 0000000..54b1cea --- /dev/null +++ b/a3_vemf_reloaded/sqf/aiKilled.sqf @@ -0,0 +1,263 @@ +/* + Author: IT07 + + Description: + executed upon AI unit death + + Params: + _this: ARRAY + _this select 0: OBJECT - the killed AI + _this select 1: OBJECT - killer + + Returns: + nothing +*/ + +(_this select 0) params [ + ["_t", objNull, [objNull]], + ["_nt", "", [""]] +]; +(_this select 1) params [ + ["_k", objNull, [objNull]], + ["_nk", "", [""]] +]; + +if (isPlayer _k) then + { + scopeName "isPlayer"; + _mod = call VEMFr_fnc_whichMod; + private ["_rspct","_crpt"]; + if (_mod isEqualTo "Exile") then + { + _rspct = + { + _ffct = + { + [_k, "showFragRequest", _arr] call ExileServer_system_network_send_to; + _rspct = (_k getVariable ["ExileScore", 0]) + (((_arr select 0) select 1) select 1) + _rw; + _k setVariable ["ExileScore", _rspct]; + ExileClientPlayerScore = _rspct; + (owner _k) publicVariableClient "ExileClientPlayerScore"; + ExileClientPlayerScore = nil; + + _kllCnt = (_k getVariable ["ExileKills",0]) + 1; + _k setVariable ["ExileKills", _kllCnt]; + ExileClientPlayerKills = _kllCnt; + (owner _k) publicVariableClient "ExileClientPlayerKills"; + ExileClientPlayerKills = nil; + + format["addAccountKill:%1", getPlayerUID _k] call ExileServer_system_database_query_fireAndForget; + format['setAccountScore:%1:%2', _rspct, getPlayerUID _k] call ExileServer_system_database_query_fireAndForget; + }; + + _arr = [[]]; + (_arr select 0) pushBack [(selectRandom ["AI WACKED","AI CLIPPED","AI WIPED","AI ERASED","AI LYNCHED","AI WRECKED","AI SNUFFED","AI WASTED","AI ZAPPED"]), _rw]; + _dist = _t distance _k; + if (_dist < 2500) then + { + scopeName "dist"; + if (_dist <= 5) then + { + (_arr select 0) pushBack ["CQB Master", 25]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 10) then + { + (_arr select 0) pushBack ["Close one", 15]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 50) then + { + (_arr select 0) pushBack ["Danger close", 15]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 100) then + { + (_arr select 0) pushBack ["Lethal aim", 20]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 200) then + { + (_arr select 0) pushBack ["Deadly.", 25]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 500) then + { + (_arr select 0) pushBack ["Niiiiice.", 30]; + call _ffct; + breakOut "dist"; + }; + if (_dist <= 1000) then + { + (_arr select 0) pushBack ["Dat distance...", 45]; + breakOut "dist"; + }; + if (_dist <= 2000) then + { + (_arr select 0) pushBack ["Danger far.", 50]; + breakOut "dist"; + }; + if (_dist > 2000) then + { + (_arr select 0) pushBack [format["hax? %1m!!!", round _dist], 65]; + breakOut "dist"; + }; + }; + }; + }; + + if (_mod isEqualTo "Epoch") then + { + _crpt = + { + _ffct = + { + _vrs = _k getVariable ["VARS", nil]; + _crptId = EPOCH_customVars find "Crypto"; + _nwCrpt = (_vrs select _crptId) + _rwrd + (([[_mod],["cryptoReward"]] call VEMFr_fnc_config) select 0); + _vrs set [_crptId, _nwCrpt]; + _k setVariable ["VARS", _vrs]; + _nwCrpt remoteExec ['EPOCH_effectCrypto', owner _k]; + }; + + _rwrd = 0; + _dist = _t distance _k; + if (_dist < 2500) then + { + scopeName "dist"; + if (_dist <= 5) then { _rwrd = 25; call _ffct; breakOut "dist" }; + if (_dist <= 10) then { _rwrd = 15; call _ffct; breakOut "dist" }; + if (_dist <= 50) then { _rwrd = 15; call _ffct; breakOut "dist" }; + if (_dist <= 100) then { _rwrd = 20; call _ffct; breakOut "dist" }; + if (_dist <= 200) then { _rwrd = 25; call _ffct; breakOut "dist" }; + if (_dist <= 500) then { _rwrd = 30; call _ffct; breakOut "dist" }; + if (_dist <= 1000) then { _rwrd = 45; call _ffct; breakOut "dist" }; + if (_dist <= 2000) then { _rwrd = 50; call _ffct; breakOut "dist" }; + if (_dist > 2000) then { _rwrd = 65; call _ffct; breakOut "dist" }; + }; + }; + }; + + _rw = ([["Exile"],["respectReward"]] call VEMFr_fnc_config) select 0; + _cw = ([["Epoch"],["cryptoReward"]] call VEMFr_fnc_config) select 0; + _sk = "sayKilled" call VEMFr_fnc_config; + + if (_k isKindOf "Man") then // Roadkill or regular kill + { + if (vehicle _k isEqualTo _k) then // If on foot + { + if (vehicle _t isEqualTo _t) then + { + if ((_mod isEqualTo "Exile") AND (_rw > 0)) then { call _rspct }; + if ((_mod isEqualTo "Epoch") AND (_cw > 0)) then { call _crpt }; + if (_sk isEqualTo 1) then { [[_t, _nt],[_k, _nk]] ExecVM "a3_vemf_reloaded\sqf\sayKilledWeapon.sqf" }; + } else + { + if (typeOf (vehicle _t) isEqualTo "Steerable_Parachute_F") then + { + if ("logCowardKills" call VEMFr_fnc_config isEqualTo 1) then + { + ["fn_aiKilled", 1, format["A coward (%1 @ %2) killed a parachuting AI", _nk, mapGridPosition _k]] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + }; + } else + { + if ((_mod isEqualTo "Exile") AND (_rw > 0)) then { call _rspct }; + if ((_mod isEqualTo "Epoch") AND (_cw > 0)) then { call _crpt }; + if (_sk isEqualTo 1) then { [[_t, _nt],[_k, _nk]] ExecVM "a3_vemf_reloaded\sqf\sayKilledWeapon.sqf" }; + }; + }; + } else // If in vehicle (a.k.a. roadkill) + { + if (("punishRoadKills" call VEMFr_fnc_config) isEqualTo 1) then + { + if (_mod isEqualTo "Exile") then + { + _pnsh = ([["Exile"],["respectRoadKillDeduct"]] call VEMFr_fnc_config) select 0; + //diag_log text format["_crRspct of _k (%1) is %2", _k, _crRspct]; + _nwRspct = (_k getVariable ["ExileScore", 0]) - _pnsh; + _k setVariable ["ExileScore", _nwRspct]; + ExileClientPlayerScore = _nwRspct; + (owner _k) publicVariableClient "ExileClientPlayerScore"; + ExileClientPlayerScore = nil; + [_k, "showFragRequest", [[["ROADKILL..."],["Penalty:", -_pnsh]]]] call ExileServer_system_network_send_to; + format['setAccountScore:%1:%2', _nwRspct, getPlayerUID _k] call ExileServer_system_database_query_fireAndForget; + + if (("sayKilled" call VEMFr_fnc_config) isEqualTo 1) then { [format["(VEMFr) %1 [Roadkill] %2", _nk, if (("sayKilledName" call VEMFr_fnc_config) > 0) then {_nt} else {"AI"}]] ExecVM "a3_vemf_reloaded\sqf\systemChatToClient.sqf" }; + }; + + if (_mod isEqualTo "Epoch") then + { + _vrs = _k getVariable ["VARS", nil]; + _crptId = EPOCH_customVars find "Crypto"; + _nwCrpt = (_vrs select _crptId) - (([["Epoch"],["cryptoRoadKillPunish"]] call VEMFr_fnc_config) select 0); + _vrs set [_crptId, _nwCrpt]; + _k setVariable ["VARS", _vrs]; + _nwCrpt remoteExec ['EPOCH_effectCrypto', owner _k]; + }; + }; + }; + } else // If kill from vehicle (NOT a roadkill) + { + if ((typeOf (vehicle _t)) isEqualTo "Steerable_Parachute_F") then + { + if ("logCowardKills" call VEMFr_fnc_config isEqualTo 1) then + { + ["fn_aiKilled", 1, format["A coward (%1 @ %2) killed a parachuting AI", _nk, mapGridPosition _k]] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + }; + } else + { + _k = effectiveCommander _k; + if ((_mod isEqualTo "Exile") AND (_rw > 0)) then { call _rspct }; + if ((_mod isEqualTo "Epoch") AND (_cw > 0)) then { call _crpt }; + if (_sk isEqualTo 1) then { [[_t, _nt],[_k, _nk]] ExecVM "a3_vemf_reloaded\sqf\sayKilledWeapon.sqf" }; + }; + }; + }; + + ([["aiCleanup"],["removeLaunchers","aiDeathRemovalEffect","removeHeadGear"]] call VEMFr_fnc_config) params ["_ms0","_ms1","_ms2"]; + if (_ms0 isEqualTo 1) then + { + _sw = secondaryWeapon _t; + if not(_sw isEqualTo "") then + { + _t removeWeaponGlobal _sw; + _mssls = getArray (configFile >> "cfgWeapons" >> _sw >> "magazines"); + { + if (_x in _mssls) then + { + _t removeMagazineGlobal _x; + }; + } forEach (magazines _t); + }; + }; + if (_ms2 isEqualTo 1) then // If removeHeadGear setting is enabled + { + removeHeadGear _t; + }; + + if (_ms1 isEqualTo 1) then // If killEffect enabled + { + playSound3D ["A3\Missions_F_Bootcamp\data\sounds\vr_shutdown.wss", _t, false, getPosASL _t, 2, 1, 60]; + for "_u" from 1 to 12 do + { + if not(isObjectHidden _t) then + { + _t hideObjectGlobal true; + } else + { + _t hideObjectGlobal false; + }; + uiSleep 0.12; + }; + _t hideObjectGlobal true; + removeAllWeapons _t; + // Automatic cleanup yaaay + deleteVehicle _t; + }; + + _t removeAllEventHandlers "MPKilled"; diff --git a/a3_vemf_reloaded/sqf/broadCast.sqf b/a3_vemf_reloaded/sqf/broadCast.sqf new file mode 100644 index 0000000..81bec65 --- /dev/null +++ b/a3_vemf_reloaded/sqf/broadCast.sqf @@ -0,0 +1,60 @@ +/* + Author: IT07 + + Description: + will alert players + + Params: + for global(!) systemChat message: + _this select 0: FORMATTED STRING - thing to send + _this select 1: ARRAY - objects to send message to. If empty, broadcast will go to all players + _this select 2: STRING - must be "sys" + for mission announcement: + _this: ARRAY + _this select 0: ARRAY + _this select 0 select 0: SCALAR - broadcast type (determines the color of the message icon) + _this select 0 select 1: STRING - announcement title + _this select 0 select 2: FORMATTED STRING - Message line + _this select 1: ARRAY - objects to send message to. If empty, broadcast will go to all players + _this select 2: STRING - (optional) must be empty or nil | for systemChat broadcast, use "sys" + + Returns: + nothing +*/ + +_send = + { + private "_arr"; + if (count _this isEqualTo 0) then + { + _arr = allPlayers; + } else + { + _arr = _this; + }; + { + if (isPlayer _x AND alive _x) then + { + VEMFrMsgToClient = [_msg, _mode]; + (owner _x) publicVariableClient "VEMFrMsgToClient"; + }; + } forEach _arr; + }; + +_to = param [1, [], [[]]]; + +if (_this select 0 isEqualType []) then // mission notification + { + _mode = (_this select 0) param [0, -1, [0]]; + _title = (_this select 0) param [1, "DEFAULT TITLE", [""]]; + _line = (_this select 0) param [2, "Default message", [""]]; + _msg = [_mode, _title, _line]; + _to call _send; + }; + +if (_this select 0 isEqualType "") then // systemchat broadcast + { + _mode = param [2, "", [""]]; + _msg = param [0, "", [""]]; + _to call _send; + }; diff --git a/a3_vemf_reloaded/sqf/checkLoot.sqf b/a3_vemf_reloaded/sqf/checkLoot.sqf new file mode 100644 index 0000000..ae5816a --- /dev/null +++ b/a3_vemf_reloaded/sqf/checkLoot.sqf @@ -0,0 +1,65 @@ +/* + Author: IT07 + + Description: + checks the VEMF loot table for invalid classnames. Reports to RPT if invalid classes found. + + Params: + none + + Returns: + nothing +*/ + +if ("validateLoot" call VEMFr_fnc_config isEqualTo 1) then +{ // _validateLoot is enabled, go ahead... + if ("debugMode" call VEMFr_fnc_config < 1) then + { + ["CheckLoot", 0, "Failed to validate loot: no output allowed in RPT"] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + } else + { + ["CheckLoot", 1, "Validating loot tables..."] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + _bin = []; + + _mags = []; + _cfgMags = "_mags pushBack (configName _x); true" configClasses (configFile >> "cfgMagazines"); + + _weapons = []; + _cfgWeapons = "_weapons pushBack (configName _x); true" configClasses (configFile >> "cfgWeapons"); + + _bags = []; + _cfgBags = "getText (_x >> 'vehicleClass') isEqualTo 'Backpacks'" configClasses (configFile >> "cfgVehicles"); + { + _bags pushBack (configName _x); + } forEach _cfgBags; + + _aiGear = [["aiGear"],["aiUniforms","aiVests","aiRifles","aiBackpacks","aiLaunchers","aiPistols"]] call VEMFr_fnc_config; + { + { + if not((_x in _mags) OR (_x in _weapons) OR (_x in _bags)) then + { + _bin pushBack _x; + }; + } forEach _x; + } forEach _aiGear; + + _loot = [["crateLoot"],["primaryWeaponLoot","secondaryWeaponLoot","magazinesLoot","attachmentsLoot","itemsLoot","vestsLoot","headGearLoot","backpacksLoot"]] call VEMFr_fnc_config; + { + { + _class = _x select 0; + if not((_class in _mags) OR (_class in _weapons) OR (_class in _bags)) then + { + _bin pushBack _x; + }; + } forEach _x; + } forEach _loot; + + if (count _bin isEqualTo 0) then + { + ["CheckLoot", 1, "Loot tables are all valid :)"] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + } else + { + ["CheckLoot", 0, format["Invalid classes found in loot! | %1", _bin]] ExecVM "a3_vemf_reloaded\sqf\log.sqf"; + }; + }; +}; diff --git a/a3_vemf_reloaded/sqf/killedMonitor.sqf b/a3_vemf_reloaded/sqf/killedMonitor.sqf new file mode 100644 index 0000000..4fcd61a --- /dev/null +++ b/a3_vemf_reloaded/sqf/killedMonitor.sqf @@ -0,0 +1,35 @@ +/* + Author: IT07 + + Description: + will loop until all given objects are dead + + Params: + _this select 0: ARRAY - array of objects to monitor + + Returns: + nothing +*/ + +_a = param [0,[],[[]]]; +if ((count _a) > 0) then + { + _k = 0; + _cnt = count _a; + _kp = round(("killPercentage" call VEMFr_fnc_config)/100*_cnt); + while {true} do + { + scopeName "while"; + _k = 0; + { + if (((damage _x) isEqualTo 1) OR (isNull _x)) then { _k = _k + 1 }; + } forEach _a; + if (_k < _kp) then + { + uiSleep 3; + } else + { + breakOut "while"; + }; + }; + }; diff --git a/a3_vemf_reloaded/sqf/loadLoot.sqf b/a3_vemf_reloaded/sqf/loadLoot.sqf new file mode 100644 index 0000000..9614fc1 --- /dev/null +++ b/a3_vemf_reloaded/sqf/loadLoot.sqf @@ -0,0 +1,122 @@ +/* + Author: IT07 + + Description: + loads loot crate inventory + + Params: + _this: ARRAY + _this select 0: OBJECT - the crate + _this select 1: STRING - (optional) name of the location where crate is + _this select 2: ARRAY - (optional) position of location where crate is + + Returns: + nothing +*/ + +params [ + ["_crate", objNull, [objNull]], + ["_locName", "", [""]], + ["_locPos", [], [[]]] +]; + +_crate setVariable ["isVEMFrCrate", 1, true]; +clearBackpackCargoGlobal _crate; +clearItemCargoGlobal _crate; +clearMagazineCargoGlobal _crate; +clearWeaponCargoGlobal _crate; + +_ms = [ + ["crateLoot"], + [ + "primarySlotsMax","primarySlotsMin","secondarySlotsMax","secondarySlotsMin","magSlotsMax","magSlotsMin","attSlotsMax","attSlotsMin","itemSlotsMax","itemSlotsMin", + "vestSlotsMax","vestSlotsMin","headGearSlotsMax","headGearSlotsMin","bagSlotsMax","bagSlotsMin","primaryWeaponLoot","secondaryWeaponLoot","magLoot","attLoot", + "itemLoot","vestLoot","backpackLoot","headGearLoot","blackListLoot" + ] +] call VEMFr_fnc_config; +_ms params [ + "_maxPrim","_minPrim","_maxSec","_minSec","_maxMagSlots","_minMagSlots","_maxAttSlots","_minAttSlots","_maxItemSlots","_minItemSlots","_maxVestSlots","_minVestSlots", + "_maxHeadGearSlots","_minHeadGearSlots","_maxBagSlots","_minBagSlots","_primaries","_secondaries","_magazines","_attachments","_items","_vests","_backpacks","_headGear","_blackList" +]; + +// Add primary weapons +for "_j" from 0 to (_maxPrim - _minPrim + floor random _minPrim) do + { + _g = _primaries call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addWeaponCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Secondary weapons +for "_j" from 0 to (_maxSec - _minSec + floor random _minSec) do + { + _g = _secondaries call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addWeaponCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Magazines +for "_j" from 0 to (_maxMagSlots - _minMagSlots + floor random _minMagSlots) do + { + _g = _magazines call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addMagazineCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Weapon attachments +for "_j" from 0 to (_maxAttSlots - _minAttSlots + floor random _minAttSlots) do + { + _g = _attachments call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addItemCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Items +for "_j" from 0 to (_maxItemSlots - _minItemSlots + floor random _minItemSlots) do + { + _g = _items call BIS_fnc_selectRandom; + if not((_g select 0) in _blacklist) then + { + _crate addItemCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Vests +for "_j" from 0 to (_maxVestSlots - _minVestSlots + floor random _minVestSlots) do + { + _g = _vests call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addItemCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Helmets / caps / berets / bandanas +for "_j" from 0 to (_maxHeadGearSlots - _minHeadGearSlots + floor random _minHeadGearSlots) do + { + _g = _headGear call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addItemCargoGlobal [_g select 0, _g select 1]; + }; + }; + +// Backpacks +for "_j" from 0 to (_maxBagSlots - _minBagSlots + floor random _minBagSlots) do + { + _g = _backpacks call BIS_fnc_selectRandom; + if not((_g select 0) in _blackList) then + { + _crate addBackpackCargoGlobal [_g select 0, _g select 1]; + }; + }; + +["loadLoot", 1, format["Loot loaded into crate located in '%1' at %2", _locName, mapGridPosition _crate]] ExecVM ("log" call VEMFr_fnc_scriptPath); diff --git a/a3_vemf_reloaded/sqf/log.sqf b/a3_vemf_reloaded/sqf/log.sqf new file mode 100644 index 0000000..0615633 --- /dev/null +++ b/a3_vemf_reloaded/sqf/log.sqf @@ -0,0 +1,49 @@ +/* + Author: IT07 + + Description: + will log given data if debug is enabled + + Params: + _this: ARRAY - contains data required for logging + _this select 0: STRING - prefix. Use "" if none + _this select 1: SCALAR - 0 = error, 1 = info, 2 = special + _this select 2: STRING - the thing to log + + Returns: + nothing (use spawn, not call) +*/ + +if (("debugMode" call VEMFr_fnc_config) > 0) then +{ + scopeName "_top"; + params [ + ["_p", "", [""]], + ["_t", 3, [0]], + ["_l", "", [""]] + ]; + + _do = { diag_log text format["IT07: [VEMFr] %1 -- %2: %3", _p, _this, _l] }; + _m = "debugMode" call VEMFr_fnc_config; + if (_t isEqualTo 0) then + { + if (_m isEqualTo 1 OR _m isEqualTo 3) then + { + "ERROR" call _do; + breakOut "_top"; + }; + }; + if (_t isEqualTo 1) then + { + if (_m isEqualTo 2 OR _m isEqualTo 3) then + { + "INFO" call _do; + breakOut "_top"; + }; + }; + if (_t isEqualTo 2) then // This bypasses _m setting. Always logs given params even if debugMode is set to 0 + { + "SYSTEM" call _do; + breakOut "_top"; + }; +}; diff --git a/a3_vemf_reloaded/sqf/missionTimer.sqf b/a3_vemf_reloaded/sqf/missionTimer.sqf new file mode 100644 index 0000000..dbb2959 --- /dev/null +++ b/a3_vemf_reloaded/sqf/missionTimer.sqf @@ -0,0 +1,69 @@ +/* + Author: IT07 + + Description: + Handles the start and timeout of missions + + Params: + none + + Returns: + nothing +*/ + +scopeName "outer"; +_mgm = "maxGlobalMissions" call VEMFr_fnc_config; +["missionTimer", 1, format["Global mission-limit is set at: %1", _mgm]] ExecVM ("log" call VEMFr_fnc_scriptPath); +_minNew = "minNew" call VEMFr_fnc_config; +if (_minNew > -1) then + { + _maxNew = "maxNew" call VEMFr_fnc_config; + if (_maxNew > 0) then + { + _ml = "missionList" call VEMFr_fnc_config; + if (count _ml > 0) then + { + _minFps = "minServerFPS" call VEMFr_fnc_config; + _mnPlyrs = "minPlayers" call VEMFr_fnc_config; + if isNil "VEMFrForceStart" then { VEMFrForceStart = false }; + waitUntil { if ((((count allPlayers) >= _mnPlyrs) AND (diag_fps > _minFps)) OR VEMFrForceStart) then { true } else { uiSleep 5; false } }; + if VEMFrForceStart then + { + ["missionTimer", 1, format["VEMFr has been forced to start. Server FPS: %1", diag_fps]] ExecVM ("log" call VEMFr_fnc_scriptPath); + } else + { + ["missionTimer", 1, format["Enough players online (%1) and server FPS (%2) is above %3. Starting missionTimer...", count allPlayers, diag_fps, _minFps]] ExecVM ("log" call VEMFr_fnc_scriptPath); + }; + + VEMFrMissionCount = 0; + _im = false; + if (_mgm isEqualTo 0) then { _im = true }; + _zz = { uiSleep ((_minNew*60)+ floor random ((_maxNew*60)-(_minNew*60))) }; + call _zz; + + while {true} do + { + // Pick A Mission if enough players online + if ((count allPlayers) >= _mnPlyrs) then + { + scopeName "pick"; + if ((VEMFrMissionCount < _mgm) AND (VEMFrMissionCount >= 0) OR _im) then + { + _mssnNm = selectRandom _ml; + _h = [_mssnNm] execVM format["a3_vemf_reloaded\missions\%1.sqf", _mssnNm]; + uiSleep 5; + if (scriptDone _h) then { breakOut "pick" } else { call _zz }; + } else + { + if (VEMFrMissionCount < 0) then + { + ["missionTimer", 0, format["VEMFrMissionCount (%1) is BELOW 0! Stopping missionTimer...", VEMFrMissionCount]] ExecVM ("log" call VEMFr_fnc_scriptPath); + breakOut "outer"; + }; + call _zz; + }; + } else { uiSleep 60 }; + }; + }; + }; +}; diff --git a/a3_vemf_reloaded/sqf/notificationToClient.sqf b/a3_vemf_reloaded/sqf/notificationToClient.sqf new file mode 100644 index 0000000..df12023 --- /dev/null +++ b/a3_vemf_reloaded/sqf/notificationToClient.sqf @@ -0,0 +1,28 @@ +/* + Author: IT07 + + Description: + will put mission notification on either all screens or just on given + + Params: + _this select 0: SCALAR - mission type (AI mode) + _this select 1: STRING - notification title + _this select 2: STRING - notification message + _this select 3: ARRAY (optional) - specific clients to (ONLY) send notification to + + Returns: + nothing +*/ + +params [ + ["_mt", -1, [-1]], + ["_title", "", [""]], + ["_line", "", [""]], + ["_to", [], [[]]] +]; + +if ((count _to) isEqualTo 0) then { _to = allPlayers }; +{ + VEMFrMsgToClient = [[_mt, _title, _line], ""]; + (owner _x) publicVariableClient "VEMFrMsgToClient"; +} forEach _to; diff --git a/a3_vemf_reloaded/sqf/sayKilledWeapon.sqf b/a3_vemf_reloaded/sqf/sayKilledWeapon.sqf new file mode 100644 index 0000000..f8d8682 --- /dev/null +++ b/a3_vemf_reloaded/sqf/sayKilledWeapon.sqf @@ -0,0 +1,23 @@ +/* + Author: IT07 + + Description: + handles the broadcast of a systemChat kill message +*/ + +(_this select 0) params [ + ["_t", objNull, [objNull]], + ["_nt", "", [""]] +]; +(_this select 1) params [ + ["_k", objNull, [objNull]], + ["_nk", "", [""]] +]; + + +private ["_crWpn","_cfg"]; +if (vehicle _k isEqualTo _k) then { _crWpn = currentWeapon _k; _cfg = "CfgWeapons" } +else { _crWpn = typeOf (vehicle _k); _cfg = "CfgVehicles" }; +_dist = _t distance _k; + +[format["(VEMFr) %1 [%2] %3 | %4m", _nk, getText(configFile >> _cfg >> _crWpn >> "displayName"), if (("sayKilledName" call VEMFr_fnc_config) > 0) then {_nt} else {"AI"}, round _dist]] ExecVM "a3_vemf_reloaded\sqf\systemChatToClient.sqf"; diff --git a/a3_vemf_reloaded/sqf/setGroupOwner.sqf b/a3_vemf_reloaded/sqf/setGroupOwner.sqf new file mode 100644 index 0000000..20d1cdb --- /dev/null +++ b/a3_vemf_reloaded/sqf/setGroupOwner.sqf @@ -0,0 +1,53 @@ +/* + Author: IT07 + + Description: + handles the transfer of ownership to another given unit/client/object. + Will transfer complete group to the same (new) owner. + + Params: + _this select 0: GROUP - the group of which the ownership should be transfered + + Returns: + nothing +*/ + +_grp = param [0, grpNull, [grpNull]]; +if not(isNull _grp) then + { + // Check if HC is enabled + _hcNbld = "headLessClientSupport" call VEMFr_fnc_config; + _force = uiNamespace getVariable ["VEMFr_forceAItoClients", nil]; + if not(isNil "_force") then { if (_force isEqualType true) then { if _force then { _hcNbld = -1 } } }; + + private "_to"; + if (_hcNbld isEqualTo 1) then + { + _arr = []; + { + if (typeOf _x isEqualTo "HeadlessClient_F") then { _arr pushBack [_x, owner _x] }; + } forEach allPlayers; + + if (count _arr > 0) then { _to = call VEMFr_fnc_hc } else { uiNamespace setVariable ["VEMFr_forceAItoClients", true] }; + } else // If Headlessclient setting is not enabled + { + if ((count allPlayers) > 0) then + { + _distToX = worldSize; + { + _dist = _x distance (leader _grp); + if (_dist <= _distToX) then + { + _distToX = _dist; + _to = _x; + }; + } forEach allPlayers; + }; + }; + + if not(isNil "_to") then + { + _grp setGroupOwner (owner _to); + waitUntil { if not(local _grp) then {true} else {uiSleep 0.1; false} }; + }; + }; diff --git a/a3_vemf_reloaded/sqf/signAI.sqf b/a3_vemf_reloaded/sqf/signAI.sqf new file mode 100644 index 0000000..30bc610 --- /dev/null +++ b/a3_vemf_reloaded/sqf/signAI.sqf @@ -0,0 +1,15 @@ +/* + Author: IT07 + + Description: + marks given group(!) as VEMF AI which will then be used by REMOTEguard for monitor of groupOwner + + Params: + _this: ARRAY + _this select 0: GROUP - group to sign as VEMF AI + + Returns: + nothing +*/ + +(param [0, grpNull, [grpNull]]) setVariable ["isVEMFrGroup",true,true]; diff --git a/a3_vemf_reloaded/sqf/spawnStaticAI.sqf b/a3_vemf_reloaded/sqf/spawnStaticAI.sqf new file mode 100644 index 0000000..719c0fd --- /dev/null +++ b/a3_vemf_reloaded/sqf/spawnStaticAI.sqf @@ -0,0 +1,22 @@ +/* + Author: IT07 + + Description: + spawns AI at all given locations in config file + + Params: + none + + Returns: + nothing +*/ + +if ((([["aiStatic"],["enabled"]] call VEMFr_fnc_config) select 0) isEqualTo 1) then +{ + ["spawnStaticAI", 2, "launching..."] ExecVM ("log" call VEMFr_fnc_scriptPath); + ([["aiStatic"],["positions","amount"]] call VEMFr_fnc_config) params ["_s0","_s1"]; + ["spawnStaticAI", 2, "spawning AI on positions..."] ExecVM ("log" call VEMFr_fnc_scriptPath); + { + [_x, 2, _s1 select _foreachindex, ([[call VEMFr_fnc_whichMod],["aiMode"]] call VEMFr_fnc_config) select 0, "Static"] spawn VEMFr_fnc_spawnVEMFrAI; + } forEach _s0; +}; diff --git a/a3_vemf_reloaded/sqf/systemChatToClient.sqf b/a3_vemf_reloaded/sqf/systemChatToClient.sqf new file mode 100644 index 0000000..a700e06 --- /dev/null +++ b/a3_vemf_reloaded/sqf/systemChatToClient.sqf @@ -0,0 +1,21 @@ +/* + Author: IT07 + + Params: + _this select 0: FORMATTED STRING - line to broadcast + _this select 1: ARRAY - specific clients to (ONLY) send line to + + Returns: + nothing +*/ + +params [ + ["_line", "", [""]], + ["_to", [], [[]]] +]; + +if (_to isEqualTo []) then { _to = allPlayers }; +{ + VEMFrMsgToClient = [_line, "sys"]; + (owner _x) publicVariableClient "VEMFrMsgToClient"; +} forEach _to; diff --git a/a3_vemf_reloaded_config/CfgPatches.hpp b/a3_vemf_reloaded_config/CfgPatches.hpp new file mode 100644 index 0000000..19c220b --- /dev/null +++ b/a3_vemf_reloaded_config/CfgPatches.hpp @@ -0,0 +1,10 @@ +class CfgPatches +{ + class a3_vemf_reloaded_config + { + units[] = {}; + requiredAddons[] = {}; + fileName = "a3_vemf_reloaded_config.pbo"; + author = "IT07"; + }; +}; diff --git a/a3_vemf_reloaded_config/config.cpp b/a3_vemf_reloaded_config/config.cpp new file mode 100644 index 0000000..0017b5f --- /dev/null +++ b/a3_vemf_reloaded_config/config.cpp @@ -0,0 +1,36 @@ +#include "CfgPatches.hpp" + +class CfgVemfReloadedOverrides +{ + /* + File: config.cpp + Description: put all of the settings you always change in here and simply keep this pbo. Then you don't have to redo all your changes to the config.cpp everytime + Description 2: the only thing you will have to do now is simply check the CHANGELOG.md on GitHub everytime there is an update to check if there are any deprecated settings + Description 3: instead of changing the config.cpp settings everytime, just add your changes here. Saves a lot of time. Yes you are welcome you lucky bastard + Note: it is extremely difficult for a coder to explain with text how to do this so I have put a few examples in this file instead + Note 2: the already present lines below line 10 are just examples so feel free to delete them + */ + + // Put all the settings you want to override below this line + /* + debugMode = 2; // Overrides CfgVemfReloaded >> debugMode + maxGlobalMissions = 5; // Overrides CfgVemfReloaded >> maxGlobalMissions + minServerFPS = 5; // Overrides CfgVemfReloaded >> minServerFPS + class crateLoot + { + primarySlotsMax = 3; // Overrides CfgVemfReloaded >> crateLoot >> primarySlotsMax + primarySlotsMin = 1; // Overrides CfgVemfReloaded >> crateLoot >> primarySlotsMin + }; + class locationBlackLists + { // NOTE: If the map you use is not listed below, simply add it by yourself or put the locations you want to blacklist into the locations array of the Other class + class Altis + { + locations[] = {}; // Overrides CfgVemfReloaded >> locationBlackLists >> Altis >> locations + }; + }; + class aiGear + { + aiPistols[] = {"hgun_ACPC2_F","hgun_Rook40_F"}; // Overrides CfgVemfReloaded >> aiGear >> aiPistols + }; + */ +}; // Do not touch this line