diff --git a/A3_Exile_VEMF_Reloaded.7z b/A3_Exile_VEMF_Reloaded.7z
new file mode 100644
index 0000000..8b1b0ba
Binary files /dev/null and b/A3_Exile_VEMF_Reloaded.7z differ
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..28403f2
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,206 @@
+## VEMF Changelog
+
+#### `v0740.30`
+*Server-side*
+**[ADDED]** Option to prevent AI from having TWS (thermal) scopes
+**[CHANGED]** Order of config settings from being a total mess to being alphabetically sorted.
+
+
+#### `v0740.27`
+*Server-side*
+**[ADDED]** More advanced ammo distribution system for AI units
+**[FIXED]** Sometimes no .50 cals at missions
+**[FIXED]** "Error: no vehicle" when killing AI with Helicopter
+**[CHANGED]** A few comments in config.cpp to improve clearness
+
+
+#### `v0740.19`
+*Server-side*
+**[ADDED]** Option to enable/disable respect punishment for roadkilling AI
+**[ADDED]** Option to remove "toolbelt" items like GPS, Radio, Map and Compass from AI
+**[ADDED]** New options class to control AI cleanup-related settings
+**[ADDED]** AI units now randomly have random weapon attachments
+**[NEW]** Config.cpp does NOT use -1 anymore to disable things. It is now 0 instead.
+**[CHANGED]** Config.cpp option comments
+**[CHANGED]** On roadkill, kill message shows [Roadkill] instead of vehicle used
+**[IMPROVED]** Overall code performance and use of newer commands
+**[FIXED]** Mines are not working
+**[REMOVED]** fn_random.sqf, replaced by selectRandom command https://community.bistudio.com/wiki/selectRandom
+
+
+#### `v0740.6`
+*Server-side*
+**[CHANGED]** BIS_fnc_param replaced by new param command
+**[CHANGED]** Blacklist method for locations. Seperate classes for each map for easier use
+
+*Client-side*
+No Changes.
+
+
+#### `v0732.8`
+*Server-side:*
+**[ADDED]** AI static spawns
+**[ADDED]** fn_aiKilled: now shows the name of vehicle used to road-kill an AI
+**[ADDED]** fn_checkLoot: RPT log message if loot validation is enabled but no debug allowed
+**[IMPROVED]** Descriptions and naming of config values
+**[IMPROVED]** fn_aiKilled: now shows killer [weapon, range] victim
+**[IMPROVED]** fn_log: is now faster and much more simple
+**[FIXED]** fn_aiKilled: if killer using vehicle gun, it shows the primaryweapon of the killer instead of the vehicle turret as the weapon used
+**[CHANGED]** Mission complete logs now show the name of location in which the mission was
+**[CHANGED]** Name of pbo is now all lowercase
+
+*Client-side:*
+**[CHANGED]** mission notification messages now have VEMFr as tag instead of the old VEMF tag
+
+
+#### `v0730.21`
+**[REMOVED]** Medikit and toolkit from loot crate(s)
+
+
+#### `v0730.20`
+**[ADDED]** Option to control the classname of the AI units
+**[ADDED]** Automatic detection of AI unit's side to make sure they get put into a correct group type
+
+
+#### `v0730.15`
+**[ADDED]** Option enable/disable the ability to lift loot crate
+
+
+#### `v0730.14`
+**[FIXED]** Loss of respect when using vehicle turret
+**[FIXED]** Server-side script error caused by killTheLights
+
+
+#### `v0730.2`
+**[NEW]** refreshed mission notification with new animations
+**[FIXED]** difficult to see quickly if mission message means new one or a defeated one
+**[FIXED]** network load peak and fps lag when mines are placed by mission
+**[CHANGED]** server-side message broadcasting to accommodate for including the notification type in the broadcast
+
+
+#### `v0729.1`
+**[CHANGED]** increased detection speed of players for triggering missions from 200 to 250
+**[REMOVED]** any usage of playableUnits command
+**[REMOVED]** any checks for the player's side
+**[FIXED]** old stuff in fn_checkLoot.sqf
+**[FIXED]** mission amount can go beyond the limit
+**[FIXED]** fn_playerCount.sqf: unreliable detection of player amount
+**[FIXED]** VEMF_Reloaded started anyway without the actual amount of minimal players to be ingame
+**[IMPROVED]** fail-safe "if checks" in fn_missionTimer.sqf
+
+#### `v0728.6`
+**[FIXED]** Instabilities in spawning/despawning of missions
+**[FIXED]** First mission does not timeout
+**[ADDED]** Option to blacklist certain buildings using their classnames
+**[NEW]** Each DynamicLocationInvasion mission type has its own marker color
+
+
+#### `v0727.15`
+**[FIX ATTEMPT]** Missions not spawning anymore under very specific conditions
+
+
+#### `v1.0727.13`
+**[FIXED]** fn_loadInv not working for the bad guys
+**[FIXED]** random missions not working if mission announcements were disabled
+
+
+#### `v1.0727.11`
+**[FIXED]** Missions stop spawning after a certain amount of time
+
+
+#### `v1.0727.9`
+**[ADDED]** Option to disable/enable mission announcements
+
+
+#### `v1.0727.3`
+**[CHANGED]** Exile_VEMF is now called Exile_VEMF_Reloaded because the original creator of VEMF is proceeding on VEMF
+**[ADDED]** S.W.A.T. AI
+**[ADDED]** Option to send kill messages only to the killer (@KillingRe)
+
+
+#### `v1.0725.6`
+**[NEW]** Option to control deletion of .50 cals when mission done
+**[IMPROVED]** Respect reward system
+**[FIXED]** Players getting respect if AI kill other AI
+
+
+#### `v1.0724.1`
+**[NEW]** Option to control distance between each mission
+**[CHANGED]** Server-side folder is now called Exile_VEMF
+
+
+#### `v1.0723.1 HOTFIX`
+**[FIXED]** fn_aiKilled.sqf: error Undefined variable in expression unit
+
+
+#### `v1.0722.15`
+**[NEW]** Player now get reputation for killing AI. Dynamically increases depending on kill distance
+**[FIXED]** Unstable fn_random.sqf
+
+
+#### `v1.0721.15`
+**[NEW]** AI will now spawn in houses
+**[NEW]** Mounted (bipod) .50 cals in/on houses if enabled
+**[ADDED]** Option to enable/disable AI "Cop mode"
+**[CHANGED]** fn_spawnAI.sqf to allow spawning in houses
+**[TWEAKED]** fn_loadInv.sqf
+
+#### `v1.0721.1`
+**[FIXED]** fn_spawnAI.sqf: Suspending not allowed in this context, line 72
+
+
+#### `v1.0720.6`
+**[NEW]** Automatic removal of loot crate marker when player gets close
+**[ADDED]** Option to enable/disable mission markers
+**[ADDED]** Ability to put `maxGlobalMissions` on -1. Disables the mission limit
+**[ADDED]** Exile default safe zones to mission blacklist positions
+**[ADDED]** Option to enable/disable loot crate markers
+**[ADDED]** Option to enable/disable loot crate parachute spawn
+**[ADDED]** Option to enable/disable loot crate visual smoke/chemlights
+**[ADDED]** Option to enable/disable loot crate spawn sound (once)
+**[ADDED]** Logging of successfull removal/exploding of mines
+**[ADDED]** Code changes to fn_missionTimer.sqf to allow ignoring of global mission count
+**[ADDED]** Code changes to DLI mission to prevent removal of non-existing mission marker
+**[CHANGED]** several config options from negative to positive
+**[CHANGED]** Default debug mode from 2 to 0 (errors only)
+**[CHANGED]** AI difficulty config now less lines
+**[CHANGED]** AI Veteran and Harcore difficulty increased
+**[CHANGED]** Mines are now switched off by default
+**[CHANGED]** Default mine removal mode is now explode
+**[CHANGED]** fn_loadLoot.sqf: now empties the crate instead of the mission itself
+**[FIXED]** Error in expression fn_findPos.sqf
+**[FIXED]** Error in expression fn_loadInv.sqf with specific set of config settings
+
+
+#### `v1.0719.10`
+**[ADDED]** Option to enable/disable the placement of a marker on the loot crate
+**[ADDED]** Attempt to fix the floating crate problem
+**[ADDED]** Fail-safety for fn_checkPlayerPresence.sqf
+**[ADDED]** Fail-safety for fn_placeMines.sqf
+**[ADDED]** Fail-safety for fn_spawnAI.sqf
+**[CHANGED]** Default value of `validateLoot` from 1 to -1
+**[REMOVED]** Option to enable/disable sound on the loot crate
+**[FIXED]** Mines not removing or exploding
+**[FIXED]** Structure error in fn_findPos.sqf
+
+#### `v1.0718.11`
+**NOTE:** VEMFclient code has been changed!
+**[ADDED]** AI difficulty presets
+**[CHANGED]** Default cleanMines setting changed from 2 to 1
+**[CHANGED]** fn_broadCast.sqf for new broadcast system
+**[CHANGED]** fn_loadLoot.sqf: fail-safety removed
+**[CHANGED]** fn_spawnAI.sqf: implementation of AI difficulty presets
+**[CHANGED]** Veteran AI difficulty lowered. Too close to aimbots
+**[FIXED]** Duplicate spawns on locations
+**[FIXED]** Player getting side ENEMY for attacking AI
+**[FIXED]** Loot crate not falling down
+**[FIXED]** Loot crate not making a sound
+
+#### `v1.0717.7`
+**[FIXED]** No loot in crate
+**[FIXED]** AI not shooting at player
+
+
+#### `v1.0716.14`
+**[NEW]** VEMF ported to Exile :)
+
diff --git a/Exile.MapName/VEMFr_client/CfgFunctions.hpp b/Exile.MapName/VEMFr_client/CfgFunctions.hpp
new file mode 100644
index 0000000..8259420
--- /dev/null
+++ b/Exile.MapName/VEMFr_client/CfgFunctions.hpp
@@ -0,0 +1,10 @@
+class VEMF_Reloaded
+{
+ tag = "VEMFr";
+ class clientFunctions
+ {
+ file = "VEMFr_client\functions";
+ class handleMessage {};
+ class clientInit { postInit = 1; };
+ };
+};
diff --git a/Exile.MapName/VEMFr_client/functions/fn_clientInit.sqf b/Exile.MapName/VEMFr_client/functions/fn_clientInit.sqf
new file mode 100644
index 0000000..0dcf227
--- /dev/null
+++ b/Exile.MapName/VEMFr_client/functions/fn_clientInit.sqf
@@ -0,0 +1,36 @@
+if (hasInterface) then
+{
+ uiNamespace setVariable ["RscDisplayVEMFrClientMsgQueue", []];
+ uiNamespace setVariable ["RscDisplayVEMFrClient", displayNull];
+ // custom addPublicVariableEventHandler. Those bloody BE filters.....
+ [] spawn
+ {
+ while {true} do
+ {
+ waitUntil { uiSleep 0.05; not isNil"VEMFrClientMsg" };
+ if (typeName VEMFrClientMsg isEqualTo "ARRAY") then
+ {
+ _data = +[VEMFrClientMsg];
+ VEMFrClientMsg = nil;
+ _data = _data select 0;
+ [_data] spawn
+ {
+ _data = _this select 0;
+ _mode = [_data, 1, "", [""]] call BIS_fnc_param;
+ _msg = [_data, 0, "", [[],format[""]]] call BIS_fnc_param;
+ switch _mode do
+ {
+ case "sys":
+ {
+ systemChat _msg;
+ };
+ default
+ {
+ [_msg select 0, _msg select 1] spawn VEMFr_fnc_handleMessage;
+ };
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/Exile.MapName/VEMFr_client/functions/fn_handleMessage.sqf b/Exile.MapName/VEMFr_client/functions/fn_handleMessage.sqf
new file mode 100644
index 0000000..2471a4a
--- /dev/null
+++ b/Exile.MapName/VEMFr_client/functions/fn_handleMessage.sqf
@@ -0,0 +1,118 @@
+_txt = [_this, 0, "", [""]] call BIS_fnc_param;
+_type = [_this, 1, "", [""]] call BIS_fnc_param;
+if not(_txt isEqualTo "") then
+{
+ _msgQueue = uiNamespace getVariable ["RscDisplayVEMFrClientMsgQueue", []];
+ _msgQueue pushBack _txt;
+ disableSerialization;
+ _dsp = uiNamespace getVariable ["RscDisplayVEMFrClient", displayNull];
+ _doAnim =
+ {
+ for "_g" from 1 to (count _txt) do
+ {
+ _ctrl ctrlSetText (_txt select [0, _g]);
+ if isNull (findDisplay 49) then
+ {
+ if not isNull _dsp then
+ {
+ playSound "ReadOutClick"
+ };
+ };
+ uiSleep 0.05;
+ };
+ _chars = [];
+ for "_t" from 1 to (count _txt) do
+ {
+ _char = _txt select [_t, 1];
+ _chars pushBack _char;
+ };
+ _writeThis = +_chars;
+ uiSleep ((count _txt)/6);
+ for "_i" from (count _chars) to 1 step -1 do
+ {
+ _charID = floor random count _chars;
+ _deleted = _chars deleteAt _charID;
+ if not(_deleted isEqualTo "") then
+ {
+ _charToSet = _writeThis find _deleted;
+ if not(_deleted isEqualTo " ") then
+ {
+ _binaries = ["0","1"];
+ _writeThis set [_charToSet, _binaries select floor random count _binaries];
+ };
+ _string = "";
+ {
+ _string = _string + _x;
+ } forEach _writeThis;
+ _ctrl ctrlSetText _string;
+ if isNull(findDisplay 49) then
+ {
+ if not isNull _dsp then
+ {
+ playSound "ReadOutHideClick1"
+ };
+ };
+ uiSleep 0.05;
+ };
+ };
+
+ if (typeName _msgQueue isEqualTo "ARRAY") then
+ {
+ _index = _msgQueue find _txt;
+ if (_index > -1) then
+ {
+ _msgQueue deleteAt _index;
+ };
+ };
+
+ if (count _msgQueue isEqualTo 0) then
+ {
+ _ctrl ctrlSetPosition [(ctrlPosition _ctrl) select 0, (ctrlPosition _ctrl) select 1, 0 * safezoneW, (ctrlPosition _ctrl) select 3];
+ _ctrl ctrlCommit 0.5;
+ uiSleep 0.5;
+ _ctrlTag ctrlSetPosition [(ctrlPosition _ctrlTag) select 0, (ctrlPosition _ctrlTag) select 1, (ctrlPosition _ctrlTag) select 2, 0 * safezoneH];
+ _ctrlTag ctrlCommit 0.3;
+ _ctrlTag ctrlSetText "";
+ uiSleep 0.3;
+ _ctrlMsgType ctrlSetPosition [(ctrlPosition _ctrlMsgType) select 0, (ctrlPosition _ctrlMsgType) select 1, 0 * safezoneW, (ctrlPosition _ctrlMsgType) select 3];
+ _ctrlMsgType ctrlCommit 0.3;
+ uiSleep 0.3;
+ (["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutFadeOut 0.3;
+ };
+ };
+ if isNull _dsp then
+ { // Make sure the display is actually active
+ (["RscDisplayVEMFrClient"] call BIS_fnc_rscLayer) cutRsc["RscDisplayVEMFrClient", "PLAIN", 0, true];
+ _dsp = uiNamespace getVariable ["RscDisplayVEMFrClient", displayNull];
+ if ((count _msgQueue) > 0) then
+ {
+ _ctrlMsgType = _dsp displayCtrl 1002;
+ _ctrlMsgType ctrlSetText _type;
+ _ctrlMsgType ctrlSetPosition [(ctrlPosition _ctrlMsgType) select 0, (ctrlPosition _ctrlMsgType) select 1, 0.1 * safezoneW, (ctrlPosition _ctrlMsgType) select 3];
+ _ctrlMsgType ctrlCommit 0.3;
+ uiSleep 0.3;
+ _ctrlTag = _dsp displayCtrl 1001;
+ _ctrlTag ctrlSetPosition [(ctrlPosition _ctrlTag) select 0, (ctrlPosition _ctrlTag) select 1, (ctrlPosition _ctrlTag) select 2, 0.03 * safezoneH];
+ _ctrlTag ctrlCommit 0.3;
+ uiSleep 0.3;
+ _ctrlTag ctrlSetText toString [86,69,77,70,114];
+ _ctrl = _dsp displayCtrl 1000;
+ _ctrl ctrlSetPosition [(ctrlPosition _ctrl) select 0, (ctrlPosition _ctrl) select 1, 0.4375 * safezoneW, (ctrlPosition _ctrl) select 3];
+ _ctrl ctrlCommit 0.3;
+ uiSleep 0.3;
+ call _doAnim;
+ };
+ };
+ if not isNull _dsp then
+ {
+ waitUntil { uiSleep 1; (_msgQueue select 0) isEqualTo _txt };
+ if not isNull _dsp then
+ {
+ _ctrlMsgType = _dsp displayCtrl 1002;
+ _ctrlMsgType ctrlSetText _type;
+ _ctrlTag = _dsp displayCtrl 1001;
+ _ctrl = _dsp displayCtrl 1000;
+ call _doAnim;
+ };
+ };
+};
diff --git a/Exile.MapName/VEMFr_client/gui/hpp_mainVEMFrClient.hpp b/Exile.MapName/VEMFr_client/gui/hpp_mainVEMFrClient.hpp
new file mode 100644
index 0000000..4407cb2
--- /dev/null
+++ b/Exile.MapName/VEMFr_client/gui/hpp_mainVEMFrClient.hpp
@@ -0,0 +1,43 @@
+class RscDisplayVEMFrClient
+{
+ idd = 2991;
+ fadeIn = 0.2;
+ fadeOut = 1;
+ duration = 99999;
+ onLoad = "uiNamespace setVariable ['RscDisplayVEMFrClient', _this select 0]";
+ movingEnable = 0;
+ class IGUIBack
+ {
+ type = 0;
+ text = "";
+ colorText[] = {0,0,0,0};
+ font = "PuristaMedium";
+ sizeEx = 0;
+ shadow = 0;
+ style = 128;
+ colorBackground[] = {0,0,0,1};
+ };
+ class RscText
+ {
+ shadow = 0;
+ deletable = 0;
+ fade = 0;
+ sizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)";
+ font = "PuristaLight";
+ style = 0;
+ access = 0;
+ type = 0;
+ fixedWidth = 0;
+ colorShadow[] = {0,0,0,0.5};
+ lineSpacing = 1;
+ tooltipColorText[] = {1,1,1,0.9};
+ tooltipColorBox[] = {1,1,1,0.2};
+ tooltipColorShade[] = {0,0,0,0.7};
+ colorText[] = {0.22,0.745,0.882,1};
+ colorBackground[] = {0.071,0.078,0.094,1};
+ };
+ class controls
+ {
+ #include "hpp_rscVEMFrClient.hpp"
+ };
+};
diff --git a/Exile.MapName/VEMFr_client/gui/hpp_rscVEMFrClient.hpp b/Exile.MapName/VEMFr_client/gui/hpp_rscVEMFrClient.hpp
new file mode 100644
index 0000000..c0cc61e
--- /dev/null
+++ b/Exile.MapName/VEMFr_client/gui/hpp_rscVEMFrClient.hpp
@@ -0,0 +1,36 @@
+class txtType: RscText
+{
+ idc = 1002;
+ font = "PuristaSemiBold";
+ text = "";
+ colorText[] = {0,0,0,0.9};
+ colorBackground[] = {1,1,1,0.9};
+ x = 0.25 * safezoneW + safezoneX;
+ y = 0.88 * safezoneH + safezoneY;
+ w = 0 * safezoneW;
+ h = 0.02 * safezoneH;
+};
+class txtTag: RscText
+{
+ idc = 1001;
+ font = "PuristaBold";
+ text = "";
+ sizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1.3)";
+ colorText[] = {0,0,0,0.9};
+ colorBackground[] = {1,1,1,0.9};
+ x = 0.25 * safezoneW + safezoneX;
+ y = 0.9 * safezoneH + safezoneY;
+ w = 0.05 * safezoneW;
+ h = 0 * safezoneH;
+};
+class txtMsg: RscText
+{
+ idc = 1000;
+ text = "";
+ colorText[] = {1,1,1,0.9};
+ colorBackground[] = {0,0,0,0.9};
+ x = 0.3 * safezoneW + safezoneX;
+ y = 0.9 * safezoneH + safezoneY;
+ w = 0 * safezoneW;
+ h = 0.03 * safezoneH;
+};
diff --git a/Exile.MapName/description.ext b/Exile.MapName/description.ext
new file mode 100644
index 0000000..a3a3f74
--- /dev/null
+++ b/Exile.MapName/description.ext
@@ -0,0 +1,9 @@
+class cfgFunctions
+{
+ #include "VEMFr_client\CfgFunctions.hpp"
+};
+
+class RscTitles
+{
+ #include "VEMFr_client\gui\hpp_mainVEMFrClient.hpp"
+};
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..512131e
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,67 @@
+================================================================================================
+====== LICENSE INFORMATION ===================================================================
+================================================================================================
+
+ VEMF code is provided under an Attribution Non-Commercial ShareAlike 4.0 Commons License.
+Link: http://creativecommons.org/licenses/by-nc-sa/4.0/
+
+ The majority of the code is created by the VEMF license holder, but not all of it.
+Very small samples of code may belong to the "Exile Mod" for Arma 3 made by the Exile Mod Team.
+
+ The "Exile Mod" code is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License
+Link: http://creativecommons.org/licenses/by-nc-nd/4.0/
+Website: http://exilemod.com/
+
+ VEMF being programmed for the Arma 3 engine means you must also comply to Bohemia
+Interactive's End User License Agreement, and Game Content Usage Rules.
+EULA: http://www.bistudio.com/community/licenses/arma3-end-user-license
+GCUR: http://www.bistudio.com/community/game-content-usage-rules
+
+================================================================================================
+What does this mean for me?
+
+ You are able to share VEMF under any format, torrents, file hosts, ftp etc,
+however it must be free to be able to access the downloads. If you have to pay
+for an account to access the download link you are in violation of the license.
+
+ You can adapt the work as you please inside of the terms of the license.
+
+ If you want to release an adapted version of VEMF, you must give appropriate
+credit to the original authors, provide a link to the license, indicate if changes
+were made (via a changelog), and share the new version under the same license.
+
+ You must do this in a way that does not indicate that the original authors
+endorses you or your use. (An example would be advertising your new adaptation
+as originally coming from VEMF. The key being "Advertise" instead of simply listing it.)
+
+ Finally, this content cannot be commercialized. If you are receiving ANY
+monetary funds where VEMF is included in your work, you are breaking the terms of this license.
+Donations are to be given without any return consideration. The person donating cannot have
+the intention of receiving something in return from you for making their donation.
+
+This include but is not limited to:
+ - Selling access to a server that runs VEMF.
+ - Allowing users of your server to purchase "perks" somehow related to VEMF. (Mission GPS?)
+ - Including VEMF in a mod that is being sold for a profit.
+ - Preventing access to VEMF files or content based on donations.
+
+================================================================================================
+So do I need to ask for your permission to modify VEMF?
+
+ As a non-binding request, I ask that you make a concerted effort to try to contact me
+to ask for my permission before you start modifying VEMF. I would like to know about modified
+versions of VEMF before they are released. This request does not apply to individuals
+("Individuals" not "groups") or "clans" that wish to modify VEMF for their individual server.
+
+ Even though this license seems a little overkill, I'm a fairly likeable guy. If you're
+trying to contact me for a non-commercial interest, I'll most likely allow it.
+
+ If you cannot reach me within a month, and you meet all the other requirements of this license,
+you can modify VEMF freely within the terms of the license.
+
+================================================================================================
+I feel VEMF is infringing upon my work.
+
+ If you think VEMF infringes upon your work, please contact me.
+ You can contact me on:
+EpochMod.com (IT07), Reddit (IT07), forums.bistudio.com (IT07) and Exilemod.com (IT07)
diff --git a/README.md b/README.md
index e4bebb9..8e320b3 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,64 @@
-# ArmA3_exile_vemf_reloaded
-Contains VEMFr (a.k.a. VEMF Reloaded) for ArmA 3 Exile Mod
+# A3_Exile_VEMF_Reloaded
+**Not to confuse with VEMF**
+
+#### How to download?
+**Because of its new location, the download process is a little different:**
+Click the .7z file and then click the "Raw" button. You will then get the exile_vemf_reloaded folder and the Exile.MapName folder inside of a packed .7z :)
+
+
+#### How to install?
+**Server-side files**
+- copy the `exile_vemf_reloaded` folder over into where your server's `@ExileServer\addons\` folder is located.
+- navigate into the `exile_vemf_reloaded` folder that you just copied over into your server.
+- open the config.cpp and READ IT. There is A LOT of settings in there that you can adjust to change VEMFr.
+- when done changing stuff in the config.cpp, simply pack **the contents(!)** of the parent folder into a pbo called `exile_vemf_reloaded`
+- you can delete the `exile_vemf_reloaded` folder that the program you use to pack into a pbo might have left behind. You don't have to though.
+
+**Client-side files**
+- whatever your server setup might be, you need to open/download/unpack your server's mission file. If you are running the Altis map for example, it will be a .pbo called `Exile.Altis`. Or when you are running Esseker for example, then it will be `Exile.Esseker`. Normally that file is located inside the *mpmissions* folder which is in the root of your server's installation path. Simply unpack that file and go into the folder that comes out of it. There should be a file called `description.ext` in there. Open that. Then look for a line that says `class CfgFunctions`. If you can not find it, then add this somewhere near the bottom of your description.ext:
+```
+class cfgFunctions
+{
+ #include "VEMFr_client\CfgFunctions.hpp"
+};
+```
+
+However, if you DO have a `class CfgFunctions` in your description.ext, then simply add `#include "VEMFr_client\CfgFunctions.hpp"` between the `{` (opening bracket) and `};` (closing bracket), like this:
+```
+class cfgFunctions
+{
+ class justAnExample
+ {
+ tag = "Exile";
+ class fkasjhdfksahfkhsd
+ {
+ file = "dssdf";
+ class fdshjlkfhasjdk {};
+ };
+ };
+ #include "VEMFr_client\CfgFunctions.hpp"
+};
+```
+
+- now the last part: `class RscTitles`. Try and find it in your description.ext, if it is not there, then just simply add this to the bottom of your description.ext:
+```
+class RscTitles
+{
+ #include "VEMFr_client\gui\hpp_mainVEMFrClient.hpp"
+};
+```
+
+BUT, if you DO have a `class RscTitles` already, then just make a new line just before the `};` and then put this on that new line:
+`#include "VEMFr_client\gui\hpp_mainVEMFrClient.hpp"`
+Just an example of how it would look with other stuff in between the brackets of `class RscTitles`:
+```
+class RscTitles
+{
+ #include "some\other\scriptszzzzz\file.hpp"
+ #include "bla\addons\dialog.hpp"
+ #include "addons\scripts\gui\someFile.hpp"
+ #include "VEMFr_client\gui\hpp_mainVEMFrClient.hpp"
+};
+```
+
+*Done!*
diff --git a/exile_vemf_reloaded/addons/VEMFAddons.txt b/exile_vemf_reloaded/addons/VEMFAddons.txt
new file mode 100644
index 0000000..8e47d00
--- /dev/null
+++ b/exile_vemf_reloaded/addons/VEMFAddons.txt
@@ -0,0 +1 @@
+VEMF Addon scripts can be added here.
\ No newline at end of file
diff --git a/exile_vemf_reloaded/config.cpp b/exile_vemf_reloaded/config.cpp
new file mode 100644
index 0000000..677f6c2
--- /dev/null
+++ b/exile_vemf_reloaded/config.cpp
@@ -0,0 +1,397 @@
+/*
+ Author: IT07
+
+ Description:
+ cpp config file for exile_vemf_reloaded
+
+ What is exile_vemf_reloaded? (short: VEMFr)
+ It is a complete remake (and port to Exile) of VEMF (for Epoch) by TheVampire.
+ exile_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 exile_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 mode ///////
+ debugMode = 2; // 0 = no debugging | 1 = ERRORS only | 2 = INFO only | 3 = ERRORS & INFO
+ ///////////////////////////////////////
+
+ // Global settings
+ addons[] = {}; // Not used for now
+ headLessClientSupport = 0;
+ headLessClientNames[] = {"HC1"};
+ housesBlackList[] = {"Land_Pier_F"};
+ killPercentage = 100; // How much of total AI has to be killed for mission completion (in percentage)
+ 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"}; // 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 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
+ 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
+
+ // 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 > = amount of respect to deduct from player;
+
+ // AI Unit settings
+ unitClass = "B_G_Soldier_AR_F"; // Default: "B_G_Soldier_AR_F"
+ // NOTE: VEMFr will automatically adjust the AI's side that belongs to the unit of given unitClass
+
+ 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[] = {"Sagonisi","Monisi","Fournos","Savri","Atsalis","Polemista","Cap Makrinos","Pyrgi","Makrynisi","Chelonisi","Almyra","Surf Club"};
+ };
+ class Stratis
+ {
+ locations[] = {"Marina Bay","Kamino Bay","Keiros Bay","Limeri Bay","Tsoukala Bay","Jay Cove","Strogos Bay","Kyfi Bay","Nisi Bay"};
+ };
+ class Namalsk
+ {
+ locations[] = {"Nemsk Bay","Brensk Bay","Seraja Bay","Lubjansk Bay","Tara Strait"};
+ };
+ class Other
+ {
+ locations[] = {};
+ };
+ };
+
+ class DynamicLocationInvasion // DynamicLocationInvasion (mission) settings
+ {
+ allowCrateLift = 0; // Allow/disallow the loot crate to be lifted with helicopter
+ aiLaunchers = 1; // Allow/disallow AI to HAVE rocket launchers
+ allowTWS = 0; // Enable/disable the usage of TWS scopes by AI
+ 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)
+ 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
+ marker = 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 = 15000; // Maximum distance from random player for mission location selection
+ /* 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 placeMines = 0;
+ minesCleanup = 1; // Enable/disable the removal of mines once mission has been completed | 2 = explode mines
+ parachuteCrate[] = {0, 250}; // default: {disabled, 250 meters} | use 1 as first number to enable crate parachute spawn
+ 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)
+ smokeTypes[] = {"SmokeShell","SmokeShellBlue","SmokeShellGreen","SmokeShellOrange","SmokeShellRed","SmokeShellYellow"};
+ 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 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 aiStatic
+ {
+ 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
+ };
+
+ // Global AI skill settings. They affect each VEMF unit for any default VEMF mission
+ class aiSkill // Minimum: 0 | Maximum: 1
+ {
+ 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.7; courage = 1; reloadSpeed = 0.3; commanding = 0.8; general = 0.3;
+ };
+ class Normal
+ {
+ accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.7; courage = 1; reloadSpeed = 0.3; commanding = 0.8; general = 0.4;
+ };
+ class Veteran
+ {
+ accuracy = 0.4; aimingShake = 0.20; aimingSpeed = 0.3; endurance = 0.25; spotDistance = 0.5; spotTime = 0.7; courage = 1; reloadSpeed = 0.3; commanding = 0.8; 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.7; courage = 1; reloadSpeed = 0.3; commanding = 0.8; 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"};
+ };
+
+ // Loot crate configuration
+ class crateLoot
+ {
+ primarySlotsMax = 10; // Maximum primary weapons in each loot crate
+ primarySlotsMin = 4; // 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 = 4; // Maximum number of secondary weapons to be in each loot crate
+ secondarySlotsMin = 2; // 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 = 6; // Maximum number of magazine slots in each loot crate
+ magSlotsMin = 4; // 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 = 4; // Maximum number of vest slots in each loot crate
+ vestSlotsMin = 2; // 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 = 4; // Maximum number of headGear slots in each loot crate
+ headGearSlotsMin = 2; // 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 = 4;
+ bagSlotsMin = 2;
+ 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_MillerBody","U_KerryBody","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_OG_leader",
+ "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"
+ };
+ };
+};
+
+class CfgPatches
+{
+ class exile_vemf_reloaded
+ {
+ units[] = {};
+ requiredAddons[] = {"exile_server"};
+ fileName = "exile_vemf_reloaded.pbo";
+ requiredVersion = 1.56; // VEMF does not work on older versions due to use of the latest scripting commands
+ version = 0740.30; // Do NOT change
+ author[]= {"IT07"};
+ };
+};
+
+class CfgFunctions
+{
+ class exile_vemf_reloaded
+ {
+ tag = "VEMFr";
+ class serverFunctions
+ {
+ file = "exile_vemf_reloaded\functions";
+ class log {};
+ class getSetting {};
+ class aiKilled {};
+ class findPos {};
+ class broadCast {};
+ class playerCount {};
+ class headLessClient {};
+ class signAI {};
+ class transferOwner {};
+ class checkPlayerPresence {};
+ class loadInv {};
+ class giveAmmo {};
+ class giveWeaponItems {};
+ class spawnAI {};
+ class spawnStaticAI {};
+ class loadLoot {};
+ class placeMines {};
+ class waitForPlayers {};
+ class waitForMissionDone {};
+ class checkLoot {};
+ class missionTimer {};
+ class launch { postInit = 1; };
+ class REMOTEguard { postInit = 1; };
+ };
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_REMOTEguard.sqf b/exile_vemf_reloaded/functions/fn_REMOTEguard.sqf
new file mode 100644
index 0000000..19b03df
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_REMOTEguard.sqf
@@ -0,0 +1,38 @@
+/*
+ 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
+*/
+
+[] spawn
+{
+ uiNamespace setVariable ["VEMFrHcLoad", []];
+ uiNamespace setVariable ["vemfGroups", []];
+ while {true} do
+ {
+ _groups = uiNamespace getVariable "vemfGroups";
+ waitUntil { uiSleep 1; count _groups > 0 };
+ {
+ if (local _x) then
+ {
+ if ((count units _x) < 1) then
+ {
+ deleteGroup _x;
+ };
+ if (count (units _x) > 0) then
+ {
+ // Group still has units, check if there is anyone that can be the owner
+ [_x] call VEMFr_fnc_transferOwner;
+ };
+ };
+ } forEach _groups;
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_aiKilled.sqf b/exile_vemf_reloaded/functions/fn_aiKilled.sqf
new file mode 100644
index 0000000..9530a78
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_aiKilled.sqf
@@ -0,0 +1,199 @@
+/*
+ VEMF AI Killed by Vampire, rewritten by IT07
+
+ Description:
+ removes launchers if desired and announces the kill if enabled in config.cpp
+
+ Params:
+ _this: ARRAY
+ _this select 0: OBJECT - the killed AI
+ _this select 1: OBJECT - killer
+
+ Returns:
+ nothing
+*/
+
+if (_this isEqualType []) then
+{
+ _target = param [0, objNull, [objNull]];
+ if not isNull _target then
+ {
+ _target removeAllEventHandlers "MPKilled";
+ _settings = [["aiCleanup"],["removeLaunchers","aiDeathRemovalEffect","removeHeadGear"]] call VEMFr_fnc_getSetting;
+ _removeLaunchers = _settings select 0;
+ if (_removeLaunchers isEqualTo 1) then
+ {
+ _secWeapon = secondaryWeapon _target;
+ if not(_secWeapon isEqualTo "") then
+ {
+ _target removeWeaponGlobal _secWeapon;
+ _missiles = getArray (configFile >> "cfgWeapons" >> _secWeapon >> "magazines");
+ {
+ if (_x in _missiles) then
+ {
+ _target removeMagazineGlobal _x;
+ };
+ } forEach (magazines _target);
+ };
+ };
+
+
+ _killer = param [1, objNull, [objNull]];
+ if isPlayer _killer then // Only allow this function to work if killer is an actual player
+ {
+ if (vehicle _killer isEqualTo _killer) then // If killer is on foot
+ {
+ _respectReward = "respectReward" call VEMFr_fnc_getSetting;
+ if (_respectReward > 1) then
+ {
+ _message = [[]];
+ _killMsg = selectRandom ["AI WACKED","AI CLIPPED","AI DISABLED","AI DISQUALIFIED","AI WIPED","AI ERASED","AI LYNCHED","AI WRECKED","AI NEUTRALIZED","AI SNUFFED","AI WASTED","AI ZAPPED"];
+ (_message select 0) pushBack [_killMsg,_respectReward];
+ _dist = _target distance _killer;
+ switch true do
+ {
+ case (_dist <= 5):
+ {
+ (_message select 0) pushBack ["CQB Master", 25]
+ };
+ case (_dist <= 10):
+ {
+ (_message select 0) pushBack ["Close one", 15]
+ };
+ case (_dist <= 50):
+ {
+ (_message select 0) pushBack ["Danger close", 15]
+ };
+ case (_dist <= 100):
+ {
+ (_message select 0) pushBack ["Lethal aim", 20]
+ };
+ case (_dist <= 200):
+ {
+ (_message select 0) pushBack ["Deadly.", 25]
+ };
+ case (_dist <= 500):
+ {
+ (_message select 0) pushBack ["Niiiiice.", 30]
+ };
+ case (_dist <= 1000):
+ {
+ (_message select 0) pushBack ["Dat distance...", 45]
+ };
+ case (_dist <= 2000):
+ {
+ (_message select 0) pushBack ["Danger far.", 50]
+ };
+ case (_dist > 2000):
+ {
+ (_message select 0) pushBack [format["hax? %1m!!!", round _dist], 65]
+ };
+ };
+ if not(_killer isEqualTo (driver (vehicle _killer))) then
+ {
+ _killer = gunner _killer;
+ };
+ if (_killer isEqualTo (driver(vehicle _killer))) then
+ {
+ _killer = driver (vehicle _killer);
+ };
+ _curRespect = _killer getVariable ["ExileScore", 0];
+ //diag_log text format["_curRespect of _killer (%1) is %2", _killer, _curRespect];
+ _respectToGive = (((_message select 0) select 1) select 1);
+ _newRespect = _curRespect + _respectToGive + _respectReward;
+ _killer setVariable ["ExileScore", _newRespect];
+ ExileClientPlayerScore = _newRespect;
+ (owner _killer) publicVariableClient "ExileClientPlayerScore";
+ ExileClientPlayerScore = nil;
+ [_killer, "showFragRequest", _message] call ExileServer_system_network_send_to;
+ format["setAccountMoneyAndRespect:%1:%2:%3", _killer getVariable ["ExileMoney", 0], _newRespect, (getPlayerUID _killer)] call ExileServer_system_database_query_fireAndForget;
+ };
+
+ _sayKilled = "sayKilled" call VEMFr_fnc_getSetting;
+ if (_sayKilled > 0) then // Send kill message if enabled
+ {
+ _killer = param [1, objNull, [objNull]];
+ _dist = _target distance _killer;
+ if (_dist > 1) then
+ {
+ private ["_curWeapon"];
+ if (vehicle _killer isEqualTo _killer) then // If on foot
+ {
+ _curWeapon = currentWeapon _killer;
+ };
+ if not(vehicle _killer isEqualTo _killer) then // If in vehicle
+ {
+ _curWeapon = currentWeapon (vehicle _killer);
+ };
+ if (_sayKilled isEqualTo 1) then
+ {
+ _kMsg = format["(VEMFr) %1 [%2, %3m] AI", name _killer, getText(configFile >> "CfgWeapons" >> _curWeapon >> "displayName"), round _dist];
+ [_kMsg, "sys"] spawn VEMFr_fnc_broadCast;
+ };
+ if (_sayKilled isEqualTo 2) then
+ {
+ VEMFrClientMsg = [format["(VEMFr) You [%1, %2m] AI", getText(configFile >> "CfgWeapons" >> _curWeapon >> "displayName"), round _dist], "sys"];
+ (owner _killer) publicVariableClient "VEMFrClientMsg";
+ VEMFrClientMsg = nil;
+ };
+ };
+ };
+ };
+
+ if not(vehicle _killer isEqualTo _killer) then // If killer is driver
+ { // Send kill message if enabled
+ _dist = _target distance _killer;
+ if (_dist < 5) then
+ {
+ if (("sayKilled" call VEMFr_fnc_getSetting) isEqualTo 1) then
+ {
+ if (isPlayer _killer) then // Should prevent Error:NoUnit
+ {
+ _kMsg = format["(VEMFr) %1 [Roadkill] AI", name _killer];
+ //_kMsg = format["(VEMFr) %1 [%2] AI", name _killer, getText(configFile >> "CfgVehicles" >> typeOf (vehicle _killer) >> "displayName")];
+ [_kMsg, "sys"] spawn VEMFr_fnc_broadCast;
+ };
+ };
+ if (("punishRoadKills" call VEMFr_fnc_getSetting) isEqualTo 1) then
+ {
+ _respectDeduct = "respectRoadKillDeduct" call VEMFr_fnc_getSetting;
+ _curRespect = _killer getVariable ["ExileScore", 0];
+ //diag_log text format["_curRespect of _killer (%1) is %2", _killer, _curRespect];
+ _newRespect = _curRespect - _respectDeduct;
+ _killer setVariable ["ExileScore", _newRespect];
+ ExileClientPlayerScore = _newRespect;
+ (owner _killer) publicVariableClient "ExileClientPlayerScore";
+ ExileClientPlayerScore = nil;
+ [_killer, "showFragRequest", [[["ROADKILL..."],["Respect Penalty:", -_respectDeduct]]]] call ExileServer_system_network_send_to;
+ format["setAccountMoneyAndRespect:%1:%2:%3", _killer getVariable ["ExileMoney", 0], _newRespect, (getPlayerUID _killer)] call ExileServer_system_database_query_fireAndForget;
+ };
+ };
+ };
+ };
+
+ if (_settings select 2 isEqualTo 1) then // If removeHeadGear setting is enabled
+ {
+ removeHeadGear _target;
+ };
+
+ if (_settings select 1 isEqualTo 1) then // If killEffect enabled
+ {
+ playSound3D ["A3\Missions_F_Bootcamp\data\sounds\vr_shutdown.wss", _target, false, getPosASL _target, 2, 1, 60];
+ for "_u" from 1 to 12 do
+ {
+ if not(isObjectHidden _target) then
+ {
+ _target hideObjectGlobal true;
+ } else
+ {
+ _target hideObjectGlobal false;
+ };
+ uiSleep 0.12;
+ };
+ _target hideObjectGlobal true;
+ removeAllWeapons _target;
+ // Automatic cleanup yaaay
+ deleteVehicle _target;
+ };
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_broadCast.sqf b/exile_vemf_reloaded/functions/fn_broadCast.sqf
new file mode 100644
index 0000000..5785d4d
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_broadCast.sqf
@@ -0,0 +1,30 @@
+/*
+ Author: IT07
+
+ Description:
+ will alert players
+
+ Params:
+ _this select 0: FORMATTED STRING - thing to send
+ _this select 1: STRING - mode to send to client
+
+ Returns:
+ nothing
+*/
+
+private ["_msg","_mode"];
+_msg = param [0, "", [[],format[""]]];
+if not(_msg isEqualTo "") then
+{
+ _mode = param [1, "", [""]];
+ if (count allPlayers > 0) then
+ {
+ {
+ if (isPlayer _x) then
+ {
+ VEMFrClientMsg = [_msg, _mode];
+ (owner _x) publicVariableClient "VEMFrClientMsg";
+ };
+ } forEach allPlayers;
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_checkLoot.sqf b/exile_vemf_reloaded/functions/fn_checkLoot.sqf
new file mode 100644
index 0000000..4fc174b
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_checkLoot.sqf
@@ -0,0 +1,70 @@
+/*
+ Author: IT07
+
+ Description:
+ checks the VEMF loot table for invalid classnames. Reports to RPT if invalid classes found.
+
+ Params:
+ none
+
+ Returns:
+ nothing
+*/
+
+_validateLoot = if ("validateLoot" call VEMFr_fnc_getSetting isEqualTo 1) then { true } else { false };
+if _validateLoot then
+{
+ // _validateLoot is enabled, go ahead...
+ if ("debugMode" call VEMFr_fnc_getSetting isEqualTo 0) then
+ {
+ ["CheckLoot", 0, "validateLoot is enabled, but no feedback allowed by debugMode setting!"] spawn VEMFr_fnc_log;
+ };
+ ["CheckLoot", 1, "Validating loot tables..."] spawn VEMFr_fnc_log;
+ _invalidClasses = [];
+
+ _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_getSetting;
+ {
+ {
+ if not((_x in _mags) OR (_x in _weapons) OR (_x in _bags)) then
+ {
+ _invalidClasses pushBack _x;
+ };
+ } forEach _x;
+ } forEach _aiGear;
+
+ _loot = [["crateLoot"],["primaryWeaponLoot","secondaryWeaponLoot","magazinesLoot","attachmentsLoot","itemsLoot","vestsLoot","headGearLoot","backpacksLoot"]] call VEMFr_fnc_getSetting;
+ {
+ {
+ _class = _x select 0;
+ if not((_class in _mags) OR (_class in _weapons) OR (_class in _bags)) then
+ {
+ _invalidClasses pushBack _x;
+ };
+ } forEach _x;
+ } forEach _loot;
+
+ _invalid = if (count _invalidClasses isEqualTo 0) then { false } else { true };
+ switch true do
+ {
+ case _invalid:
+ {
+ ["CheckLoot", 0, format["Invalid classes found in loot! | %1", _invalidClasses]] spawn VEMFr_fnc_log;
+ };
+ case (not _invalid):
+ {
+ ["CheckLoot", 1, "Loot tables are all valid :)"] spawn VEMFr_fnc_log;
+ };
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_checkPlayerPresence.sqf b/exile_vemf_reloaded/functions/fn_checkPlayerPresence.sqf
new file mode 100644
index 0000000..96e7623
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_checkPlayerPresence.sqf
@@ -0,0 +1,40 @@
+/*
+ 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 ["_pos","_rad","_objs","_found","_isClose"]; // Prevents these variables overwriting existing vars from where this was called from
+// By default, we assume that there are no players close. The distance check below should prove otherwise if there are players close
+_found = false;
+_pos = param [0, [], [[]]];
+if (count _pos isEqualTo 3) then
+{
+ _rad = param [1, -1, [0]];
+ if (_rad > -1) then
+ { // Check all player distances from _loc
+ if (count allPlayers > 0) then
+ {
+ {
+ if (isPlayer _x) then
+ {
+ if (speed _x < 250) then // Ignore fast moving players
+ {
+ _isClose = if ((position _x distance _pos) < _rad) then { true } else { false };
+ if _isClose then { _found = true };
+ };
+ };
+ } forEach allPlayers;
+ };
+ };
+};
+
+_found
diff --git a/exile_vemf_reloaded/functions/fn_findPos.sqf b/exile_vemf_reloaded/functions/fn_findPos.sqf
new file mode 100644
index 0000000..c8b8bff
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_findPos.sqf
@@ -0,0 +1,221 @@
+/*
+ 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: OBJECT - Center for nearestLocations check
+ _this select 3: SCALAR - Max distance in meters from center to search for _pos
+ _this select 4: SCALAR - Distance in meters. Locations closer than that will be excluded
+ _this select 5: SCALAR - Max prefered distance in meters from center. If not achievable, further dest will be selected
+ _this select 6: SCALAR - Distance in meters to check from _cntr for players
+
+ Returns:
+ ARRAY - [name of town, town position]
+*/
+
+private ["_settings","_locPos","_loc","_locName","_ret","_continue","_settings","_blackList","_usedLocs","_checkRange","_tooCloseRange","_maxPrefered","_skipDistance","_nonPopulated","_mode","_pos","_hasPlayers","_blackPos","_checkBlackPos"];
+
+_ret = false;
+// Define settings
+_settings = [["nonPopulated","noMissionPos","missionDistance"]] call VEMFr_fnc_getSetting;
+_nonPopulated = _settings param [0, 1, [0]];
+_blackPos = _settings param [1, [], [[]]];
+_missionDistance = _settings param [2, 3000, [0]];
+_checkBlackPos = false;
+if (count _blackPos > 0) then
+{
+ _checkBlackPos = true;
+};
+_mode = param [0, "", [""]];
+if not(_mode isEqualTo "") then
+{
+ _onRoad = param [1, false, [false]];
+ _roadRange = 5000;
+ _cntr = param [2, [], [[]]];
+ if (count _cntr > 0) then
+ {
+ _rad = param [3, -1, [0]];
+ if (_rad > -1) then
+ {
+ _tooCloseRange = param [4, -1, [0]];
+ if (_tooCloseRange > -1) then
+ {
+ _maxPrefered = param [5, -1, [0]];
+ if (_maxPrefered > -1) then
+ {
+ _skipDistance = param [6, -1, [0]];
+ if (_skipDistance > -1) then
+ {
+ if (_mode isEqualTo "loc") then
+ {
+ // Get a list of locations close to _cntr (position of player)
+ _locs = nearestLocations [_cntr, ["Area","BorderCrossing","CityCenter","Hill","fakeTown","Name","RockArea","Strategic","StrongpointArea","ViewPoint","NameVillage","NameCity","NameCityCapital",if(_nonPopulated isEqualTo 1)then{"nameLocal"}], _rad];
+ if (count _locs > 0) then
+ {
+ _usedLocs = uiNamespace getVariable "VEMFrUsedLocs";
+ _remLocs = [];
+ _blackListMapClasses = "true" configClasses (configFile >> "CfgVemfReloaded" >> "locationBlackLists");
+ _listedMaps = []; // Define
+ { // Make a list of locationBlackLists's children
+ _listedMaps pushBack (configName _x);
+ } forEach _blackListMapClasses;
+ private ["_blackList"];
+ if (worldName in _listedMaps) then { _blackList = ([["locationBlackLists", worldName],["locations"]] call VEMFr_fnc_getSetting) select 0 };
+ if not(worldName in _listedMaps) then { _blackList = ([["locationBlackLists","Other"],["locations"]] call VEMFr_fnc_getSetting) select 0 };
+
+ { // Check _locs for invalid locations (too close, hasPlayers or inBlacklist)
+ _hasPlayers = [locationPosition _x, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
+ if _hasPlayers then
+ {
+ _remLocs pushBack _x;
+ };
+ if not _hasPlayers then
+ {
+ if _checkBlackPos then
+ {
+ private ["_locPos","_loc"];
+ _locPos = locationPosition _x;
+ _loc = _x;
+ {
+ if (count _x isEqualTo 2) then
+ {
+ _pos = _x param [0, [0,0,0], [[]]];
+ if not(_pos isEqualTo [0,0,0]) then
+ {
+ _range = _x param [1, 600, [0]];
+ if ((_pos distance _locPos) < _range) then
+ {
+ _remLocs pushBack _loc;
+ };
+ };
+ };
+ if not(count _x isEqualTo 2) then
+ {
+ ["fn_findPos", 0, format["found invalid entry in mission blacklist: %1", _x]] spawn VEMFr_fnc_log;
+ };
+ } forEach _blackPos;
+ };
+ if ((text _x) in _blackList) then
+ {
+ _remLocs pushBack _x;
+ };
+ if not((text _x) in _blackList) then
+ {
+ if (_cntr distance (locationPosition _x) < _tooCloseRange) then
+ {
+ _remLocs pushBack _x;
+ };
+ if (_cntr distance (locationPosition _x) > _tooCloseRange) then
+ {
+ if (([text _x, locationPosition _x]) in _usedLocs) then
+ {
+ _remLocs pushBack _x;
+ };
+ };
+ };
+ if (count _usedLocs > 0) then
+ {
+ private ["_loc"];
+ _loc = _x;
+ {
+ if (((locationPosition _loc) distance (_x select 1)) < _missionDistance) then
+ {
+ _remLocs pushBack _loc;
+ };
+ } forEach _usedLocs;
+ };
+ };
+ } forEach _locs;
+
+ { // Remove all invalid locations from _locs
+ _index = _locs find _x;
+ _locs deleteAt _index;
+ } forEach _remLocs;
+
+ // Check what kind of distances we have
+ _far = []; // Further than _maxPrefered
+ _pref = []; // Closer then _maxPrefered
+ {
+ _dist = _cntr distance (locationPosition _x);
+ if (_dist > _maxPrefered) then
+ {
+ _far pushBack _x;
+ };
+ if (_dist < _maxPrefered) then
+ {
+ _pref pushBack _x;
+ };
+ } forEach _locs;
+
+ // Check if there are any prefered locations. If yes, randomly select one
+ if (count _pref > 0) then
+ {
+ _loc = selectRandom _pref;
+ };
+
+ // Check if _far has any locations and if _pref is empty
+ if (count _far > 0) then
+ {
+ if (count _pref isEqualTo 0) then
+ {
+ _loc = selectRandom _far;
+ };
+ };
+
+ // Validate _locs just to prevent the .RPT from getting spammed
+ if (count _locs > 0) then
+ {
+ // Return Name and POS
+ _ret = [text _loc, locationPosition _loc];
+ (uiNamespace getVariable "VEMFrUsedLocs") pushBack _ret;
+ };
+ };
+ };
+ if (_mode isEqualTo "pos") then
+ {
+ _valid = false;
+ for "_p" from 1 to 10 do
+ {
+ if (_ret isEqualType true) then
+ {
+ if not _ret then
+ {
+ _pos = [_cntr, _tooCloseRange, _rad, 2, 0, 500, 0] call BIS_fnc_findSafePos;
+ if _onRoad then
+ {
+ _roads = _pos nearRoads _roadRange;
+ if (count _roads > 0) then
+ {
+ private ["_closest","_dist"];
+ _closest = ["", _roadRange];
+ { // Find the closest road
+ _dist = _x distance _pos;
+ if (_dist < (_closest select 1)) then
+ {
+ _closest = [_x, _dist];
+ };
+ } forEach _roads;
+ _pos = position (_closest select 0);
+ };
+ };
+ _hasPlayers = [_pos, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
+ if not(_hasPlayers) then
+ {
+ _ret = _pos;
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+};
+
+_ret
diff --git a/exile_vemf_reloaded/functions/fn_getSetting.sqf b/exile_vemf_reloaded/functions/fn_getSetting.sqf
new file mode 100644
index 0000000..73f2e7a
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_getSetting.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["_cfg","_v","_r","_path","_check"];
+_r = [];
+_check =
+{
+ if (isNumber _cfg) then
+ {
+ _v = getNumber _cfg
+ };
+ if not(isNumber _cfg) then
+ {
+ if (isText _cfg) then
+ {
+ _v = getText _cfg
+ };
+ if not(isText _cfg) then
+ {
+ if (isArray _cfg) then
+ {
+ _v = getArray _cfg
+ };
+ };
+ };
+};
+
+if (_this isEqualType "") then
+{
+ _cfg = configFile >> "CfgVemfReloaded" >> _this;
+ call _check;
+ if not(isNil"_v") then
+ {
+ _r = _v;
+ };
+};
+
+if (_this isEqualType []) then
+{
+ if (count _this isEqualTo 2) then
+ {
+ _cfg = configFile >> "CfgVemfReloaded";
+ _path = _cfg;
+ {
+ _path = _path >> _x; // Build the config path
+ } forEach (_this select 0);
+ {
+ _cfg = _path >> _x;
+ call _check;
+ if not isNil"_v" then
+ {
+ _r pushBack _v
+ };
+ } forEach (_this select 1);
+ };
+ if (count _this isEqualTo 1) then
+ {
+ {
+ _cfg = configFile >> "CfgVemfReloaded" >> _x;
+ call _check;
+ _r pushBack _v;
+ } forEach (_this select 0);
+ };
+};
+
+if isNil"_v" then { _r = nil };
+_r
diff --git a/exile_vemf_reloaded/functions/fn_giveAmmo.sqf b/exile_vemf_reloaded/functions/fn_giveAmmo.sqf
new file mode 100644
index 0000000..b7a3e1f
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_giveAmmo.sqf
@@ -0,0 +1,119 @@
+/*
+ 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
+
+ Returns:
+ BOOLEAN - true if successful
+*/
+
+private ["_done"];
+_done = false;
+if (_this isEqualType []) then
+{
+ private ["_unit"];
+ _unit = param [0, objNull, [objNull]];
+ if not isNull _unit then
+ {
+ if local _unit then
+ {
+ if not(primaryWeapon _unit isEqualTo "") then
+ {
+ if not(vest _unit isEqualTo "") then
+ {
+ private ["_itemMass","_weapon","_mag","_magMass","_vestMass","_itemMass"];
+ _weapon = primaryWeapon _unit;
+ _mag = selectRandom (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines"));
+ _magMass = getNumber (configFile >> "CfgMagazines" >> _mag >> "mass");
+ _vestMass = getNumber (configFile >> "CfgWeapons" >> (vest _unit) >> "ItemInfo" >> "mass");
+ {
+ _itemMass = getNumber (configFile >> "CfgMagazines" >> _x >> "ItemInfo" >> "mass");
+ if (_itemMass isEqualTo 0) then
+ {
+ _itemMass = getNumber (configFile >> "CfgWeapons" >> _x >> "WeaponSlotsInfo" >> "mass");
+ };
+ _vestMass = _vestMass - _itemMass;
+ } forEach (vestItems _unit);
+ if (_vestMass >= _magMass) then
+ {
+ for "_m" from 1 to (round(_vestMass / _magMass)) do
+ {
+ _unit addItemToVest _mag;
+ };
+ };
+ };
+ };
+ if not (secondaryWeapon _unit isEqualTo "") then
+ {
+ if not(backPack _unit isEqualTo "") then
+ {
+ private ["_weapon","_mag","_magMass"];
+ _weapon = secondaryWeapon _unit;
+ _mag = selectRandom (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines"));
+ _magMass = getNumber (configFile >> "CfgMagazines" >> _mag >> "mass");
+ if not(backpack _unit isEqualTo "") then
+ {
+ private ["_packMass"];
+ _packMass = getNumber (configFile >> "CfgVehicles" >> (backpack _unit) >> "mass");
+ {
+ private ["_itemMass"];
+ _itemMass = getNumber (configFile >> "CfgMagazines" >> _x >> "mass");
+ if (_itemMass isEqualTo 0) then
+ {
+ _itemMass = getNumber (configFile >> "CfgWeapons" >> _x >> "WeaponSlotsInfo" >> "mass");
+ };
+ _packMass = _packMass - _itemMass;
+ } forEach (backpackItems _unit);
+ if (_packMass >= _magMass) then
+ {
+ for "_m" from 1 to (round(_packMass / _magMass)) do
+ {
+ _unit addItemToBackpack _mag;
+ };
+ };
+ };
+ };
+ };
+ if not (handGunWeapon _unit isEqualTo "") then
+ {
+ if not(uniform _unit isEqualTo "") then
+ {
+ private ["_weapon","_mag","_uniformMass"];
+ _weapon = handGunWeapon _unit;
+ _mag = selectRandom (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines"));
+ _magMass = getNumber (configFile >> "CfgMagazines" >> _mag >> "mass");
+ _uniformMass = getNumber (configFile >> "CfgWeapons" >> (uniform _unit) >> "ItemInfo" >> "mass");
+ {
+ private ["_itemMass"];
+ _itemMass = getNumber (configFile >> "CfgMagazines" >> _x >> "mass");
+ if (_itemMass isEqualTo 0) then
+ {
+ _itemMass = getNumber (configFile >> "CfgWeapons" >> _x >> "WeaponSlotsInfo" >> "mass");
+ };
+ _uniformMass = _uniformMass - _itemMass;
+ } forEach (uniformItems _unit);
+ for "_m" from 1 to (round(_uniformMass / _magMass)) do
+ {
+ _unit addItemToUniform _mag;
+ };
+ };
+ };
+ _done = true;
+ };
+ if not local _unit then
+ {
+ ["fn_giveAmmo", 0, format["%1 is not local. Can not execute!", _unit]] spawn VEMfr_fnc_log;
+ };
+ };
+ if isNull _unit then
+ {
+ ["fn_giveAmmo", 0, "_unit isNull. Can not execute!"] spawn VEMFr_fnc_log;
+ };
+};
+
+_done
diff --git a/exile_vemf_reloaded/functions/fn_giveWeaponItems.sqf b/exile_vemf_reloaded/functions/fn_giveWeaponItems.sqf
new file mode 100644
index 0000000..1f083d7
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_giveWeaponItems.sqf
@@ -0,0 +1,78 @@
+/*
+ Author: IT07
+
+ Description:
+ Gives random weapon attachments to given unit
+
+ Params:
+ _this: ARRAY
+ _this select 0: OBJECT - unit
+
+ Returns: BOOLEAN - if not isNull _unit, returns true
+*/
+
+private ["_done","_unit","_randomPattern","_primaryWeapon","_unit","_handgunWeapon"];
+_done = false;
+if (_this isEqualType []) then
+{
+ _unit = param [0, objNull, [objNull]];
+ if not (isNull _unit) then
+ {
+ // primaryWeapon items
+ private ["_randomPattern"];
+ _randomPattern = [1,0,1,0,1,1,1,1,0,0,1,1,1];
+ _primaryWeapon = primaryWeapon _unit;
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random scope
+ _scopes = getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems");
+ if ([["DynamicLocationInvasion"],["allowTWS"]] call VEMFr_fnc_getSetting isEqualTo 0) then
+ {
+ private["_indexes"];
+ _indexes = [];
+ {
+ if not(_x find "tws" isEqualTo -1) then
+ {
+ _indexes pushBack _forEachIndex;
+ };
+ if not(_x find "TWS" isEqualTo -1) then
+ {
+ _indexes pushBack _forEachIndex;
+ };
+ } forEach _scopes;
+ if (count _indexes > 0) then
+ {
+ {
+ _scopes deleteAt _x;
+ } forEach _indexes;
+ };
+ };
+ _unit addPrimaryWeaponItem (selectRandom _scopes);
+ };
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random muzzle
+ _unit addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems")));
+ };
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random pointer
+ _unit addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "WeaponSlotsInfo" >> "PointerSlot" >> "compatibleItems")));
+ };
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random bipod
+ _unit addPrimaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "WeaponSlotsInfo" >> "UnderbarrelSlot" >> "compatibleItems")));
+ };
+
+ // handgunWeapon items
+ _handgunWeapon = handgunWeapon _unit;
+ _randomPattern = [1,0,1,0,0,1,0,0,0,0,1,1,1];
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random scope
+ _unit addSecondaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _handgunWeapon >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems")));
+ };
+ if (selectRandom _randomPattern isEqualTo 1) then
+ { // Select random muzzle
+ _unit addSecondaryWeaponItem (selectRandom (getArray (configFile >> "CfgWeapons" >> _handgunWeapon >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems")));
+ };
+ _done = true;
+ };
+};
+_done
diff --git a/exile_vemf_reloaded/functions/fn_headLessClient.sqf b/exile_vemf_reloaded/functions/fn_headLessClient.sqf
new file mode 100644
index 0000000..ac77a75
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_headLessClient.sqf
@@ -0,0 +1,52 @@
+/*
+ Author: IT07
+
+ Description:
+ selects a headless client with least (VEMF) load
+
+ Params:
+ None
+
+ Returns:
+ OBJECT - the headless client
+*/
+
+if (("headLessClientSupport" call VEMFr_fnc_getSetting) isEqualTo 1) then
+{
+ // Ok, Headless Clients enabled. let us continue
+ _hcList = "headLessClientNames" call VEMFr_fnc_getSetting;
+ // We have the names now, check if any of them is actually ingame
+ _ingameHCs = [];
+ {
+ if (typeOf _x isEqualTo "HeadlessClient_F") then
+ {
+ if (_x in _hcList) then
+ {
+ _ingameHCs pushBack [_x, name _x];
+ };
+ };
+ } forEach allPlayers;
+ if (count _ingameHCs > 0) then
+ {
+ // At least 1 of given headless clients is ingame, lets check their load
+ _globalLoad = uiNamespace getVariable "VEMFrHcLoad";
+ _lowestLoad = 99999;
+ _hasLowest = "";
+ { // Find the lowest load number
+ _load = _x select 1;
+ if (_load < _lowestLoad) then
+ {
+ _lowestLoad = _load;
+ _hasLowest = _x select 0;
+ };
+ } forEach _globalLoad;
+ // HC with lowest load found, add +1 to its current load
+ _index = _globalLoad find [_hasLowest, _lowestLoad];
+ if (_index > -1) then
+ {
+ _globalLoad set [_index,[_hasLowest, _lowestLoad +1]]
+ };
+ };
+};
+// Lowest load found, send it
+_hasLowest
diff --git a/exile_vemf_reloaded/functions/fn_launch.sqf b/exile_vemf_reloaded/functions/fn_launch.sqf
new file mode 100644
index 0000000..24055f2
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_launch.sqf
@@ -0,0 +1,15 @@
+/*
+ Author: IT07
+
+ Description:
+ launches VEMFr (You don't say?)
+*/
+
+["Launcher", 2, format["/// STARTING v%1 \\\", getNumber (configFile >> "CfgPatches" >> "Exile_VEMF_Reloaded" >> "version")]] spawn VEMFr_fnc_log;
+uiNamespace setVariable ["VEMFrUsedLocs", []];
+uiNamespace setVariable ["VEMFrHcLoad", []];
+[] spawn VEMFr_fnc_checkLoot; // Check loot tables if enabled
+[] spawn VEMFr_fnc_missionTimer; // Launch mission timer
+[] spawn VEMFr_fnc_spawnStaticAI; // Launch Static AI spawner
+west setFriend [independent, 0];
+independent setFriend [west, 0];
diff --git a/exile_vemf_reloaded/functions/fn_loadInv.sqf b/exile_vemf_reloaded/functions/fn_loadInv.sqf
new file mode 100644
index 0000000..6d08f4b
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_loadInv.sqf
@@ -0,0 +1,220 @@
+/*
+ Author: VAMPIRE, rebooted by IT07
+
+ Description:
+ loads AI inventory
+
+ Param:
+ _this: ARRAY
+ _this select 0: ARRAY - units to load inventory for
+ _this select 1: STRING - what type of mission the loadout should be for
+ _this select 2: SCALAR - inventory mode
+
+ Returns:
+ BOOLEAN - true if nothing failed
+*/
+
+private ["_ok","_params","_units","_mode","_settings","_aiLaunchers","_aiGear","_uniforms","_headGear","_vests","_backpacks","_launchers","_rifles","_pistols","_aiMode","_givenAmmo"];
+_ok = false;
+_params = _this;
+if (_this isEqualType []) then
+{
+ _units = param [0, [], [[]]];
+ if (count _units > 0) then
+ {
+ _mode = param [1, "", [""]];
+ if not(_mode isEqualTo "") then
+ {
+ _aiMode = param [2, 0, [0]];
+ if (_aiMode isEqualTo 0) then
+ {
+ // Define settings
+ _aiGear = [["aiGear"],["aiUniforms","aiHeadGear","aiVests","aiBackpacks","aiLaunchers","aiRifles","aiPistols"]] call VEMFr_fnc_getSetting;
+ _uniforms = _aiGear select 0;
+ _headGear = _aiGear select 1;
+ _vests = _aiGear select 2;
+ _backpacks = _aiGear select 3;
+ _rifles = _aiGear select 5;
+ _pistols = _aiGear select 6;
+ _aiLaunchers = ([["DynamicLocationInvasion"],["aiLaunchers"]] call VEMFr_fnc_getSetting) select 0;
+ if (_aiLaunchers isEqualTo 1) then
+ {
+ _launchers = _aiGear select 4;
+ };
+ {
+ private ["_unit","_gear","_ammo"];
+ _unit = _x;
+ // Strip it
+ removeAllWeapons _unit;
+ removeAllItems _unit;
+ if ("removeAllAssignedItems" call VEMFr_fnc_getSetting isEqualTo 1) then
+ {
+ removeAllAssignedItems _unit;
+ };
+ removeUniform _unit;
+ removeVest _unit;
+ removeBackpack _unit;
+ removeGoggles _unit;
+ removeHeadGear _unit;
+
+ _gear = selectRandom _uniforms;
+ _unit forceAddUniform _gear; // Give the poor naked guy some clothing :)
+
+ _gear = selectRandom _headGear;
+ _unit addHeadGear _gear;
+
+ _gear = selectRandom _vests;
+ _unit addVest _gear;
+
+ if ((floor random 2) isEqualTo 0) then
+ {
+ _gear = selectRandom _backpacks;
+ _unit addBackpack _gear;
+ if (_aiLaunchers isEqualTo 1) then
+ {
+ if ((floor random 4) isEqualTo 0) then
+ {
+ private ["_ammo"];
+ _gear = selectRandom _launchers;
+ _unit addWeapon _gear;
+ _ammo = getArray (configFile >> "cfgWeapons" >> _gear >> "magazines");
+ if (count _ammo > 2) then
+ {
+ _ammo resize 2;
+ };
+ for "_i" from 0 to (2 + (round random 1)) do
+ {
+ _unit addMagazine (selectRandom _ammo);
+ };
+ };
+ };
+ };
+
+ // Add Weapons & Ammo
+ _gear = selectRandom _rifles;
+ _unit addWeapon _gear;
+ _unit selectWeapon _gear;
+
+ _gear = selectRandom _pistols;
+ _unit addWeapon _gear;
+
+ // Give this guy some ammo
+ _givenAmmo = [_unit] call VEMFr_fnc_giveAmmo;
+ if not _givenAmmo then
+ {
+ ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _unit]] spawn VEMFr_fnc_log;
+ };
+ // Give this guy some weaponItems
+ _giveAttachments = [_unit] call VEMFr_fnc_giveWeaponItems;
+ if not _giveAttachments then
+ {
+ ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _unit]] spawn VEMFr_fnc_log;
+ };
+
+ } forEach _units;
+ _ok = true;
+ };
+
+ if (_aiMode isEqualTo 1) then
+ {
+ private ["_policeGear","_headGear","_vests"];
+ _policeGear = [["policeConfig"],["headGear","vests","uniforms","rifles","pistols","backpacks"]] call VEMFr_fnc_getSetting;
+ _headGear = _policeGear select 0;
+ _vests = _policeGear select 1;
+ _uniforms = _policeGear select 2;
+ _rifles = _policeGear select 3;
+ _pistols = _policeGear select 4;
+ _backpacks = _policeGear select 5;
+ {
+ _unit = _x;
+ // Strip it
+ removeAllWeapons _unit;
+ removeAllItems _unit;
+ if ("removeAllAssignedItems" call VEMFr_fnc_getSetting isEqualTo 1) then
+ {
+ removeAllAssignedItems _unit;
+ };
+ removeUniform _unit;
+ removeVest _unit;
+ removeBackpack _unit;
+ removeGoggles _unit;
+ removeHeadGear _unit;
+
+ _hat = selectRandom _headGear;
+ _unit addHeadGear _hat;
+ _vest = selectRandom _vests;
+ _unit addVest _vest;
+ _uniform = selectRandom _uniforms;
+ _unit forceAddUniform _uniform;
+ _rifle = selectRandom _rifles;
+ _unit addWeapon _rifle;
+ _unit selectWeapon _rifle;
+ _pistol = selectRandom _pistols;
+ _unit addWeapon _pistol;
+ _backpack = selectRandom _backpacks;
+ _unit addBackPack _backpack;
+
+ // Give this guy some ammo
+ _givenAmmo = [_unit] call VEMFr_fnc_giveAmmo;
+ if not _givenAmmo then
+ {
+ ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _unit]] spawn VEMFr_fnc_log;
+ };
+ // Give this guy some weaponItems
+ _giveAttachments = [_unit] call VEMFr_fnc_giveWeaponItems;
+ if not _giveAttachments then
+ {
+ ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _unit]] spawn VEMFr_fnc_log;
+ };
+ } forEach _units;
+ };
+
+ if (_aiMode isEqualTo 2) then
+ {
+ private ["_policeGear","_headGear","_vests"];
+ _policeGear = [["policeConfig"],["rifles","pistols"]] call VEMFr_fnc_getSetting;
+ _rifles = _policeGear select 0;
+ _pistols = _policeGear select 1;
+ {
+ _unit = _x;
+ // Strip it
+ removeAllWeapons _unit;
+ removeAllItems _unit;
+ if ("removeAllAssignedItems" call VEMFr_fnc_getSetting isEqualTo 1) then
+ {
+ removeAllAssignedItems _unit;
+ };
+ removeUniform _unit;
+ removeVest _unit;
+ removeBackpack _unit;
+ removeGoggles _unit;
+ removeHeadGear _unit;
+ _unit addHeadGear "H_HelmetB_light_black";
+ _unit addGoggles "G_Balaclava_blk";
+ _unit addVest "V_PlateCarrier2_blk";
+ _unit forceAddUniform "Exile_Uniform_ExileCustoms";
+ _rifle = selectRandom _rifles;
+ _unit addWeapon _rifle;
+ _unit selectWeapon _rifle;
+ _pistol = selectRandom _pistols;
+ _unit addWeapon _pistol;
+
+ // Give this guy some ammo
+ _givenAmmo = [_unit] call VEMFr_fnc_giveAmmo;
+ if not _givenAmmo then
+ {
+ ["fn_loadInv", 0, format["FAILED to give ammo to AI: %1", _unit]] spawn VEMFr_fnc_log;
+ };
+ // Give this guy some weaponItems
+ _giveAttachments = [_unit] call VEMFr_fnc_giveWeaponItems;
+ if not _giveAttachments then
+ {
+ ["fn_loadInv", 0, format["FAILED to giveWeaponItems to %1", _unit]] spawn VEMFr_fnc_log;
+ };
+ } forEach _units;
+ };
+ };
+ };
+};
+
+_ok
diff --git a/exile_vemf_reloaded/functions/fn_loadLoot.sqf b/exile_vemf_reloaded/functions/fn_loadLoot.sqf
new file mode 100644
index 0000000..a63a603
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_loadLoot.sqf
@@ -0,0 +1,143 @@
+/*
+ Author: VAMPIRE, rebooted by IT07
+
+ Description:
+ loads loot crate inventory
+
+ Returns:
+ BOOL - true if everything went ok
+*/
+private
+[
+ "_crate","_settings","_loot","_amount","_quant","_prim","_sec","_mags","_att","_items","_vests","_packs","_primaries","_secondaries",
+ "_magazines","_attachments","_items","_vests","_backpacks","_headGear","_blackList","_maxPrim","_minPrim","_maxSec","_minSec",
+ "_maxMagSlots","_minMagSlots","_maxAttSlots","_minAttSlots","_maxItemSlots","_minItemSlots","_maxVestSlots","_minVestSlots",
+ "_maxHeadGearSlots","_minHeadGearSlots","_maxBagSlots","_minBagSlots","_ok"
+];
+
+_ok = false;
+// Define _vars
+_crate = param [0, objNull, [objNull]];
+if not isNull _crate then
+{
+ clearWeaponCargoGlobal _crate;
+ clearMagazineCargoGlobal _crate;
+ clearBackpackCargoGlobal _crate;
+ clearItemCargoGlobal _crate;
+ _settings =
+ [
+ ["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_getSetting;
+ _maxPrim = _settings select 0;
+ _minPrim = _settings select 1;
+ _maxSec = _settings select 2;
+ _minSec = _settings select 3;
+ _maxMagSlots = _settings select 4;
+ _minMagSlots = _settings select 5;
+ _maxAttSlots = _settings select 6;
+ _minAttSlots = _settings select 7;
+ _maxItemSlots = _settings select 8;
+ _minItemSlots = _settings select 9;
+ _maxVestSlots = _settings select 10;
+ _minVestSlots = _settings select 11;
+ _maxHeadGearSlots = _settings select 12;
+ _minHeadGearSlots = _settings select 13;
+ _maxBagSlots = _settings select 14;
+ _minBagSlots = _settings select 15;
+ _primaries = _settings select 16;
+ _secondaries = _settings select 17;
+ _magazines = _settings select 18;
+ _attachments = _settings select 19;
+ _items = _settings select 20;
+ _vests = _settings select 21;
+ _backpacks = _settings select 22;
+ _headGear = _settings select 23;
+ _blackList = _settings select 24;
+
+ // Add primary weapons
+ for "_j" from 0 to (_maxPrim - _minPrim + floor random _minPrim) do
+ {
+ _prim = _primaries call BIS_fnc_selectRandom;
+ if not((_prim select 0) in _blackList) then
+ {
+ _crate addWeaponCargoGlobal [_prim select 0, _prim select 1];
+ };
+ };
+
+ // Secondary weapons
+ for "_j" from 0 to (_maxSec - _minSec + floor random _minSec) do
+ {
+ _sec = _secondaries call BIS_fnc_selectRandom;
+ if not((_sec select 0) in _blackList) then
+ {
+ _crate addWeaponCargoGlobal [_sec select 0, _sec select 1];
+ };
+ };
+
+ // Magazines
+ for "_j" from 0 to (_maxMagSlots - _minMagSlots + floor random _minMagSlots) do
+ {
+ _mag = _magazines call BIS_fnc_selectRandom;
+ if not((_mag select 0) in _blackList) then
+ {
+ _crate addMagazineCargoGlobal [_mag select 0, _mag select 1];
+ };
+ };
+
+ // Weapon attachments
+ for "_j" from 0 to (_maxAttSlots - _minAttSlots + floor random _minAttSlots) do
+ {
+ _att = _attachments call BIS_fnc_selectRandom;
+ if not((_att select 0) in _blackList) then
+ {
+ _crate addItemCargoGlobal [_att select 0, _att select 1];
+ };
+ };
+
+ // Items
+ for "_j" from 0 to (_maxItemSlots - _minItemSlots + floor random _minItemSlots) do
+ {
+ _item = _items call BIS_fnc_selectRandom;
+ if not((_item select 0) in _blacklist) then
+ {
+ _crate addItemCargoGlobal [_item select 0, _item select 1];
+ };
+ };
+
+ // Vests
+ for "_j" from 0 to (_maxVestSlots - _minVestSlots + floor random _minVestSlots) do
+ {
+ _vest = _vests call BIS_fnc_selectRandom;
+ if not((_vest select 0) in _blackList) then
+ {
+ _crate addItemCargoGlobal [_vest select 0, _vest select 1];
+ };
+ };
+
+ // Helmets / caps / berets / bandanas
+ for "_j" from 0 to (_maxHeadGearSlots - _minHeadGearSlots + floor random _minHeadGearSlots) do
+ {
+ _headGearItem = _headGear call BIS_fnc_selectRandom;
+ if not((_headGearItem select 0) in _blackList) then
+ {
+ _crate addItemCargoGlobal [_headGearItem select 0, _headGearItem select 1];
+ };
+ };
+
+ // Backpacks
+ for "_j" from 0 to (_maxBagSlots - _minBagSlots + floor random _minBagSlots) do
+ {
+ _pack = _backpacks call BIS_fnc_selectRandom;
+ if not((_pack select 0) in _blackList) then
+ {
+ _crate addBackpackCargoGlobal [_pack select 0, _pack select 1];
+ };
+ };
+ _ok = true;
+};
+_ok
diff --git a/exile_vemf_reloaded/functions/fn_log.sqf b/exile_vemf_reloaded/functions/fn_log.sqf
new file mode 100644
index 0000000..0b9745e
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_log.sqf
@@ -0,0 +1,37 @@
+/*
+ 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)
+*/
+
+private ["_param","_prefix","_mode","_logThis","_logModesAllowed","_loggingEnabled"];
+_loggingEnabled = "debugMode" call VEMFr_fnc_getSetting;
+if (_loggingEnabled > 0) then
+{
+ if (_loggingEnabled < 4) then
+ {
+ _type = param [1, 3, [0]];
+ _line = param [2, "", [""]];
+ if (_type < _loggingEnabled) then
+ {
+ if not(_line isEqualTo "") then
+ {
+ diag_log text format["IT07: [exile_vemf_reloaded] %1", _line];
+ };
+ };
+ if (_type isEqualTo 2) then // Always allow log type 2 no matter which debugMode is set
+ {
+ diag_log text format["IT07: [exile_vemf_reloaded] %1", _line];
+ };
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_missionTimer.sqf b/exile_vemf_reloaded/functions/fn_missionTimer.sqf
new file mode 100644
index 0000000..d31b32e
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_missionTimer.sqf
@@ -0,0 +1,85 @@
+/*
+ Author: IT07
+
+ Description:
+ Handles the start and timeout of missions
+
+ Params:
+ none
+
+ Returns:
+ nothing
+*/
+
+_minFPS = "minServerFPS" call VEMFr_fnc_getSetting;
+if (_minFPS > -1) then
+{
+ _minPlayers = "minPlayers" call VEMFr_fnc_getSetting;
+ if (_minPlayers > -1) then
+ {
+ _maxGlobalMissions = "maxGlobalMissions" call VEMFr_fnc_getSetting;
+ if (_maxGlobalMissions > -2) then
+ {
+ _minNew = "minNew" call VEMFr_fnc_getSetting;
+ if (_minNew > -1) then
+ {
+ _maxNew = "maxNew" call VEMFr_fnc_getSetting;
+ if (_maxNew > 0) then
+ {
+ _missionList = "missionList" call VEMFr_fnc_getSetting;
+ if (count _missionList > 0) then
+ {
+ waitUntil { uiSleep 5; (if (([_minPlayers] call VEMFr_fnc_playerCount) AND (diag_fps > _minFPS)) then { true } else { false }) };
+ ["missionTimer", 1, format["Minimal player count of %1 reached! Starting timer...", _minPlayers]] spawn VEMFr_fnc_log;
+
+ VEMFr_missionCount = 0;
+ private ["_ignoreLimit"];
+ _ignoreLimit = false;
+ if (_maxGlobalMissions isEqualTo 0) then
+ {
+ _ignoreLimit = true;
+ };
+ while {true} do
+ {
+ // Wait random amount
+ uiSleep ((_minNew*60)+ floor random ((_maxNew*60)-(_minNew*60)));
+
+ // Pick A Mission if enough players online
+ if ([_minPlayers] call VEMFr_fnc_playerCount) then
+ {
+ if _ignoreLimit then
+ {
+ _missVar = selectRandom _missionList;
+ [] execVM format["exile_vemf_reloaded\missions\%1.sqf", _missVar];
+ _lastMission = serverTime;
+ };
+ if not _ignoreLimit then
+ {
+ if (VEMFr_missionCount <= _maxGlobalMissions) then
+ {
+ _missVar = selectRandom _missionList;
+ [] execVM format["exile_vemf_reloaded\missions\%1.sqf", _missVar];
+ VEMFr_missionCount = VEMFr_missionCount +1;
+ _lastMission = serverTime;
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ if (_maxGlobalMissions < -1) then
+ {
+ ["missionTimer", 0, format["Invalid maximum global missions number! it is: %1", _maxGlobalMissions]] spawn VEMFr_fnc_log;
+ };
+ };
+ if (_minPlayers < 0) then
+ {
+ ["missionTimer", 0, format["Invalid minimum player setting of %1", _minPlayers]] spawn VEMFr_fnc_log;
+ };
+};
+if (_minFPS < 0) then
+{
+ ["missionTimer", 0, format["Invalid minimum server FPS setting of %1", _minFPS]] spawn VEMFr_fnc_log;
+};
diff --git a/exile_vemf_reloaded/functions/fn_placeMines.sqf b/exile_vemf_reloaded/functions/fn_placeMines.sqf
new file mode 100644
index 0000000..454843a
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_placeMines.sqf
@@ -0,0 +1,52 @@
+/*
+ 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)
+
+ Returns:
+ BOOL - true if all OK
+*/
+
+private ["_ok","_enabled","_pos","_min","_max","_amount","_minePos","_mine","_mines","_mines","_mineTypes"];
+_ok = false;
+_enabled = ([["DynamicLocationInvasion"],["mines"]] call VEMFr_fnc_getSetting) select 0;
+if (_enabled > 0) then
+{
+ _pos = param [0, [], [[]]];
+ if (count _pos isEqualTo 3) then
+ {
+ _min = param [1, -1, [0]];
+ if (_min > -1) then
+ {
+ _max = param [2, -1, [0]];
+ if (_max > _min) then
+ {
+ _amount = ([["DynamicLocationInvasion"],["minesAmount"]] call VEMFr_fnc_getSetting) select 0;
+ if (_amount > -1) then
+ {
+ _mines = [["DynamicLocationInvasion"],["mines"]] call VEMFr_fnc_getSetting param [0, 1, [0]];
+ if (_mines isEqualTo 1) then { _mineTypes = ["ATMine"] };
+ if (_mines isEqualTo 2) then { _mineTypes = ["APERSMine"] };
+ if (_mines isEqualTo 3) then { _mineTypes = ["ATMine","APERSMine"] };
+ _mines = [];
+ ["fn_placeMines", 1, format["Placing %1 mines at %2", _amount, _pos]] spawn VEMFr_fnc_log;
+ for "_m" from 1 to _amount do
+ {
+ _mine = createMine [selectRandom _mineTypes, ([_pos, _min, _max, 2, 0, 20, 0] call BIS_fnc_findSafePos), [], 0];
+ uiSleep 0.5;
+ _mines pushBack _mine;
+ };
+ _ok = [_mines];
+ };
+ };
+ };
+ };
+};
+
+_ok
diff --git a/exile_vemf_reloaded/functions/fn_playerCount.sqf b/exile_vemf_reloaded/functions/fn_playerCount.sqf
new file mode 100644
index 0000000..93c3f8d
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_playerCount.sqf
@@ -0,0 +1,38 @@
+/*
+ Author: IT07
+
+ Description:
+ checks if player count is above or equal to given number. If no number given, default of 1 will be used.
+
+ Params:
+ none
+
+ Returns:
+ ARRAY - [false if current player count is below minimum, true if (more than OR equalTo) minimum]
+*/
+
+private ["_minimum","_players","_ok"];
+_ok = false;
+if (_this isEqualType []) then
+{
+ _minimum = param [0, -1, [0]];
+ if (_minimum > -1) then
+ {
+ if (count allPlayers >= _minimum) then
+ {
+ _players = 0;
+ {
+ if (isPlayer _x) then
+ {
+ _players = _players + 1;
+ };
+ } forEach allPlayers;
+ if not(_players isEqualTo 0) then
+ {
+ _ok = true
+ };
+ };
+ };
+};
+
+_ok
diff --git a/exile_vemf_reloaded/functions/fn_signAI.sqf b/exile_vemf_reloaded/functions/fn_signAI.sqf
new file mode 100644
index 0000000..c69940b
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_signAI.sqf
@@ -0,0 +1,23 @@
+/*
+ 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:
+ BOOL - true if OK
+*/
+
+private["_signed","_abort"];
+_ok = false;
+_group = param [0, grpNull, [grpNull]];
+if not isNull _group then
+{
+ (uiNamespace getVariable "vemfGroups") pushBack _group;
+ _ok = true
+};
+_ok
diff --git a/exile_vemf_reloaded/functions/fn_spawnAI.sqf b/exile_vemf_reloaded/functions/fn_spawnAI.sqf
new file mode 100644
index 0000000..6b6430b
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_spawnAI.sqf
@@ -0,0 +1,235 @@
+/*
+ Author: original by Vampire, completely rewritten by IT07
+
+ Description:
+ spawns AI using given _pos 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
+
+ Returns:
+ ARRAY of UNITS
+*/
+
+private // Make sure that the vars in this function do not interfere with vars in the calling script
+[
+ "_pos","_grpCount","_unitsPerGrp","_sldrClass","_groups","_settings","_hc","_skills","_newPos","_return","_waypoints","_wp","_cyc","_units",
+ "_accuracy","_aimShake","_aimSpeed","_stamina","_spotDist","_spotTime","_courage","_reloadSpd","_commanding","_general","_loadInv","_noHouses","_cal50sVehs","_mode"
+];
+
+_spawned = [[],[]];
+_pos = param [0, [], [[]]];
+if (count _pos isEqualTo 3) then
+{
+ _grpCount = param [1, 1, [0]];
+ if (_grpCount > 0) then
+ {
+ _unitsPerGrp = param [2, 1, [0]];
+ if (_unitsPerGrp > 0) then
+ {
+ _mode = param [3, -1, [0]];
+ _sldrClass = "unitClass" call VEMFr_fnc_getSetting;
+ _groups = [];
+ _hc = "headLessClientSupport" call VEMFr_fnc_getSetting;
+ _aiDifficulty = [["aiSkill"],["difficulty"]] call VEMFr_fnc_getSetting param [0, "Veteran", [""]];
+ _skills = [["aiSkill", _aiDifficulty],["accuracy","aimingShake","aimingSpeed","endurance","spotDistance","spotTime","courage","reloadSpeed","commanding","general"]] call VEMFr_fnc_getSetting;
+ _accuracy = _skills select 0;
+ _aimShake = _skills select 1;
+ _aimSpeed = _skills select 2;
+ _stamina = _skills select 3;
+ _spotDist = _skills select 4;
+ _spotTime = _skills select 5;
+ _courage = _skills select 6;
+ _reloadSpd = _skills select 7;
+ _commanding = _skills select 8;
+ _general = _skills select 9;
+
+ _houses = nearestTerrainObjects [_pos, ["House"], 200]; // Find some houses to spawn in
+ _notTheseHouses = "housesBlackList" call VEMFr_fnc_getSetting;
+ _goodHouses = [];
+ { // Filter the houses that are too small for one group
+ if not(typeOf _x in _notTheseHouses) then
+ {
+ if ([_x, _unitsPerGrp] call BIS_fnc_isBuildingEnterable) then
+ {
+ _goodHouses pushBack _x;
+ };
+ };
+ } forEach _houses;
+ _goodHouses = _goodHouses call BIS_fnc_arrayShuffle;
+ _noHouses = false;
+ if (count _goodHouses < _grpCount) then
+ {
+ _noHouses = true;
+ };
+
+ _cal50s = [["DynamicLocationInvasion"],["cal50s"]] call VEMFr_fnc_getSetting param [0, 3, [0]];
+ if (_cal50s > 0) then
+ {
+ _cal50sVehs = [];
+ };
+ _units = []; // Define units array. the for loops below will fill it with units
+ for "_g" from 1 to _grpCount do // Spawn Groups near Position
+ {
+ if not _noHouses then
+ {
+ if (count _goodHouses < 1) then
+ {
+ _noHouses = true
+ };
+ };
+ private ["_unitSide","_grp","_unit"];
+ _unitSide = getText (configFile >> "CfgVehicles" >> ("unitClass" call VEMFr_fnc_getSetting) >> "faction");
+ switch _unitSide do
+ {
+ case "BLU_G_F":
+ {
+ _grp = createGroup WEST;
+ };
+ case "CIV_F":
+ {
+ _grp = createGroup civilian;
+ };
+ case "IND_F":
+ {
+ _grp = createGroup independent;
+ };
+ case "IND_G_F":
+ {
+ _grp = createGroup resistance;
+ };
+ case "OPF_F":
+ {
+ _grp = createGroup EAST;
+ };
+ default
+ {
+ ["fn_spawnAI", 0, format["Unknown side %1", _unitSide]] spawn VEMFr_fnc_log;
+ };
+ };
+ if not isNil"_grp" then
+ {
+ if not _noHouses then
+ {
+ _grp enableAttack false;
+ };
+ _grp setBehaviour "AWARE";
+ _grp setCombatMode "RED";
+ _grp allowFleeing 0;
+ private ["_house","_housePositions"];
+ if not _noHouses then
+ {
+ _house = selectRandom _goodHouses;
+ _houseID = _goodHouses find _house;
+ _goodHouses deleteAt _houseID;
+ _housePositions = [_house] call BIS_fnc_buildingPositions;
+ };
+
+ _placed50 = false;
+ for "_u" from 1 to _unitsPerGrp do
+ {
+ private ["_spawnPos","_hmg"];
+ if not _noHouses then
+ {
+ _spawnPos = selectRandom _housePositions;
+ if not _placed50 then
+ {
+ _placed50 = true;
+ if (_cal50s > 0) then
+ {
+ _hmg = createVehicle ["B_HMG_01_high_F", _spawnPos, [], 0, "CAN_COLLIDE"];
+ _hmg setVehicleLock "LOCKEDPLAYER";
+ (_spawned select 1) pushBack _hmg;
+ };
+ };
+ };
+ if _noHouses then
+ {
+ _spawnPos = [_pos,20,250,1,0,200,0] call BIS_fnc_findSafePos; // Find Nearby Position
+ };
+
+ _unit = _grp createUnit [_sldrClass, _spawnPos, [], 0, "CAN_COLLIDE"]; // Create Unit There
+ if not _noHouses then
+ {
+ doStop _unit;
+ if (_cal50s > 0) then
+ {
+ if not isNil"_hmg" then
+ {
+ if not isNull _hmg then
+ {
+ _unit moveInGunner _hmg;
+ _hmg = nil;
+ _cal50s = _cal50s - 1;
+ };
+ };
+ };
+
+ _houseIndex = _housePositions find _spawnPos;
+ _housePositions deleteAt _houseIndex;
+ };
+
+ _unit addMPEventHandler ["mpkilled","if (isDedicated) then { [_this select 0, _this select 1] spawn VEMFr_fnc_aiKilled }"];
+ (_spawned select 0) pushBack _unit;
+ // Set skills
+ _unit setSkill ["aimingAccuracy", _accuracy];
+ _unit setSkill ["aimingShake", _aimShake];
+ _unit setSkill ["aimingSpeed", _aimSpeed];
+ _unit setSkill ["endurance", _stamina];
+ _unit setSkill ["spotDistance", _spotDist];
+ _unit setSkill ["spotTime", _spotTime];
+ _unit setSkill ["courage", _courage];
+ _unit setSkill ["reloadSpeed", _reloadSpd];
+ _unit setSkill ["commanding", _commanding];
+ _unit setSkill ["general", _general];
+ _unit setRank "Private"; // Set rank
+ };
+ _grp selectLeader _unit; // Leader Assignment
+ _groups pushBack _grp; // Push it into the _groups array
+ };
+ };
+
+ _invLoaded = [_spawned select 0, "Invasion", _mode] call VEMFr_fnc_loadInv; // Load the AI's inventory
+ if isNil"_invLoaded" then
+ {
+ ["fn_spawnAI", 0, "failed to load AI's inventory..."] spawn VEMFr_fnc_log;
+ };
+
+ if (count _groups isEqualTo _grpCount) then
+ {
+ if not _noHouses then
+ {
+ {
+ [_x] spawn VEMFr_fnc_signAI;
+ } forEach _groups;
+ };
+ if _noHouses then
+ {
+ _waypoints =
+ [
+ [(_pos select 0), (_pos select 1)+50, 0],
+ [(_pos select 0)+50, (_pos select 1), 0],
+ [(_pos select 0), (_pos select 1)-50, 0],
+ [(_pos select 0)-50, (_pos select 1), 0]
+ ];
+ { // Make them Patrol
+ for "_z" from 1 to (count _waypoints) do
+ {
+ _wp = _x addWaypoint [(_waypoints select (_z-1)), 10];
+ _wp setWaypointType "SAD";
+ _wp setWaypointCompletionRadius 20;
+ };
+ _cyc = _x addWaypoint [_pos,10];
+ _cyc setWaypointType "CYCLE";
+ _cyc setWaypointCompletionRadius 20;
+ [_x] spawn VEMFr_fnc_signAI;
+ } forEach _groups;
+ };
+ };
+ };
+ };
+};
+_spawned
diff --git a/exile_vemf_reloaded/functions/fn_spawnStaticAI.sqf b/exile_vemf_reloaded/functions/fn_spawnStaticAI.sqf
new file mode 100644
index 0000000..36a3c2e
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_spawnStaticAI.sqf
@@ -0,0 +1,28 @@
+/*
+ Author: IT07
+
+ Description:
+ spawns AI at all given locations in config file
+
+ Params:
+ none
+
+ Returns:
+ nothing
+*/
+
+if ([["aiStatic"],["enabled"]] call VEMFr_fnc_getSetting isEqualTo 1) then
+{
+ ["spawnStaticAI", 3, "launching..."] spawn VEMFr_fnc_log;
+ _settings = [["aiStatic"],["positions","amount"]] call VEMFr_fnc_getSetting;
+ _positions = _settings select 0;
+ if (count _positions > 0) then
+ {
+ ["spawnStaticAI", 3, "spawning AI on positions..."] spawn VEMFr_fnc_log;
+ _amounts = _settings select 1;
+ {
+ _amount = _amounts select _foreachindex;
+ [_x, 2, _amount / 2, "aiMode" call VEMFr_fnc_getSetting] spawn VEMFr_fnc_spawnAI;
+ } forEach _positions;
+ };
+};
diff --git a/exile_vemf_reloaded/functions/fn_transferOwner.sqf b/exile_vemf_reloaded/functions/fn_transferOwner.sqf
new file mode 100644
index 0000000..7485279
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_transferOwner.sqf
@@ -0,0 +1,86 @@
+/*
+ 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:
+ BOOLEAN - true if transfer was successful
+*/
+
+private ["_toTransfer","_hcEnabled","_hcUIDs","_hcClients","_to","_transfer"];
+_transfer = false;
+_toTransfer = param [0, grpNull, [grpNull]];
+if not isNull _toTransfer then
+{
+ // Check if HC is enabled
+ _hcEnabled = "headLessClientSupport" call VEMFr_fnc_getSetting;
+ _forceClients = uiNamespace getVariable ["VEMFr_forceAItoClients", nil];
+ if not(isNil"_forceClients") then
+ {
+ if _forceClients then
+ {
+ _hcEnabled = -1;
+ };
+ };
+ if (_hcEnabled isEqualTo 1) then
+ { // Gather the Headless Client(s)
+ _hcClients = [];
+ {
+ if (typeOf _x isEqualTo "HeadlessClient_F") then // it is an HC
+ {
+ _hcClients pushBack [_x, owner _x];
+ };
+ } forEach allPlayers;
+ if (count _hcClients > 0) then
+ {
+ _to = call VEMFr_fnc_headLessClient; // Select a random hc
+ };
+ if (count _hcClients isEqualTo 0) then
+ {
+ uiNamespace setVariable ["VEMFr_forceAItoClients", true];
+ };
+ };
+ if (_hcEnabled isEqualTo 0) then
+ {
+ if ([1] call VEMFr_fnc_playerCount) then
+ {
+ _closest = [0,0,0];
+ {
+ if (isPlayer _x) then
+ {
+ _leaderPos = position (leader _toTransfer);
+ _dist = _leaderPos distance (position _x);
+ if (_dist < (_leaderPos distance _closest)) then
+ { // Find the closest player
+ _closest = position _x;
+ _to = _x;
+ };
+ };
+ } forEach allPlayers;
+ };
+ };
+ if not isNil"_to" then
+ {
+ _transfer = _toTransfer setGroupOwner (owner _to);
+ _load = uiNamespace getVariable ["VEMFrHcLoad", nil];
+ if not isNil"_load" then
+ {
+ _index = _load find _to;
+ if (_index > -1) then
+ {
+ _load set [_index, ((_load select _index) select 1) + 1];
+ };
+ if (_index isEqualTo -1) then
+ {
+ _load pushBack [_to, 1];
+ };
+ };
+ };
+};
+
+_transfer // Return the value of this var to the calling script
diff --git a/exile_vemf_reloaded/functions/fn_waitForMissionDone.sqf b/exile_vemf_reloaded/functions/fn_waitForMissionDone.sqf
new file mode 100644
index 0000000..ac5ed5c
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_waitForMissionDone.sqf
@@ -0,0 +1,60 @@
+/*
+ Author: VAMPIRE, rebooted by IT07
+
+ Description:
+ fn_waitForMissionDone - waits for mission to be done
+
+ Params:
+ _this select 0: STRING - name of mission location
+ _this select 1: POSITION - center of area to be waiting for
+ _this select 2: ARRAY - array of units to check for
+ _this select 3: SCALAR - radius around center to check for players
+
+ Returns:
+ BOOL - true when mission is done
+*/
+
+private ["_pos","_unitArr","_unitCount","_killed","_killToComplete","_rad","_playerNear","_complete"];
+_complete = false;
+_pos = param [1, [], [[]]];
+if (count _pos isEqualTo 3) then
+{
+ _unitArr = param [2, [], [[]]];
+ if (count _unitArr > 0) then
+ {
+ _unitCount = count _unitArr;
+ _killed = [];
+ _killToComplete = round(("killPercentage" call VEMFr_fnc_getSetting)/100*_unitCount);
+ _rad = param [3, 0, [0]];
+ if (_rad > 0) then
+ {
+ while {not _complete} do
+ {
+ // First check for a player
+ if not _complete then { uiSleep 1; };
+ _playerNear = [_pos, _rad] call VEMFr_fnc_checkPlayerPresence;
+ if (_playerNear) then
+ {
+ {
+ if not(alive _x) then
+ {
+ _killed pushBack _x;
+ };
+ } forEach _unitArr;
+ { // Delete the not(alive) units
+ _index = _unitArr find _x;
+ if not(_index isEqualTo -1) then
+ {
+ _unitArr deleteAt _index;
+ };
+ } forEach _killed;
+ };
+ if not _complete then { uiSleep 1 };
+ if (((count _killed) isEqualTo _killToComplete) OR ((count _killed) > _killToComplete)) then { _complete = true };
+ if not _complete then { uiSleep 1 };
+ };
+ ["fn_waitForMissionDone", 1, format["mission in %1 completed!", _this select 0]] spawn VEMFr_fnc_log;
+ };
+ };
+};
+_complete
diff --git a/exile_vemf_reloaded/functions/fn_waitForPlayers.sqf b/exile_vemf_reloaded/functions/fn_waitForPlayers.sqf
new file mode 100644
index 0000000..6c67e0a
--- /dev/null
+++ b/exile_vemf_reloaded/functions/fn_waitForPlayers.sqf
@@ -0,0 +1,43 @@
+/*
+ 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 ["_playerNear","_pos","_rad","_time","_timeOutTime","_pp"];
+_playerNear = false;
+_pos = param [0, [], [[]]];
+if (count _pos isEqualTo 3) then
+{
+ _rad = param [1, -1, [0]];
+ if (_rad > -1) then
+ {
+ _time = round time;
+ // Define _settings
+ _timeOutTime = ("timeOutTime" call VEMFr_fnc_getSetting)*60;
+ // _pp = playerPresence
+ _pp = [_pos, _rad] call VEMFr_fnc_checkPlayerPresence;
+ if _pp then
+ {
+ _playerNear = true;
+ };
+ if not _pp then
+ {
+ waitUntil { uiSleep 2; (([_pos, _rad] call VEMFr_fnc_checkPlayerPresence) OR (round time - _time > _timeOutTime)) };
+ if ([_pos, _rad] call VEMFr_fnc_checkPlayerPresence) then
+ {
+ _playerNear = true;
+ };
+ };
+ };
+};
+
+_playerNear
diff --git a/exile_vemf_reloaded/missions/DynamicLocationInvasion.sqf b/exile_vemf_reloaded/missions/DynamicLocationInvasion.sqf
new file mode 100644
index 0000000..6befda8
--- /dev/null
+++ b/exile_vemf_reloaded/missions/DynamicLocationInvasion.sqf
@@ -0,0 +1,362 @@
+/*
+ DynamicLocationInvasion by Vampire, rewritten by IT07
+*/
+private ["_settings","_grpCount","_groupUnits","_skipDistance","_loc","_hasPlayers","_spawned","_grpArr","_unitArr","_done","_boxes","_box","_chute","_colors","_lightType","_light","_smoke"];
+
+// Define _settings
+_settings = [["DynamicLocationInvasion"],["maxInvasions","groupCount","groupUnits","maxDistance","maxDistancePrefered","skipDistance","marker","parachuteCrate","markCrateVisual","markCrateOnMap","announce","streetLights","streetLightsRestore","streetLightsRange","allowCrateLift"]] call VEMFr_fnc_getSetting;
+_maxInvasions = _settings select 0;
+if isNil"VEMFr_invasCount" then
+{
+ VEMFr_invasCount = 0;
+};
+VEMFr_invasCount = VEMFr_invasCount + 1;
+if (VEMFr_invasCount <= _maxInvasions) then
+{
+ _grpCount = _settings select 1;
+ _groupUnits = _settings select 2;
+ _range = _settings select 3;
+ _maxPref = _settings select 4;
+ _skipDistance = _settings select 5;
+ _useMissionMarker = _settings select 6;
+ _useChute = (_settings select 7) select 0;
+ _crateAltitude = (_settings select 7) select 1;
+ _markCrateVisual = _settings select 8;
+ _markCrateOnMap = _settings select 9;
+ _announce = _settings select 10;
+ _streetLights = _settings select 11;
+ _streetLightsRestore = _settings select 12;
+ _streetLightsRange = _settings select 13;
+ _allowCrateLift = _settings select 14;
+
+ _loc = ["loc", false, position (selectRandom allPlayers), _range, _skipDistance, _maxPref, _skipDistance] call VEMFr_fnc_findPos;
+ if (_loc isEqualType []) then
+ {
+ _locName = _loc select 0;
+ if (_locName isEqualTo "") then { _locName = "Area"; };
+ ["DynamicLocationInvasion", 1, format["Invading %1...", _locName]] spawn VEMFr_fnc_log;
+ VEMFr_invasCount = VEMFr_invasCount + 1;
+ // Send message to all players
+ private ["_mode"];
+ _mode = "aiMode" call VEMFr_fnc_getSetting;
+ _randomModes = ([["DynamicLocationInvasion"],["randomModes"]] call VEMFr_fnc_getSetting) select 0;
+ if (_randomModes isEqualTo 1) then
+ {
+ _mode = selectRandom [0,1,2];
+ };
+ if (_announce isEqualTo 1) then
+ {
+ if (_mode isEqualTo 0) then
+ {
+ [[format["Plundering groups have invaded %1 @ %2", _locName, mapGridPosition (_loc select 1)], "NEW INVASION"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ if (_mode isEqualTo 1) then
+ {
+ [[format["%1 Police forces are now controlling %2 @ %3", worldName, _locName, mapGridPosition (_loc select 1)], "NEW MISSION"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ if (_mode isEqualTo 2) then
+ {
+ [[format["%1 S.W.A.T. teams are now raiding %2 @ %3", worldName, _locName, mapGridPosition (_loc select 1)], "NEW RAID"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ };
+ private["_marker"];
+ if (_useMissionMarker isEqualTo 1) then
+ { // Create/place the marker if enabled
+ _marker = createMarker [format["VEMFr_DynaLocInva_ID%1", random 9000], (_loc select 1)];
+ _marker setMarkerShape "ICON";
+ _marker setMarkerType "o_unknown";
+ switch true do
+ {
+ case (_mode isEqualTo 0):
+ {
+ _marker setMarkerColor "ColorEAST";
+ };
+ case (_mode isEqualTo 1):
+ {
+ _marker setMarkerColor "ColorWEST";
+ };
+ case (_mode isEqualTo 2):
+ {
+ _marker setMarkerColor "ColorBlack";
+ };
+ };
+ };
+
+ // If enabled, kill all the lights
+ if (_streetLights isEqualTo 0) then
+ {
+ private ["_all"];
+ _all = nearestObjects [_loc select 1, ["Lamps_Base_F","PowerLines_base_F","Land_PowerPoleWooden_L_F"], _streetLightsRange];
+ {
+ if (damage _x < 0.95) then
+ {
+ _x setDamage 0.95;
+ uiSleep 0.1;
+ };
+ } forEach _all;
+ };
+
+ // Usage: POSITION, Radius
+ _playerNear = [_loc select 1, 800] call VEMFr_fnc_waitForPlayers;
+ if _playerNear then
+ {
+ // Player is Near, so Spawn the Units
+ _spawned = [_loc select 1, ((_grpCount select 0) + round random ((_grpCount select 1) - (_grpCount select 0))), ((_groupUnits select 0) + round random ((_groupUnits select 1) - (_groupUnits select 0))), _mode] call VEMFr_fnc_spawnAI;
+ if (count (_spawned select 0) > 0) then
+ {
+ private ["_cal50s"];
+ if (count (_spawned select 1) > 0) then
+ {
+ _cal50s = _spawned select 1;
+ };
+ // Place mines if enabled
+ private ["_minesPlaced","_mines"];
+ _mines = [["DynamicLocationInvasion"],["mines"]] call VEMFr_fnc_getSetting param [0, 0, [0]];
+ if (_mines > 0) then
+ {
+ _minesPlaced = [_loc select 1, 5, 100] call VEMFr_fnc_placeMines param [0, [], [[]]];
+ if (count _minesPlaced > 0) then
+ {
+ ["DynamicLocationInvasion", 1, format["Successfully placed mines at %1", _locName]] spawn VEMFr_fnc_log;
+ };
+ if (count _minesPlaced isEqualto 0) then
+ {
+ ["DynamicLocationInvasion", 0, format["Failed to place mines at %1", _locName]] spawn VEMFr_fnc_log;
+ _minesPlaced = nil;
+ };
+ };
+
+ // Wait for Mission Completion
+ _done = [_loc select 0, _loc select 1, _spawned select 0, _skipDistance] call VEMFr_fnc_waitForMissionDone;
+ _usedLocs = uiNamespace getVariable "VEMFrUsedLocs";
+ _index = _usedLocs find [_loc select 0, _loc select 1];
+ if (_index > -1) then
+ {
+ _usedLocs deleteAt _index;
+ };
+ if _done then
+ {
+ // Broadcast
+ if (_announce isEqualTo 1) then
+ {
+ if (_mode isEqualTo 0) then
+ {
+ [[format["%1 @ %2 has been cleared of %3 bad guys", _locName, mapGridPosition (_loc select 1), worldName], "COMPLETED"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ if (_mode isEqualTo 1) then
+ {
+ [[format["%1 @ %2 has been cleared of %3 Police forces", _locName, mapGridPosition (_loc select 1), worldName], "CLEARED"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ if (_mode isEqualTo 2) then
+ {
+ [[format["S.W.A.T. raid on %1 @ %2 has been eliminated", _locName, mapGridPosition (_loc select 1)], "DEFEATED"], ""] spawn VEMFr_fnc_broadCast;
+ };
+ };
+ // Deal with the 50s
+ if not isNil"_cal50s" then
+ {
+ private["_cal50sDelete"];
+ _cal50sDelete = ([["DynamicLocationInvasion"],["cal50sDelete"]] call VEMFr_fnc_getSetting) select 0;
+ if (_cal50sDelete > 0) then
+ {
+ {
+ if (_cal50sDelete isEqualTo 1) then
+ {
+ deleteVehicle _x;
+ };
+ if (_cal50sDelete isEqualTo 2) then
+ {
+ _x setDamage 1;
+ };
+ } forEach _cal50s;
+ };
+ };
+ // Choose a box
+ _boxes = [["DynamicLocationInvasion"],["crateTypes"]] call VEMFr_fnc_getSetting;
+ _box = (_boxes select 0) call BIS_fnc_selectRandom;
+ _pos = [_loc select 1, 0, 100, 0, 0, 300, 0] call bis_fnc_findSafePos;
+ private ["_crate"];
+ if (_useChute isEqualTo 1) then
+ {
+ _chute = createVehicle ["I_Parachute_02_F", _pos, [], 0, "FLY"];
+ _chute setPos [getPos _chute select 0, getPos _chute select 1, _crateAltitude];
+ _chute enableSimulationGlobal true;
+
+ if not isNull _chute then
+ {
+ _crate = createVehicle [_box, getPos _chute, [], 0, "NONE"];
+ _crate allowDamage false;
+ _crate enableSimulationGlobal true;
+ _crate attachTo [_chute, [0,0,0]];
+ if (_allowCrateLift isEqualTo 0) then
+ {
+ _crate enableRopeAttach false;
+ };
+ ["DynamicLocationInvasion", 1, format ["Crate parachuted at: %1 / Grid: %2", (getPosATL _crate), mapGridPosition (getPosATL _crate)]] spawn VEMFr_fnc_log;
+ _lootLoaded = [_crate] call VEMFr_fnc_loadLoot;
+ if _lootLoaded then { ["DynamicLocationInvasion", 1, "Loot loaded successfully into parachuting crate"] spawn VEMFr_fnc_log };
+ };
+ };
+ if (_useChute isEqualTo 0) then
+ {
+ _crate = createVehicle [_box, _pos, [], 0, "NONE"];
+ _crate allowDamage false;
+ if (_allowCrateLift isEqualTo 0) then
+ {
+ _crate enableRopeAttach false;
+ };
+ _lootLoaded = [_crate] call VEMFr_fnc_loadLoot;
+ if _lootLoaded then { ["DynamicLocationInvasion", 1, "Loot loaded successfully into crate"] spawn VEMFr_fnc_log };
+ };
+ if (_markCrateVisual isEqualTo 1) then
+ {
+ uiSleep 0.5;
+ // If night, attach a chemlight
+ if (dayTime < 5 OR dayTime > 19) then
+ {
+ _colors = [["DynamicLocationInvasion"],["flairTypes"]] call VEMFr_fnc_getSetting param [0, [], [[]]];
+ if (count _colors > 0) then
+ {
+ _lightType = selectRandom _colors;
+ _light = _lightType createVehicle (position _crate);
+ _light attachTo [_crate,[0,0,0]];
+ };
+ };
+ // Attach smoke
+ _colors = [["DynamicLocationInvasion"],["smokeTypes"]] call VEMFr_fnc_getSetting param [0, [], [[]]];
+ if (count _colors > 0) then
+ {
+ _rndmColor = selectRandom _colors;
+ _smoke = createVehicle [_rndmColor, getPos _crate, [], 0, "CAN_COLLIDE"];
+ _smoke attachTo [_crate,[0,0,0]];
+ };
+ };
+ if (_useChute isEqualTo 1) then
+ {
+ waitUntil { uiSleep 1; (((getPos _crate) select 2) < 7) };
+ detach _crate;
+ };
+ if not isNil"_marker" then
+ {
+ deleteMarker _marker
+ };
+ VEMFr_invasCount = VEMFr_invasCount - 1;
+ VEMFr_missionCount = VEMFr_missionCount - 1;
+
+ // Put a marker on the crate if enabled
+ if not isNil "_crate" then
+ {
+ if not isNull _crate then
+ {
+ if not ([getPos _crate, 2] call VEMFr_fnc_checkPlayerPresence) then
+ {
+ _addMarker = [["DynamicLocationInvasion"],["markCrateOnMap"]] call VEMFr_fnc_getSetting param [0, 1, [0]];
+ if (_addMarker isEqualTo 1) then
+ {
+ private ["_crateMarker"];
+ _crateMarker = createMarker [format["VEMF_lootCrate_ID%1", random 9000], position _crate];
+ _crateMarker setMarkerShape "ICON";
+ _crateMarker setMarkerType "mil_box";
+ _crateMarker setMarkerColor "colorBlack";
+ _crateMarker setMarkerText " Loot";
+ [_crate, _crateMarker] spawn
+ {
+ _crate = _this select 0;
+ _crateMarker = _this select 1;
+ waitUntil { uiSleep 4; [getPos _crate, 3] call VEMFr_fnc_checkPlayerPresence };
+ deleteMarker _crateMarker;
+ };
+ };
+ };
+ };
+ };
+
+ if isNil "_crate" then
+ {
+ ["DynamicLocationInvasion", 0, "ERROR! _crate not found"] spawn VEMFr_fnc_log;
+ };
+
+ // Explode or remove the mines
+ if not isNil"_minesPlaced" then
+ {
+ private ["_cleanMines"];
+ _cleanMines = [["DynamicLocationInvasion"],["minesCleanup"]] call VEMFr_fnc_getSetting param [0, 1, [0]];
+ if (_cleanMines isEqualTo 2) then
+ {
+ {
+ if not isNull _x then
+ {
+ _x setDamage 1;
+ uiSleep (2 + round random 2);
+ };
+ } forEach _minesPlaced;
+ ["DynamicLocationInvasion", 1, format["Successfully exploded all %1 mines at %2", count _minesPlaced, _locName]] spawn VEMFr_fnc_log;
+ _minesPlaced = nil;
+ };
+ if (_cleanMines isEqualTo 1) then
+ {
+ {
+ if not isNull _x then
+ {
+ deleteVehicle _x;
+ };
+ } forEach _minesPlaced;
+ ["DynamicLocationInvasion", 1, format["Successfully deleted all %1 mines at %2", count _minesPlaced, _locName]] spawn VEMFr_fnc_log;
+ _minesPlaced = nil;
+ };
+ };
+
+ // If enabled, fix all the lights
+ if (_streetLightsRestore isEqualTo 1) then
+ {
+ private ["_all"];
+ _all = nearestObjects [_loc select 1, ["Lamps_Base_F","PowerLines_base_F","Land_PowerPoleWooden_L_F"], _streetLightsRange];
+ {
+ if (damage _x > 0.94) then
+ {
+ _x setDamage 0;
+ uiSleep 0.2;
+ };
+ } forEach _all;
+ };
+ };
+ };
+ if isNil"_spawned" then
+ {
+ ["DynamicLocationInvasion", 0, format["Failed to spawn AI in %1", _locName]] spawn VEMFr_fnc_log;
+ if not isNil"_marker" then
+ {
+ deleteMarker _marker
+ };
+ VEMFr_invasCount = VEMFr_invasCount - 1;
+ VEMFr_missionCount = VEMFr_missionCount - 1;
+ };
+ };
+ if not _playerNear then
+ {
+ ["DynamicLocationInvasion", 1, format["Invasion of %1 timed out.", _locName]] spawn VEMFr_fnc_log;
+ if not isNil"_marker" then
+ {
+ deleteMarker _marker
+ };
+ _usedLocs = uiNamespace getVariable "VEMFrUsedLocs";
+ _index = _usedLocs find _loc;
+ if (_index > -1) then
+ {
+ _usedLocs deleteAt _index;
+ };
+ VEMFr_invasCount = VEMFr_invasCount - 1;
+ VEMFr_missionCount = VEMFr_missionCount - 1;
+ };
+ };
+ if not(_loc isEqualType []) then
+ {
+ VEMFr_invasCount = VEMFr_invasCount - 1;
+ VEMFr_missionCount = VEMFr_missionCount - 1;
+ };
+};
+if (VEMFr_invasCount >= _maxInvasions) then
+{
+ VEMFr_invasCount = VEMFr_invasCount - 1;
+ VEMFr_missionCount = VEMFr_missionCount - 1;
+};