diff --git a/Server_Install_Pack/sc/BattlEye/remoteexec.txt b/Server_Install_Pack/sc/BattlEye/remoteexec.txt
index 8355a220..9d2ee094 100644
--- a/Server_Install_Pack/sc/BattlEye/remoteexec.txt
+++ b/Server_Install_Pack/sc/BattlEye/remoteexec.txt
@@ -1 +1 @@
-5 "" !="bis_fnc_execvm \[\[.+\],\"initPlayerServer.sqf\"]" !="bis_fnc_effectkilled(airdestruction|secondaries) \[.+\]" !="epoch_server_checkplayer \[[A-Z]{1} [A-Za-z]{4,10} [0-9]{1,3}-[0-9]{1,3}:[0-9]{1,3}( \(.+\)|) REMOTE\]" !="epoch_server_(save(_vehicles|building)|(lock|pack)Storage|(upgrade|remove|paint|maint)build) \[.+\]" !="epoch_server_((load|respawn|dead|invite|revive|teleport)Player|(upgrade|updateplayer|create|delete)Group) \[.+\]" !="epoch_server_(deadplayerdetonate|triggerantagonist|playersetvariable) \[.+\]" !="epoch_server_(knockDownTree|mineRocks|lootAnimal|handle_(say3d|switchmove|sapperObjs)) \[.+\]" !="epoch_server_((repair|fill|lock)Vehicle|(loot|fill)Container|(store|take)Crypto|make(NPC|)Trade) \[.+\]" !="epoch_server_(tradeRequest|equippeditem|packJack|create(object|AirDrop)|airDropCrate|destroytrash|unpackBackpack) \[.+\]" !="epoch_(localcleanup|fnc_saveplayer) \[.+\]"
+5 "" !="bis_fnc_execvm \[\[.+\],\"initPlayerServer.sqf\"]" !="bis_fnc_effectkilled(airdestruction|secondaries) \[.+\]" !="epoch_server_checkplayer \[[A-Z]{1} [A-Za-z]{4,10} [0-9]{1,3}-[0-9]{1,3}:[0-9]{1,3}( \(.+\)|) REMOTE\]" !="epoch_server_(save(_vehicles|building)|(lock|pack)Storage|(upgrade|remove|paint|maint)build) \[.+\]" !="epoch_server_((load|respawn|dead|invite|revive|teleport)Player|(upgrade|updateplayer|create|delete)Group) \[.+\]" !="epoch_server_(deadplayerdetonate|triggerantagonist|playersetvariable|missioncomms) \[.+\]" !="epoch_server_(knockDownTree|mineRocks|lootAnimal|handle_(say3d|switchmove|sapperObjs)) \[.+\]" !="epoch_server_((repair|fill|lock)Vehicle|(loot|fill)Container|(store|take)Crypto|make(NPC|)Trade) \[.+\]" !="epoch_server_(tradeRequest|equippeditem|packJack|create(object|AirDrop)|airDropCrate|destroytrash|unpackBackpack) \[.+\]" !="epoch_(localcleanup|fnc_saveplayer) \[.+\]"
diff --git a/Sources/epoch_code/compile/EPOCH_callSapperMigration.sqf b/Sources/epoch_code/compile/EPOCH_callSapperMigration.sqf
index 47da22fb..f868db50 100644
--- a/Sources/epoch_code/compile/EPOCH_callSapperMigration.sqf
+++ b/Sources/epoch_code/compile/EPOCH_callSapperMigration.sqf
@@ -42,13 +42,17 @@ while {_notReady} do {
};
if(_abortAfter < 42)then{
- for "_i" from 1 to _sapperCount step 1 do {
- _pos = _start findEmptyPosition [0,20,"Epoch_Sapper_F"];
- _axeSapper = createAgent ["Epoch_Sapper_F", _pos, [], 12, "FORM"];
- waitUntil {_axeSapper == _axeSapper};
- _axeSapper call _disableAI;
- EPOCHSapperMigrationHandle = [_axeSapper,_finish] execFSM "\x\addons\a3_epoch_code\System\sapperSwarmMember.fsm";
- uiSleep 0.75;
+
+ [_sapperCount,_start,_disableAI,_finish]spawn{
+ params["_sapperCount","_start","_disableAI","_finish",["_pos",[]],["_axeSapper", objNull]];
+ for "_i" from 1 to _sapperCount step 1 do {
+ _pos = _start findEmptyPosition [0,20,"Epoch_Sapper_F"];
+ _axeSapper = createAgent ["Epoch_Sapper_F", _pos, [], 12, "FORM"];
+ waitUntil {_axeSapper == _axeSapper};
+ _axeSapper call _disableAI;
+ EPOCHSapperMigrationHandle = [_axeSapper,_finish] execFSM "\x\addons\a3_epoch_code\System\sapperSwarmMember.fsm";
+ uiSleep 0.75;
+ };
+ Epoch_axeMigrationRunning = true;
};
- Epoch_axeMigrationRunning = true;
};
diff --git a/Sources/epoch_code/compile/functions/EPOCH_fnc_createMarker.sqf b/Sources/epoch_code/compile/functions/EPOCH_fnc_createMarker.sqf
new file mode 100644
index 00000000..0c4c1ed8
--- /dev/null
+++ b/Sources/epoch_code/compile/functions/EPOCH_fnc_createMarker.sqf
@@ -0,0 +1,38 @@
+/*
+ Author: Andrew Gregory - EpochMod.com
+
+ Contributors:
+
+ Description:
+ Create a local marker, with options.
+
+ Licence:
+ Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
+
+ Github:
+ https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_code/compile/functions/EPOCH_fnc_createMarker.sqf
+
+ Example:
+ [player, position player, "ICON", "mil_dot", "Hi, I am a marker.. yay.", "ColorRed", [0.7,0.7], "Border", 42, 0.6] call EPOCH_fnc_createMarker
+
+ Parameter(s):
+ _this select 0: ANY - Marker name.
+ _this select 1: ARRAY / OBJECT - Marker Position (Object should be acceptable)
+ _this select 2 - 9: STRING(S) - Marker parameters.
+
+ Returns:
+
+*/
+_paramres = params [["_trgt", str(diag_tickTime)],["_mPos", position player],["_mShape","ICON"],["_mType","mil_dot"],["_mColor","ColorBlack"],["_mSize",[0.7,0.7]],["_mBrush",""],["_mDir",0],["_mText",""],["_mAlpha",1],["_mName",""]];
+diag_log format["Epoch: ADMIN: Creating marker at %1 called %2 (Params:%3).", _mPos, _trgt, _paramres];
+
+if(_mName == "")then{_mName = str(_trgt) + str(diag_tickTime);};
+_mrkr = createMarkerLocal [_mName, _mPos];
+_mrkr setMarkerShapeLocal _mShape;
+_mrkr setMarkerTypeLocal _mType;
+if!(_mText=="")then{_mrkr setMarkerTextLocal _mText;};
+_mrkr setMarkerSizeLocal _mSize;
+_mrkr setMarkerColorLocal _mColor;
+if!(_mBrush == "")then{_mrkr setMarkerBrushLocal _mBrush;};
+_mrkr setMarkerDirLocal _mDir;
+_mrkr setMarkerAlphaLocal _mAlpha;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/functions/EPOCH_fnc_findSapperStalkLocation.sqf b/Sources/epoch_code/compile/functions/EPOCH_fnc_findSapperStalkLocation.sqf
index 0cea3d49..b89744d5 100644
--- a/Sources/epoch_code/compile/functions/EPOCH_fnc_findSapperStalkLocation.sqf
+++ b/Sources/epoch_code/compile/functions/EPOCH_fnc_findSapperStalkLocation.sqf
@@ -4,7 +4,7 @@
Contributors:
Description:
- Picks a random spot relative to the target with some randomness. (Unused)
+ Picks a random spot relative to the target with some randomness. Used in Sapper Brain
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
diff --git a/Sources/epoch_code/compile/missions/EPOCH_mission_accept.sqf b/Sources/epoch_code/compile/missions/EPOCH_mission_accept.sqf
index 98e6c20e..f7160376 100644
--- a/Sources/epoch_code/compile/missions/EPOCH_mission_accept.sqf
+++ b/Sources/epoch_code/compile/missions/EPOCH_mission_accept.sqf
@@ -4,7 +4,7 @@
Contributors: Aaron Clark - EpochMod.com
Description:
- Mission accept
+ Handle mission select from trader menu
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
@@ -12,11 +12,11 @@
Github:
https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_code/compile/missions/EPOCH_mission_accept.sqf
*/
-_index = lbValue[1500, lbCurSel 1500];
-
-_config = "MissionList" call EPOCH_returnConfig;
-_disabledMissions = getArray(_config >> "traderMissionDisabled");
-if (_index in _disabledMissions) exitWith{ titleText["Invalid Mission", "PLAIN", 3]; };
+private ["_missionTasks","_selectedMission","_simpleTask","_simpleTaskFSM","_simpleTaskSQF","_simpleTaskFNC","_taskNS","_itemCompile","_fnc_path","_path","_taskControl","_missionAllowed","_missionIndex","_plyrVar"];
+_missionIndex = lbCurSel 1500;
+_missionAllowed = true;
+//systemChat format ["Mission Acepted: %1",_missionIndex];
+_missionClasses = getArray(getMissionConfig "EpochMissionList" >> "traderMissionClasses");
_nrEnts = player nearEntities ["Man", 20];
_trader = objNull;
@@ -27,79 +27,90 @@ _trader = objNull;
}forEach _nrEnts;
if !(isNull _trader) then {
- switch _index do {
- case 0: {
- [player,_trader] execFSM "\x\addons\a3_epoch_code\System\Trader_Missions_Delivery.fsm";
- };
- case 1: {
- [player,_trader] execFSM "\x\addons\a3_epoch_code\System\Trader_Missions_Animal_Control.fsm";
- };
- case 2: {
- [player,_trader] execFSM "\x\addons\a3_epoch_code\System\Trader_Missions_UAV.fsm";
- };
- case 3: {
- [] execFSM "\x\addons\a3_epoch_code\System\Trader_Missions_VIP.fsm";
- };
- case 4: {
- _formatMsg = format["The time is %1:%2.",date select 3, date select 4];
- [_formatMsg, 5] call Epoch_dynamicText;
- };
- case 5: {
- _players = [];
- _playersOut = [];
- _grpWith = false;
- _msg = "Apart from you";
- _grp = group player;
- _players = nearestObjects [player, ["Epoch_Man_base_F","Epoch_Female_base_F"], 750];
- _players = _players - [player];
- {
- if!(group _x == _grp)then{
- _playersOut pushBack _x;
- }else{
- _grpWith = true;
- };
- } forEach _players;
- if(_grpWith)then{
- _msg = "Apart from your team and you";
- };
- _trdrMsg = format["%2 %1, I haven't seen anybody for a while.",name player,_msg];
+_menuCondition = getText(getMissionConfig "epochMissions" >> (_missionClasses select _missionIndex) >> "missionDeny");
+ if!(_menuCondition=="")then{
+ if(call compile _menuCondition)then{_missionAllowed = false;};
+ };
+
- if (count _playersOut > 0) then {
- _player = selectRandom _playersOut;
- _trdrMsg = format["The last person picked up by the UAV was %1.",name _player];
- };
- [format["%1",_trdrMsg], 5] call Epoch_dynamicText;
- };
- case 6:
- {
- _newsArr = ["My dog was shot. That made me sad.","Business has been quiet since word got out that sappers are in the area.","Looters are expecting too much crypto for all the junk they bring in.","What do I look like ? A newspaper vendor. Go Away.","The sun came up again this morning.. That's good news I suppose.","Keep your dog fed with raw or cooked carcasses.","Sappers are known to be good for their pelts. Just don't get too close to one","Some very strange rumours that a Construct was seen in the mountains. Those things are just bedtime stories to scare kids with.","UAVs are a good source of components.","Some say this town is haunted by malevolent spirits.","I hear the military are helping survivors with air drops. Your loot is always welcome here if you find one.","Jammers seem to scare away some of the bad.. things.","Help Military Support Crew spot you with smoke or chemlights.","Hmm, have heard bar stories of a new monster on the loose. You watch yourself out there."];
- _config = 'CfgEpochClient' call EPOCH_returnConfig;
- _customNews = getArray(_config >> "EPOCH_news");
- if(count _customNews > 0)then{
- {
- _newsArr pushBack _x;
- } forEach _customNews;
- };
- _formatMsg = format["%1",selectRandom _newsArr];
- [_formatMsg, 5] call Epoch_dynamicText;
- };
- case 7: {
- _responseArr = ["My name..? What does it matter.","Hey buddy you rock up here unannounced and suddenly we're friends ? On your bike if you aren't buying or selling.",format["My name.. I am known as %1",name _trader], format["When names mattered I was called %1",name _trader],"I forget.. At least, I try to forget."];
- _formatMsg = format["%1",selectRandom _responseArr];
- [_formatMsg, 5] call Epoch_dynamicText;
+ if(_missionAllowed)then{
+ _selectedMission = _missionClasses select _missionIndex;
+ _missionTasks = getArray(getMissionConfig "epochMissions" >> _selectedMission >> "tasksList");
+
+ _simpleTask = getNumber (getMissionConfig "inGameTasks" >> (_missionTasks select 0) >> "simpleTask");
+
+ //systemChat format ["Simple Task: %1 | Mission: %2 from %3",_simpleTask,_selectedMission,_missionTasks];
+
+ if(_simpleTask > 0)then{//Simple Task
+
+ _simpleTaskFSM = getText (getMissionConfig "inGameTasks" >> (_missionTasks select 0) >> "initfsm");
+ _simpleTaskSQF = getText (getMissionConfig "inGameTasks" >> (_missionTasks select 0) >> "initsqf");
+ _simpleTaskFNC = getText (getMissionConfig "inGameTasks" >> (_missionTasks select 0) >> "initcall");
+
+ if!(_simpleTaskSQF == "")then{//Compile and store SQF Function
+ _tag = getText (getMissionConfig "CfgClientFunctions" >> "A3E" >> "tag");
+ _path = getText (getMissionConfig "inGameTasks" >> "file");
+ _taskNS = _tag + "_" + ((_simpleTaskSQF splitString ".") select 0);
+ _fnc_path = _path + "\" +_simpleTaskSQF;
+
+ if!((typeName _taskNS)=="CODE")then{
+ _itemCompile = compileFinal preprocessFileLineNumbers _fnc_path;
+ missionNamespace setvariable [_taskNS,_itemCompile];
+ }else{
+ _itemCompile = missionNamespace getVariable ["_taskNS",""];
};
- case 8: {
- "Epoch_Sapper_F" call EPOCH_unitSpawn;
- };
- case 9: {
- call EPOCH_spawn_looters;
- };
- default {
- ["Quit your jabbering and get the hell out of here.", 5] call Epoch_dynamicText;
+
+ //Emulating CfgClientFunctions - Is this required ?
+ [] call _itemCompile;
+
+ };
+
+ if!(_simpleTaskFSM == "")then{
+ _simpleTaskFSM = _path + "\" + _simpleTaskFSM;
+ epochSimpleTaskHandle = [] execFSM _simpleTaskFSM;
+ };
+
+ if!(_simpleTaskFNC == "")then{
+ call compile _simpleTaskFNC;
+ };
+
+ }else{//Run Task / Mission Monitor
+
+ _doTask = (_missionTasks select 0);
+ _allowTask = true;
+ //_uiNSTask = uiNameSpace getVariable ["axeTask",""];//TODO: Use hive to store this via dynamic vars. Or server mission control server_vars
+ _plyrVar = player getVariable ["SERVER_VARS",[]] select {_x find "axeTask" > -1;};
+ _uiNSTask = "";
+ if(count _plyrVar > 0)then{
+ _uiNSTask = _plyrVar select 0 select 1;
+ };
+ _miNSTask = missionNameSpace getVariable ["axeTask",""];
+
+ //Allow continuation of mission from Cached Task
+ if!(_uiNSTask == "")then{
+ if(_miNSTask == "")then{
+ _doTask = _uiNSTask;
+ }else{
+ _allowTask = false;
+ [format ["Already on a mission - %1",selectRandom ['Chop Chop !','Get on With It !','What are you waiting for ?','No bonuses for tardiness !']], 5] call Epoch_dynamicText;
+ };
+ };
+
+ if(_allowTask)then{
+ epochTaskHandle = [_doTask] execFSM "epoch_code\System\task_control.fsm"
+ };
+
};
+
+ }else{
+
+ [format["Mission Not Allowed !",_menuCondition], 5] call Epoch_dynamicText;
+
};
+
} else {
- titletext["Trader Lost. Goodbye.", "PLAIN DOWN", 3];
+//systemChat format ["Trader Not Found",""];
+["Trader Lost. Goodbye.", 5] call Epoch_dynamicText;
};
diff --git a/Sources/epoch_code/compile/missions/tasks/mission_spawnUAV.sqf b/Sources/epoch_code/compile/missions/tasks/mission_spawnUAV.sqf
new file mode 100644
index 00000000..3e6674b6
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/mission_spawnUAV.sqf
@@ -0,0 +1,11 @@
+params [["_trgt",player],"_targetPos","_unit","_grp","_driver"];
+_targetPos = getPosATL _trgt;
+_targetPos = [_targetPos, 600, 1200, 5, 0, 400, 0] call BIS_fnc_findSafePos;
+_targetPos set[2, 600];
+_unit = createVehicle["I_UAV_01_F", _targetPos, [], 0, "FLY"];
+addToRemainsCollector[_unit];
+_unit flyInHeight 600;
+_grp = createGroup RESISTANCE;
+_driver = _grp createUnit["I_UAV_AI", position _unit, [], 0, "CAN_COLLIDE"];
+_driver moveInAny _unit;
+[_unit, _trgt] execFSM "\x\addons\a3_epoch_code\System\Copter_brain.fsm";
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDebug_resetMissions.sqf b/Sources/epoch_code/compile/missions/tasks/traderDebug_resetMissions.sqf
new file mode 100644
index 00000000..7d5025e9
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDebug_resetMissions.sqf
@@ -0,0 +1,2 @@
+player setVariable ["SERVER_VARS",[],true];
+[format ["%1","Missions Reset - Re-open Trader Menu."], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_name.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_name.sqf
new file mode 100644
index 00000000..47dfd8f1
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_name.sqf
@@ -0,0 +1,15 @@
+_trader = objNull;
+_nrMn = nearestObjects [player, ["C_Man_1"], 16];
+_trader = _nrMn select 0;
+if(_trader getVariable ["traderName",""]== "")then{
+_nameArr = ["Aaron Clark","Kenneth Bente","Damian Clark","Raimonds Virtoss","Richie","Paden Sturtevant","Darren Harrison","Paul Tomany","Dan","Darren Harrison","Niklas Wagner","Andrew Gregory","Isaac Gregory","Florian Kinder","Denis Erygin","Alan Denham"];
+_trdrCurrName = name _trader;
+if((random 100) < 6 && !(_trdrCurrName in _nameArr))then{
+_newName = selectRandom _nameArr;
+_trader setName _newName;
+_trader setVariable ["traderName",_newName, true];
+};
+
+};
+_responseArr = ["I don't know. You can only be regenerated so many times before the memory starts to go..","You again..! Go bother someone else.",format["There was a time when names mattered, call me %1.",name _trader],"My name..? What does it matter.","Hey buddy you rock up here unannounced and suddenly we're friends ? On your bike if you aren't buying or selling.",format["My name.. I am known as %1",name _trader], format["When names mattered I was called %1",name _trader],"I forget.. At least, I try to forget."];
+[format ["%1",selectRandom _responseArr], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_nearPlayers.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_nearPlayers.sqf
new file mode 100644
index 00000000..0b953e52
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_nearPlayers.sqf
@@ -0,0 +1,12 @@
+private["_plyr","_trdrMsg"];
+_trdrMsg = "Do I look like the local Neighbourhood Watch..? No, I do not !";
+_plyrs = [];
+_plyrs = player nearEntities [["Epoch_Man_base_F","Epoch_Female_base_F"], 250];
+if (count _plyrs < 2) then {
+ _trdrMsg = format["Apart from you %1. %2",name player, selectRandom ["I haven't seen any round these parts for a long while.","It has been very quiet around here,","There is not much to report !"]];
+} else {
+ _plyrs deleteAt 0;
+ _plyr = selectRandom _plyrs;
+ _trdrMsg = format["%2 %1.",name _plyr, selectRandom ["The last person picked up by the UAV was","I did spot someone earlier, their name was","I heard there was somebody new in the area, "]];
+};
+[format ["%1",_trdrMsg], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_nearVehicles.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_nearVehicles.sqf
new file mode 100644
index 00000000..72b5b481
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_nearVehicles.sqf
@@ -0,0 +1,13 @@
+private["_plyr","_trdrMsg"];
+_trdrMsg = "Hey, there is a garage down the road.. Well, there used to be.";
+_vehs = [];
+_plyr = player;
+_vehs = nearestObjects [_plyr, ["CAR","AIR"], 1000];
+if (count _vehs < 1) then {
+ _trdrMsg = format["%2 %1.",name _plyr,selectRandom["I haven't seen anything lately, why not buy one","There is nothing around here","The last time the UAV went out it found nothing"]];
+} else {
+ _veh = _vehs select (floor (random count _vehs));
+ _dist = _veh distance _plyr;
+ _trdrMsg = format["I know of at least one vehicle within %1m of my current location. It looks like a %2.",_dist, typeof _veh];
+};
+[format ["%1",_trdrMsg], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_news.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_news.sqf
new file mode 100644
index 00000000..d2a36326
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_news.sqf
@@ -0,0 +1,3 @@
+_newsArr = ["My dog was shot. That made me sad.","Business has been quiet since word got out that sappers are in the area.","Looters are expecting too much crypto for all the junk they bring in.","What do I look like ? A newspaper vendor. Go Away.","The sun came up again this morning.. That's good news I suppose.","Keep your dog fed with raw or cooked carcasses.","Sappers are known to be good for their pelts. Just don't get too close to one","Some very strange rumours that a Construct was seen in the mountains. Those things are just bedtime stories to scare kids with.","UAVs are a good source of components.","Some say the nearby town is haunted by malevolent spirits.","I hear the military are helping survivors with air drops. Your loot is always welcome here if you find one.","Dogs can help you find pelts and animal carcasses","I heard that a new vehicle has been seen, some kind of board that you stand on. I personally don't believe the rumours."];
+
+[format ["%1",selectRandom _newsArr], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_timePlease.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_timePlease.sqf
new file mode 100644
index 00000000..b819101f
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_timePlease.sqf
@@ -0,0 +1,13 @@
+
+_hour = str(date select 3);
+_min = str(date select 4);
+
+if(count _hour < 2)then{
+_hour = "0" + _hour;
+};
+
+if(count _min < 2)then{
+_min = "0" + _min;
+};
+
+[format ["The time is %1:%2.",_hour, _min], 5] call Epoch_dynamicText;
\ No newline at end of file
diff --git a/Sources/epoch_code/compile/missions/tasks/traderDiag_triggerAirDrop.sqf b/Sources/epoch_code/compile/missions/tasks/traderDiag_triggerAirDrop.sqf
new file mode 100644
index 00000000..503dc8c8
--- /dev/null
+++ b/Sources/epoch_code/compile/missions/tasks/traderDiag_triggerAirDrop.sqf
@@ -0,0 +1,6 @@
+if((random 100) < 6)then{
+[] execFSM "\x\addons\a3_epoch_code\System\Event_Air_Drop.fsm";
+["Air Drop Incoming !", 5] call Epoch_dynamicText;
+}else{
+["Sorry, None Available!", 5] call Epoch_dynamicText;
+};
\ No newline at end of file
diff --git a/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_description.sqf b/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_description.sqf
index 4e44e1c4..ba74c704 100644
--- a/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_description.sqf
+++ b/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_description.sqf
@@ -4,7 +4,7 @@
Contributors: Aaron Clark
Description:
- TODO: Description
+ Reload trader menu description, from config, when mission is clicked on. Filter out disabled missions.
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
@@ -12,7 +12,19 @@
Github:
https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf
*/
-private["_index","_missionDesc"];
+private["_index","_missionClasses","_missionDesc"];
+_missionClasses = getArray(getMissionConfig "EpochMissionList" >> "traderMissionClasses");
+
_index = lbCurSel 1500;
-_missionDesc = getArray(getMissionConfig "MissionList" >> "traderMissionLongDesc");
-ctrlSetText [1001, _missionDesc select _index];
+
+_menuCondition = getText(getMissionConfig "epochMissions" >> (_missionClasses select _index) >> "missionDeny");
+_missionDesc = getText(getMissionConfig "epochMissions" >> (_missionClasses select _index) >> "missionDesc");
+
+if!(_menuCondition=="")then{
+ if(call compile _menuCondition)then{
+ _missionDesc = "NOT AVAILABLE - " + _missionDesc;
+ lbSetColor [1001, 0, [0.73,0.24,0.11,1] ] ;
+ };
+};
+
+ctrlSetText [1001, _missionDesc];
diff --git a/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf b/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf
index a23257a3..c6019912 100644
--- a/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf
+++ b/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf
@@ -4,7 +4,7 @@
Contributors: Aaron Clark
Description:
- TODO: Description
+ Loads trader menu with available missions from config. Applies conditions and tooltips.
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
@@ -12,12 +12,42 @@
Github:
https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_code/gui/scripts/missions/EPOCH_mission_refresh.sqf
*/
-private ["_index","_missionList","_disabledMissions"];
-_missionList = getArray(getMissionConfig "MissionList" >> "traderMissionNames");
-_disabledMissions = getArray(getMissionConfig "MissionList" >> "traderMissionDisabled");
+private ["_lbl","_missionClasses","_missionName","_menuCondition","_toolTip","_plyrVar","_uiNSTask"];
+params [["_currentTask",""]];
+_missionClasses = getArray(getMissionConfig "EpochMissionList" >> "traderMissionClasses");
+_plyrVar = player getVariable ["SERVER_VARS",[]] select {_x find "axeTask" > -1;};
+_uiNSTask = "";
+if(count _plyrVar > 0)then{
+_uiNSTask = _plyrVar select 0 select 1;
+};
+
{
- if !(_forEachIndex in _disabledMissions) then {
- _index = lbAdd[1500, _x];
- lbSetValue[1500, _index, _forEachIndex];
+
+ _missionName = getText(getMissionConfig "epochMissions" >> _x >> "missionName");
+ if!(_missionName == "")then{
+
+ _lbl = lbAdd[1500, _missionName];
+ lbSetValue[1500, _lbl, _forEachIndex];
+ _toolTip = getText(getMissionConfig "epochMissions" >> _x >> "missionToolTip");
+
+ _menuCondition = getText(getMissionConfig "epochMissions" >> _x >> "missionDeny");
+ if!(_menuCondition=="")then{
+ if(call compile _menuCondition)then{
+ lbSetColor [1500, _lbl, [0.73,0.24,0.11,1] ] ;
+ _toolTip = getText(getMissionConfig "epochMissions" >> _x >> "missionDenyToolTip");
+ };
+ };
+
+
+
+ if(_uiNSTask in getArray(getMissionConfig "epochMissions" >> _x >> "tasksList"))then{
+ lbSetColor [1500, _lbl, [0.98,0.98,0.33,1]] ;
+ _toolTip = "CONTINUE - " + _toolTip;
+ };
+
+ lbSetTooltip [1500, _lbl, _toolTip];
+
};
-}forEach _missionList;
+
+
+}forEach _missionClasses;
diff --git a/Sources/epoch_config/Configs/CfgMissions.hpp b/Sources/epoch_config/Configs/CfgMissions.hpp
new file mode 100644
index 00000000..af5a0cd9
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions.hpp
@@ -0,0 +1,185 @@
+/*
+ Author: Andrew Gregory - EpochMod.com
+
+ Contributors:
+
+ Description:
+ Mission selection configs and dialogs. Defines the missions for trader menu or triggered event.
+
+ Licence:
+ Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
+
+ Github:
+ https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_config/Configs/CfgMissions.hpp
+*/
+
+class EpochMissionList{
+ traderMissionClasses[] = {"missionDelivery","missionEscort","missionUav","missionSapper","missionSkull","missionMilitary","gameCaptureTheJammer","gameCarRace","infoTime","infoName","infoNews","infoVehicles","infoPeople","helpAirDrop","debugResetMission"}; //Exclude from here to remove from menu and trigger
+ traderMissionActiveNames[] = {}; //Not currently used (WIP)
+ traderMissionLongDesc[] = {}; //Not currently used (WIP)
+ traderMissionActiveLongDesc[] = {}; //Not currently used (WIP)
+};
+
+class epochMissions {
+
+ class missionDelivery{
+ missionName = "Pikes Peak Express"; //Name of mission as it appears in trader list
+ missionToolTip= "Courier."; //Tooltip for trader menu
+ missionDesc = "You must deliver an important message to another trader somewhere else on the map. Choose your trader wisely."; //Misison description as it appears in trader menu.
+ missionDeny = ""; //Specify a call compile condition. If it returns true the mission will be dis-allowed. Title will be rust coloured and prefixed with NOT ALLOWED.
+ missionDenyToolTip = ""; //Provides a tooltip explaining why the mission is denied. prefixed with NOT ALLOWED.
+ tasksList[] = {"prepForDelivery","doDelivery","finishDelivery"}; //Must contain a list of tasks used for this mission, in order. Used to control trader menu when mission is active. WIP - To control mission from this array alone.
+ missionTrigger = ""; //A dynamic trigger that sets off the mission anywhere in-game. e.g. player != vehicle player Not currently used (WIP)
+ missionTriggerDialog[] = {""}; //Randomly selected dialogue that is shown when mission is dynamically triggered. Not currently used (WIP)
+ };
+
+ class missionEscort{
+ missionName = "VIP Escort";
+ missionToolTip = "Escort a VIP..";
+ missionDesc = "You must deliver the generals daughter to a secret military base.";
+ missionDeny = "true";
+ missionDenyToolTip = "Not Ready.";
+ tasksList[] = {"takeEscortDelivery","startEscortMission","AIVehicleFind","rndDenyIfInGroup"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class missionUav{
+ missionName = "Drone Pilot";
+ missionToolTip = "Pilot a UAV.";
+ missionDesc = "Fly a drone to another trader and perform reconnaissance over the area. Girls make better pilots.";
+ missionDeny = "missionNameSpace getVariable [""EPOCH_playerEnergy"",0] < 50";
+ missionDenyToolTip = "You require energy for this mission !";
+ tasksList[] = {"uavMissionAccepted","doUAVSpawn","doUAVAttach","takeOffUAV","uavMission1","uavMission2","uavMission3"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class missionSapper{
+ missionName = "Sapper Bait";
+ missionToolTip = "Lure a sapper back to the trader.";
+ missionDesc = "Traders use sappers as bait for bigger prey, earn a reward.";
+ missionDeny = "true";
+ missionDenyToolTip = "Not Ready.";
+ tasksList[] = {"takeEscortDelivery","startSapperMission","AIVehicleFind","rndDenyIfInGroup"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class missionSkull{
+ missionName = "Skulls New Target";
+ missionToolTip = "Infiltrate a secure location.";
+ missionDesc = "Use your sniper and camouflage skills to complete this mission for a large reward.";
+ missionDeny = "true";
+ missionDenyToolTip = "Not Ready.";
+ tasksList[] = {"prepForMisssion","moveToContact","TakeMission","leaveContact","moveToMilitary","meetInsurgentContact","spawnCOntact","findPosition","removeTargets","moveIn","takeReward","rndVehicleSpawn","rndLooter","rndSapperSpwn","rndInsurgentTaskBin","rndInsurgentTaksCont"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class missionMilitary{
+ missionName = "Military Crash";
+ missionToolTip = "Loot the crashed military vehcile.";
+ missionDesc = "Expect some resistance as you clear out the remaining troops and reap the rewards.";
+ missionDeny = "count weapons player < 1";
+ missionDenyToolTip = "You are going to need weapons.";
+ tasksList[] = {"milMissionAccepted","milSpawnCrashSite","milMarkCrashSite","milFindCrashSite","milEndCrashSite"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class gameCaptureTheJammer{
+ missionName = "Capture the Jammer";
+ missionToolTip = "Mini Game - Fight for control of the base with your group.";
+ missionDesc = "Weapon and ammo drops during the game, the longer you keep the jammer the larger the prize, if you can find it.";
+ missionDeny = "true";
+ missionDenyToolTip = "Not Ready.";
+ tasksList[] = {"acceptMisssion","tpPlayerFSM","scoreMOnitorFSM","timeoutSpawnRndReward"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class gameCarRace{
+ missionName = "First Past The Line";
+ missionToolTip = "Mini Game - Vehicle Race";
+ missionDesc = "Mini Game - Race your vehicles to the finish point, make it there without stacking into a tree, there may be a prize for the winner.";
+ missionDeny = "true";
+ missionDenyToolTip = "Not Ready.";
+ tasksList[] = {};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class infoTime{
+ missionName = "What is the time ?";
+ missionDesc = "Find out the time from the trader.";
+ missionToolTip = "What's the time";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderDiagTime"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class infoName{
+ missionName = "What is your name friend ?";
+ missionDesc = "Ask the trader his name..";
+ missionToolTip = "Trader Name";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderDiagName"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+
+ class infoNews{
+ missionName = "So, what's new ?";
+ missionDesc = "Ask the trader for news or tips.";
+ missionToolTip = "News";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderDiagNews"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+ class infoPeople{
+ missionName = "Who is nearby ?";
+ missionDesc = "Find out if there are nearby players.";
+ missionToolTip = "Players";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderDiagNearby"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+ class infoVehicles{
+ missionName = "What Vehicles are Nearby ?";
+ missionDesc = "Ask the trader if they know of any vehicle locations.";
+ missionToolTip = "Need a Ride.";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderNearVehicles"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+ class helpAirDrop{
+ missionName = "Call an Air Drop";
+ missionDesc = "Helper - Call an airdrop if available";
+ missionToolTip = "Airdrop Request.";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderTriggerAirDrop"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+ class debugResetMission{
+ missionName = "Reset Missions";
+ missionDesc = "Experimental - Reset missions cache if stuck on a mission.";
+ missionToolTip = "DEBUG - Reset.";
+ missionDeny = "";
+ missionDenyToolTip = "";
+ tasksList[] = {"traderMissionReset"};
+ missionTrigger = "";
+ missionTriggerDialog = "";
+ };
+};
diff --git a/Sources/epoch_config/Configs/CfgMissions/CfgExample.hpp b/Sources/epoch_config/Configs/CfgMissions/CfgExample.hpp
new file mode 100644
index 00000000..64878a4a
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions/CfgExample.hpp
@@ -0,0 +1,199 @@
+/*
+ Author: Andrew Gregory - EpochMod.com
+ Contributors:
+
+ Description:
+ Example Mission file containing individual tasks (Commented)
+
+ Licence:
+ Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
+
+ Github:
+ https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_config/Configs/CfgEpochClient.hpp
+*/
+
+//Built in useful vars that can be used in code based conditions / responses etc.
+//N.B. Local vars can not be used as they are not in scope when call compiled.
+//
+//EPOCH_task_startTime - task start diag_tickTime | Usage: diag_tickTime - EPOCH_task_startTime > _someDelayTime;
+//EPOCH_taskMarkerPos - Will override the built in marker position. Must be set at init stage, i.e. before marker is created.
+//EPOCH_taskTitle - As set by title in each task class.
+//EPOCH_taskLastLoop - is the diag_tickTime at the last loop start (based on taskCheckTime). Set to start time until loop starts.
+//EPOCH_taskItem - Weaponholder object used to hold task item. Is null object until items are spawned in.
+//EPOCH_taskMarkerName - Name for the marker generated automatically by the task system.
+//
+//Stand alone missions can be called by triggering the first task class with: epochTaskHandle = ["myTaskClass"] execFSM "epoch_code\System\task_control.fsm";
+//
+
+
+class taskWithComments{
+ //Task Author
+ author = "axeman";
+ //Task Title as appears in (Accept / Decline) dialogue box. Leave as "" to trigger code only.
+ //title, desc and img are WIP and will be used for future dialogue GUIs.
+ title = "Find the Backpack.";
+ //Description on task. For dialogue box.
+ desc = "Our new friend has lost his backpack. Find it in a nearby house. It will be within 50m and looks like a white package. He needs the contents to continue on his way.";
+ //Task Image. For dialogue box.
+ img = "\A3\Characters_F_EPA\Data\ui\Icon_V_plate_carrier_snake_ca.paa";
+ //Simple tasks are used for one off calls, e.g. Ask the trader the time. initfsm, initsqf and/or initcall will be triggered and the task will exit with no monitoring.
+ simpleTask = 0;
+ //Trigger this task. Use this condition to trigger the task (WIP - Mission and Individual Task Triggers from the Main Loop)
+ triggerCondition = "count nearestObjects [player,[""house""],250] > 8";
+ //Limit the number of times this task can run for player per life or server restart. (WIP - Part of client / server mission & task monitoring) - Leave as default !
+ taskLimit = 3;
+ //Pause time in the task loop. This figure is also applied before triggering completion of mission and again before cleanup / reminder / next task.
+ taskCheckTime = 16;
+ //A pause at the start of the task after collecting variables, before anything is created. TODO: maybe remove..
+ triggerDelay = 16;
+ //Spawn helper objects at start of task / mission (e.g. a hatchet for a tree chopping task). Array will accept any object classes which will be positioned appropriately (WIP - Mainly to support vehicle spawning).
+ items[] = {"ItemSodaOrangeSherbet","itemGPS"};
+ //Item Spawn (0 - Do not spawn, 1 - Nearby in House, 2 - Nearby Hidden, 3 - Near Player)
+ itemSpawn = 1;
+
+ //Call these functions at init of task, after item spawn but before marker creation. Allows setting EPOCH_taskMarkerPos
+ initfsm = "";
+ initsqf = "";
+ initcall = "systemChat 'STARTING FROM CONFIG'";
+
+ //Place a marker on task target (0 = No Marker, 1 = Marker, with text, exactly on target, 2 = radial marker with target somewhere random inside marker)
+ markerType = 2;
+ //Set marker radius for radial marker (markerType = 2)
+ markerRadius = 50;
+ //Marker Text - Add text to marker, leave "" for no text. No text available for Marker type 2 yet.
+ markerText = "Last seen here somewhere.";
+ //task fsm / sqf. Call an sqf or FSM, designed to manage the mission locally. Will trigger at task start (After specified delay)
+ //All FSM & SQF Calls pass default variables. e.g. [player ,EPOCH_taskItem] execVM "yourSQF.sqf";
+ //Both options (SQF or FSM) will be presented when a script call is available. Both will be called if value is not ""
+ //All sqf, fsm files are stored, by default, in \epoch_code\compile\missions\tasks\ (WIP - Can be edited with the task setting in CfgMissionTasks.hpp)
+ //TODO - Reduce to just call so these can all be pre-CompileFinaled
+
+ //Call additional functions based on condition, e.g. air drop, antagonist spawn, or custom code.
+ //Conditions must return a boolean. e.g. player distance player < 12;
+ callEventBinTask = 0;//If calling another task (callEventTask1 etc.) then bin this task before starting the new one ? - WIP
+ callEventCondition1 = "true";
+ callEventCondition2 = "EPOCH_taskItem distance player < 50";
+ callEventCondition3 = "";
+
+ //All sqf, fsm files are stored, by default, in \epoch_code\compile\missions\tasks\ (WIP - Can be edited with the task setting above)
+ callEventCALL1 = "";
+ callEventFSM1 = "";
+ callEventSQF1 = "triggerAirDrop.sqf";
+ //Call another task class from the same mission.
+ callEventTask1 = "";
+
+ callEventCALL2 = "hint 'You are getting warm'";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+
+ //dialogues. One of the array will be selected randomly upon each trigger
+ //Dialogue 1 will trigger only one time upon it's condition, designed to be a welcome message.
+ diag1Condition = "true";
+ dialogue1[] = {"Ok, first thing I need to do is find my rucksack","Help me find my rucksack first.","I need to find my rucksack."};
+
+ //Delay between triggering dialogue, to stop flooding.
+ diagSquelch = 60;
+ //Dialogue 2 and 3 will repeat everytime the condition is met and the squelch time has elapsed. Designed as warnings / hint dialogues. Again, a random message will be chosen from the array.
+ diag2Condition = "diag_tickTime - EPOCH_task_startTime > 20";
+ dialogue2[] = {"I dropped it in one of these buildings. Some.. thing was chasing me.","It is in a house nearby, I have a map that I need in it.","Search the nearby houses until you find it."};
+ diag3Condition = "EPOCH_taskItem distance player < 12";
+ dialogue3[] = {"Wow, you are really close now.","Keep looking, it is right near you.","Smoking hot, you are practically standing on it."};
+
+ //FAILED / ABANDONED
+ //Apply a condition to detect mission failure. e.g. '!alive _unit' if escorting a NPC. Task will bin upon player death anyway.
+ failedCondition = "!alive player";
+ //Abandon Distance - Player moves this far from 'task trigger position' causes abandonment of mission (0 = unlimited)
+ abandonDist = 100;
+ //Time Limit - Once time limit is reached, and completed condition is not met, the mission has failed and will be disposed. 0 = No Limit.
+ abandonTime = 240;
+ //Failed Message (triggered by timeLimit or abandon distance) - Display random message from array upon task failure.
+ failed[] = {"You blew it.","Don't give up your day job pal..","That's you finished mate, bring on the pain."};
+ //Run a command to punish failure of task (triggered by timeLimit or failure condition).
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "[] call EPOCH_callSapperMigration;";
+ //Add failure task. Can be multiple tasks that are picked at random.
+ failedTask[] = {""};
+ //Dispose of task item at failure 0 = No, 1 = Yes. Cleans up any spawned weaponholders.
+ cleanUp = 1;
+ //Upon FSM disposal call compile each piece of code. Designed to cleanup namespace(s).
+ cleanUpCalls[] = {""};
+ //COMPLETED
+ //Condition met to trigger completion of task.
+ completeCondition = "EPOCH_taskItem distance player < 2";
+ //Drop reward for player - Currently always nearby, on the floor.
+ reward[] = {"ItemSodaOrangeSherbet","ItemSodaPurple","ItemSodaMocha"};
+ //Completed dialogues, selected randomly from each array. With pause in-between completed1 and completed2.
+ completed1[] = {"Well done, that was quick. Let me have it, and here's something for you.","You've found it, good job. I have something in here you can have.","Well found, you're a natural. Here, this is yours, thank you."};
+ completed2[] = {"Now let's head out of town, you lead the way !","It's time to leave this area, let's go !","Do you think we should get out of this area now ?"};
+ //Remind / hint to the player to get them onto the NEXT task. Displays after longer pause
+ reminder[] = {"It's about time we headed out of town.","We need to get away from these houses.","Let's move away from these built up areas."};
+ //Trigger next task at disposal of this one. Allows tasks to be strung together. If more than one a task is selected at random. Leave blank to end mission and reset menu item at trader.
+ nextTask[] = {"findHouseItem"};
+};
+
+class blankTaskWithDefaults{
+ author = "axeman";
+ title = "";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 16;
+ items[] = {""};
+ itemSpawn = 1;
+ markerType = 2;
+ markerRadius = 50;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "";
+ callEventBinTask = 0;
+ callEventCondition1 = "";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "";
+ dialogue1[] = {""};
+ diagSquelch = 60;
+ diag2Condition = "";
+ dialogue2[] = {""};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = 100;
+ abandonTime = 240;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 1;
+ cleanUpCalls[] = {};
+ completeCondition = "";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "";
+ reminder[] = {""};
+ nextTask[] = {""};
+};
\ No newline at end of file
diff --git a/Sources/epoch_config/Configs/CfgMissions/CfgTraderDiags.hpp b/Sources/epoch_config/Configs/CfgMissions/CfgTraderDiags.hpp
new file mode 100644
index 00000000..6ef3141d
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions/CfgTraderDiags.hpp
@@ -0,0 +1,71 @@
+class traderDiagTime{
+author = "axeman";
+title = "Trader Time";
+//Simple task will skip all monitoring and run the provided code (call, fsm, sqf) only.
+simpleTask = 1;
+initsqf = "traderDiag_timePlease.sqf";
+initfsm = "";
+initcall = "";
+//Next task is allowed to trigger a task if required.
+nextTask[] = {};
+};
+
+class traderDiagNearby{
+author = "axeman";
+title = "Trader Near By Players";
+simpleTask = 1;
+initsqf = "traderDiag_nearPlayers.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
+
+class traderDiagNews{
+author = "axeman";
+title = "Trader News";
+simpleTask = 1;
+initsqf = "traderDiag_news.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
+
+class traderDiagName{
+author = "axeman";
+title = "Traders Name";
+simpleTask = 1;
+initsqf = "traderDiag_name.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
+
+class traderNearVehicles{
+author = "axeman";
+title = "Trader Nearby Vehicles";
+simpleTask = 1;
+initsqf = "traderDiag_nearVehicles.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
+
+class traderTriggerAirDrop{
+author = "axeman";
+title = "Trigger AirDrop";
+simpleTask = 1;
+initsqf = "traderDiag_triggerAirDrop.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
+
+class traderMissionReset{
+author = "axeman";
+title = "Reset Missions";
+simpleTask = 1;
+initsqf = "traderDebug_resetMissions.sqf";
+initfsm = "";
+initcall = "";
+nextTask[] = {};
+};
\ No newline at end of file
diff --git a/Sources/epoch_config/Configs/CfgMissions/CfgmissionDelivery.hpp b/Sources/epoch_config/Configs/CfgMissions/CfgmissionDelivery.hpp
new file mode 100644
index 00000000..c73f3d91
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions/CfgmissionDelivery.hpp
@@ -0,0 +1,232 @@
+class prepForDelivery{
+ author = "axeman";
+ title = "Prep for Delivery";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 0;
+ items[] = {"ItemDocumentMission"};
+ itemSpawn = 3;
+ markerType = 0;
+ markerRadius = 0;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "axeDocDeliveryStart = diag_tickTime";
+ callEventBinTask = 0;
+ callEventCondition1 = "(""ItemDocumentMission"" in magazines player)";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "uiNameSpace setVariable ['axeStartTraders',(player nearentities [[""C_Man_1""],500]) apply {_x getVariable [""AI_SLOT"",-1]}]";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "true";
+ dialogue1[] = {"Pick up the Document to Start."};
+ diagSquelch = 60;
+ diag2Condition = "!(""ItemDocumentMission"" in magazines player)";
+ dialogue2[] = {"Come on Buddy, Pick it up !","It's right next to you on the floor, pick it up to start."};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = 100;
+ abandonTime = 240;
+ failed[] = {"I guess you have better things to do.","Try again later.","You didn't pick up the document. Misison Failed !"};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 1;
+ cleanUpCalls[] = {"uiNameSpace setVariable ['axeStartTraders', nil]"};
+ completeCondition = "('ItemDocumentMission' in magazines player)";
+ reward[] = {};
+ completed1[] = {"That's great, let's get out of here.","Good, you have the document, let's move on.","Ok, well done. We can start now."};
+ completed2[] = {""};
+ reminder[] = {""};
+ nextTask[] = {"doDelivery"};
+};
+class doDelivery{
+ author = "axeman";
+ title = "Do Delivery";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "(""ItemDocumentMission"" in magazines player)";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 3;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 0;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "";
+ callEventBinTask = 0;
+ callEventCondition1 = "(axeDocDeliveryStart + 480 < diag_tickTime) && ((player nearentities [[""C_Man_1""],500]) apply {_x getVariable [""AI_SLOT"",-1]} isEqualTo (uiNameSpace getVariable [""axeStartTraders"",[]]))";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "[""Hey, what are you doing here ? Get on with your task !"", 5] call Epoch_dynamicText";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "(""ItemDocumentMission"" in magazines player)";
+ dialogue1[] = {"Ok, head off to another trader, you can't deliver to any nearby.","All set. Now take that document to another trader further away.","Take that message to another trader or trader city."};
+ diagSquelch = 40;
+ diag2Condition = "!('ItemDocumentMission' in magazines player)";
+ dialogue2[] = {"Don't leave that document anywhere.","If you lose that document you will fail the mission."};
+ diag3Condition = "(count (player nearentities [[""C_Man_1""],42]) > 0) && (count (((player nearentities [[""C_Man_1""],42]) apply {_x getVariable [""AI_SLOT"",-1]}) select {_x in (uiNameSpace getVariable [""axeStartTraders"",[]])}) < 1)";
+ dialogue3[] = {"Well done, you have a trader nearby, go see him","Looks like you found another trader, well done, deliver the message.","UAV has spotted another trader nearby, go deliver the message."};
+ failedCondition = "";
+ abandonDist = 0;
+ abandonTime = 1800;
+ failed[] = {"Looks like you took too long buddy, Mission Over.","You need to be quicker next time, Mission Over !","Misison Failed - You took too long, better luck next time."};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 0;
+ cleanUpCalls[] = {"uiNameSpace setVariable ['axeStartTraders', nil]"};
+ completeCondition = "(count (player nearentities [[""C_Man_1""],6]) > 0) && (count (((player nearentities [[""C_Man_1""],6]) apply {_x getVariable [""AI_SLOT"",-1]}) select {_x in (uiNameSpace getVariable [""axeStartTraders"",[]])}) < 1)";
+ reward[] = {};
+ completed1[] = {"Hey there pal, it looks like you have something for me ?","Great Job there. Step into my office traveller.","You made it, time to take a look at that message."};
+ completed2[] = {""};
+ reminder[] = {""};
+ nextTask[] = {"finishDelivery"};
+};
+class finishDelivery{
+ author = "axeman";
+ title = "Finish Delivery";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "(""ItemDocumentMission"" in magazines player)";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 3;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 0;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "axeRndBadNews = floor random 100";
+ callEventBinTask = 1;
+ callEventCondition1 = "(""ItemDocumentMission"" in magazines player)";
+ callEventCondition2 = "axeRndBadNews < 6";
+ callEventCondition3 = "";
+ callEventCALL1 = "player removeMagazine ""ItemDocumentMission""";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "deliveryMissionBadNews";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "axeRndBadNews > 5";
+ dialogue1[] = {"That's interesting news. Thanks for bringing this.","Great news, you did well to bring this to me."};
+ diagSquelch = 60;
+ diag2Condition = "";
+ dialogue2[] = {""};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = 0;
+ abandonTime = 240;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {};
+ cleanUp = 0;
+ cleanUpCalls[] = {"uiNameSpace setVariable ['axeStartTraders', nil]"};
+ completeCondition = "axeRndBadNews > 5";
+ reward[] = {};
+ completed1[] = {"Take your reward, you have earnt it","Here is your reward, you are a great courier.","Any time you need work, come and see me, great job."};
+ completedCALL = "axeRewardWH = createVehicle[""groundWeaponHolder"",getPosATL player,[],0,""CAN_COLLIDE""];[axeRewardWH,""Pelican_EPOCH""] remoteExec [""EPOCH_serverLootObject"",2];";
+ reminder[] = {""};
+ nextTask[] = {};
+};
+class deliveryMissionBadNews{
+ author = "axeman";
+ title = "Delivery Gone Bad";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 4;
+ triggerDelay = 3;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 50;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "[player,6] call EPOCH_callSapperMigration";
+ callEventBinTask = 0;
+ callEventCondition1 = "";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "true";
+ dialogue1[] = {"Oh my, that's terrible, why did you bring me this news ?","No no no, why would you do this to me, this is awful news."};
+ diagSquelch = 60;
+ diag2Condition = "";
+ dialogue2[] = {""};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = 100;
+ abandonTime = 240;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 1;
+ cleanUpCalls[] = {"uiNameSpace setVariable ['axeStartTraders', nil]"};
+ completeCondition = "true";
+ reward[] = {""};
+ completed1[] = {"You are going to pay for that, get out of my sight","Nobody does that to me, go away.","I would run buddy, I am not pleased."};
+ completed2[] = {""};
+ reminder[] = {""};
+ nextTask[] = {};
+};
\ No newline at end of file
diff --git a/Sources/epoch_config/Configs/CfgMissions/CfgmissionMilitary.hpp b/Sources/epoch_config/Configs/CfgMissions/CfgmissionMilitary.hpp
new file mode 100644
index 00000000..00265166
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions/CfgmissionMilitary.hpp
@@ -0,0 +1,296 @@
+class milMissionAccepted{
+ author = "axeman";
+ title = "Military Crash Site";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 3;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 250;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "";
+ callEventBinTask = 0;
+ callEventCondition1 = "";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "true";
+ dialogue1[] = {"A militia group has stolen military aircraft from a nearby airfield.","A stolen military aircraft has just taken off from an airport nearby.","I have received word that a splinter group are stealing an aircraft."};
+ diagSquelch = 30;
+ diag2Condition = "";
+ dialogue2[] = {""};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = -1;
+ abandonTime = 480;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 0;
+ cleanUpCalls[] = {};
+ completeCondition = "true";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "";
+ reminder[] = {""};
+ nextTask[] = {"milSpawnCrashSite"};
+};
+class milSpawnCrashSite{
+ author = "axeman";
+ title = "Military Spawn Crash Site";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 0;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 250;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "[] spawn {milCrashPos = [position player, 1000, 2550, 0, 0, 1000, 0] call BIS_fnc_findSafePos;terminate _thisScript;};";
+ callEventBinTask = 0;
+ callEventCondition1 = "(diag_tickTime - EPOCH_task_startTime) > 12";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "[player,Epoch_personalToken,selectRandom [""B_Plane_CAS_01_F"",""O_Heli_Attack_02_black_F"",""B_UAV_02_CAS_F"",""I_Plane_Fighter_03_AA_F ""],milCrashPos,objNull,false,""CAN_COLLIDE"","""","""","""","""",true] remoteExec [""EPOCH_Server_createObject"",2];";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "(diag_tickTime - EPOCH_task_startTime) > 6";
+ dialogue1[] = {"As suspected, the aircraft was sabotaged and has crashed.","An inept theft attempt, the aircraft has gone down.","Something went wrong, my UAV has spotted the aircraft, it has crashed nearby."};
+ diagSquelch = 15;
+ diag2Condition = "true";
+ dialogue2[] = {};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = -1;
+ abandonTime = 480;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 0;
+ cleanUpCalls[] = {};
+ completeCondition = "(diag_tickTime - EPOCH_task_startTime) > 18";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "true";
+ reminder[] = {"Wait 10, I am triangulating the position.","Hold your position and wait for the location","I am calculating the location of the crash site."};
+ nextTask[] = {"milMarkCrashSite"};
+};
+class milMarkCrashSite{
+ author = "axeman";
+ title = "Mark Military Crash Site";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 3;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 500;
+ markerText = "Crash Site";
+ initfsm = "";
+ initsqf = "";
+ initcall = "[[1,player],milCrashPos,""ELLIPSE"",""mil_dot"",""Crash Site"",""ColorRed"",[800,800], ""SolidBorder"", 42, 0.6] remoteExec [""EPOCH_server_createMarker"",2];";
+ callEventBinTask = 0;
+ callEventCondition1 = "true";
+ callEventCondition2 = "true";
+ callEventCondition3 = "true";
+ callEventCALL1 = "milWH1 = createVehicle[""groundWeaponHolder"", milCrashPos, [], 4, ""CAN_COLLIDE""];removeFromRemainsCollector [milWH1];[milWH1,""Pelican_EPOCH""] remoteExec [""EPOCH_serverLootObject"",2];";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "milWH2 = createVehicle[""groundWeaponHolder"", milCrashPos, [], 4, ""CAN_COLLIDE""];removeFromRemainsCollector [milWH2];[milWH2,""ToolRack_EPOCH""] remoteExec [""EPOCH_serverLootObject"",2];";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "milWH3 = createVehicle[""groundWeaponHolder"", milCrashPos, [], 4, ""CAN_COLLIDE""];removeFromRemainsCollector [milWH3];[milWH3,""AirDrop_Payout1""] remoteExec [""EPOCH_serverLootObject"",2];";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "(diag_tickTime - EPOCH_task_startTime) > 6";
+ dialogue1[] = {"Check your map, I have marked the site in red for your team.","Your map has been marked.","I have added a marker for your team."};
+ diagSquelch = 30;
+ diag2Condition = "(diag_tickTime - EPOCH_task_startTime) > 31";
+ dialogue2[] = {"Reports are it was last spotted in that area..","Search the area, it was seen coming down from that location.","Be sure to search the area, the marker is the last know location."};
+ diag3Condition = "(diag_tickTime - EPOCH_task_startTime) > 128";
+ dialogue3[] = {"Be careful, I have spotted another UAV.","An enemy UAV is scouting the location","Keep a low profile, the enemy are scouting the area."};
+ failedCondition = "";
+ abandonDist = -1;
+ abandonTime = 1280;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 0;
+ cleanUpCalls[] = {};
+ completeCondition = "(diag_tickTime - EPOCH_task_startTime) > 60";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "";
+ reminder[] = {""};
+ nextTask[] = {"milFindCrashSite"};
+};
+class milFindCrashSite{
+ author = "axeman";
+ title = "Military Crash Site Hunt";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 20;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 250;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "milDoUAV = false;";
+ callEventBinTask = 0;
+ callEventCondition1 = "count (units group player select {_x distance milCrashPos < 800}) > 0";
+ callEventCondition2 = "count (units group player select {_x distance milCrashPos < 480}) > 0 && random 100 < 12";
+ callEventCondition3 = "";
+ callEventCALL1 = "_diag = format [""Great work the UAV has spotted %1 nearly on-site."",name ((units group player select {_x distance milCrashPos < 800}) select 0)];[format [""%1"",_diag], 5] call Epoch_dynamicText;";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "[(selectRandom (units group player select {_x distance milCrashPos < 480}))] execVM ""epoch_code\compile\missions\tasks\mission_spawnUAV.sqf"";milDoUAV = true;";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "count (units group player select {_x distance milCrashPos < 1000}) > 0";
+ dialogue1[] = {"Keep going you are getting close now","You are closing in on the target.","You are nearly there. Keep it up."};
+ diagSquelch = 60;
+ diag2Condition = "milDoUAV";
+ dialogue2[] = {"Enemy UAV spotted, you've got company.","You've got another UAV in the area, keep low.","Find a spot to hide, enemy UAV incoming."};
+ diag3Condition = "count (units group player select {_x distance milCrashPos < 60}) > 0";
+ dialogue3[] = {"You've made it, find any loot.","Search the area, there will be loot around","There should be plenty to scavange."};
+ failedCondition = "";
+ abandonDist = -1;
+ abandonTime = 4800;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 0;
+ cleanUpCalls[] = {};
+ completeCondition = "(diag_tickTime - EPOCH_task_startTime) > 4600 || count (units group player select {_x distance milWH1 < 60}) > 0";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "";
+ reminder[] = {""};
+ nextTask[] = {"milEndCrashSite"};
+};
+
+class milEndCrashSite{
+ author = "axeman";
+ title = "";
+ desc = "";
+ img = "";
+ simpleTask = 0;
+ triggerCondition = "";
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 16;
+ items[] = {""};
+ itemSpawn = 1;
+ markerType = 0;
+ markerRadius = 50;
+ markerText = "";
+ initfsm = "";
+ initsqf = "";
+ initcall = "";
+ callEventBinTask = 0;
+ callEventCondition1 = "";
+ callEventCondition2 = "";
+ callEventCondition3 = "";
+ callEventCALL1 = "";
+ callEventFSM1 = "";
+ callEventSQF1 = "";
+ callEventTask1 = "";
+ callEventCALL2 = "";
+ callEventFSM2 = "";
+ callEventSQF2 = "";
+ callEventTask2 = "";
+ callEventCALL3 = "";
+ callEventFSM3 = "";
+ callEventSQF3 = "";
+ callEventTask3 = "";
+ diag1Condition = "true";
+ dialogue1[] = {"Well done, that was a good find","You are an official scavenger now, congratulations.","Your loot is welcome at my store any time."};
+ diagSquelch = 60;
+ diag2Condition = "";
+ dialogue2[] = {""};
+ diag3Condition = "";
+ dialogue3[] = {""};
+ failedCondition = "";
+ abandonDist = 100;
+ abandonTime = 240;
+ failed[] = {""};
+ failedFSM = "";
+ failedSQF = "";
+ failedCall = "";
+ failedTask[] = {""};
+ cleanUp = 1;
+ cleanUpCalls[] = {};
+ completeCondition = "true";
+ reward[] = {""};
+ completed1[] = {""};
+ completed2[] = {""};
+ completedCALL = "";
+ reminder[] = {""};
+ nextTask[] = {""};
+};
\ No newline at end of file
diff --git a/Sources/epoch_config/Configs/CfgMissions/CfgmissionUav.hpp b/Sources/epoch_config/Configs/CfgMissions/CfgmissionUav.hpp
new file mode 100644
index 00000000..f9a73e26
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissions/CfgmissionUav.hpp
@@ -0,0 +1,166 @@
+class uavMissionAccepted{
+ author = "axeman";
+ title = "UAV Mission Accepted";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 3;
+ triggerDelay = 2;
+ items[] = {"B_UavTerminal"};
+ itemSpawn = 3;
+ markerType = 0;
+ markerRadius = 0;
+ callEventBinTask = 0;
+ diag1Condition = "true";
+ dialogue1[] = {"The UAV terminal is at your feet, Equip it !","Pick up the terminal and equip yourself with it.","Grab the UAV terminal and put it in your GPS slot."};
+ diagSquelch = 30;
+ diag2Condition = "!('B_UavTerminal' in assignedItems player)";
+ dialogue2[] = {"Hurry it up, pick up and equip the terminal.","Come on, Equip yourself with the terminal.","We don't have all day, get that terminal equipped."};
+ abandonDist = 100;
+ abandonTime = 240;
+ failed[] = {"I guess you have better things to do.","Try again later.","You didn't pick up the terminal. Misison Failed !"};
+ cleanUp = 0;
+ completeCondition = "'B_UavTerminal' in assignedItems player";
+ completed1[] = {"That's great, you have 30 seconds to find a safe position.","Find a hidden spot to operate from, take off in 30 seconds.","Find yourself a concealed position to work from, taking off in half a minute."};
+ nextTask[] = {"doUAVSpawn"};
+};
+class doUAVSpawn{
+ author = "axeman";
+ title = "UAV Spawn";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 8;
+ triggerDelay = 30;
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 0;
+ initcall = "axeUAV = objNull";
+ callEventBinTask = 0;
+ callEventCondition1 = "(diag_tickTime - EPOCH_task_startTime) > 6";
+ callEventCALL1 = "_targetPos = (getPosATL player) findEmptyPosition [25,250,""I_UAV_01_F""];axeUAV = createVehicle[""I_UAV_01_F"", _targetPos, [], 10, ""CAN_COLLIDE""];_driver = (group player) createUnit[""I_UAV_AI"", position axeUAV, [], 0, ""CAN_COLLIDE""];_driver moveInAny axeUAV;";
+ diag1Condition = "true";
+ dialogue1[] = {"UAV is ready, get prepared !","Here it comes, connecting you now. 10 seconds..","Nice spot, connecting you to the UAV !"};
+ diagSquelch = 60;
+ failedCondition = "!('B_UavTerminal' in assignedItems player)";
+ abandonDist = -1;
+ abandonTime = 1200;
+ failed[] = {"Lost it already.. Mission Over","Not a willing pilot eh ? Try again later.","Equipment Lost.. Mission Failed !"};
+ cleanUp = 0;
+ completeCondition = "!(isNull axeUAV)";
+ nextTask[] = {"doUAVAttach"};
+};
+class doUAVAttach{
+ author = "axeman";
+ title = "UAV Spawn";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 6;
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 0;
+ initcall = "player connectTerminalToUAV axeUAV;player action [""SwitchToUAVDriver"", axeUAV];addToRemainsCollector[axeUAV];";
+ callEventBinTask = 0;
+ diag1Condition = "true";
+ dialogue1[] = {"Woohoo, here we go.. Get it in the air.","Get it in the air, no time to waste","You are a natural kid. Let's fly."};
+ diagSquelch = 60;
+ failedCondition = "!('B_UavTerminal' in assignedItems player) || !(alive axeUAV)";
+ abandonDist = -1;
+ abandonTime = 1200;
+ failed[] = {"Lost it already.. Mission Over","Not a natural pilot. Try again later.","Mission Failed !"};
+ cleanUp = 0;
+ completeCondition = "(getPosATL axeUAV select 2) > 10";
+ completedCALL = "if(SunOrMoon < 1)then{player action [""lightOn"", axeUAV];};";
+ nextTask[] = {"takeOffUAV"};
+};
+class takeOffUAV{
+ author = "axeman";
+ title = "Pilot the UAV";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 8;
+ triggerDelay = 6;
+ itemSpawn = 0;
+ markerType = 0;
+ markerRadius = 0;
+ initcall = "axeUAVRndMission = floor random 2;";
+ callEventBinTask = 1;
+ callEventCondition1 = "(diag_tickTime - EPOCH_task_startTime > 30) && axeUAVRndMission == 0";
+ callEventCondition2 = "(diag_tickTime - EPOCH_task_startTime > 30) && axeUAVRndMission == 1";
+ callEventTask1 = "uavMission1";
+ callEventTask2 = "uavMission2";
+ diag1Condition = "alive axeUAV";
+ dialogue1[] = {"Great start.. Lets take this thing for a ride.","We're off, get some practice, I am finding you a target.","Get clear of this area, I am calculating your target."};
+ diagSquelch = 60;
+ diag2Condition = "alive axeUAV";
+ dialogue2[] = {"Keep it up, you are doing a great job.","Try and find some targets on your way.","Don't get shot down now !"};
+ failedCondition = "!('B_UavTerminal' in assignedItems player) || !(alive axeUAV)";
+ abandonDist = -1;
+ abandonTime = 1280;
+ failed[] = {"Oh dear, that didn't go well..","Try again later.","Misison Failed !"};
+ cleanUp = 0;
+ completeCondition = "false";
+ completedCALL = "player connectTerminalToUAV objNull;";
+ nextTask[] = {};
+};
+class uavMission1{
+ author = "axeman";
+ title = "Trader House Recon";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 8;
+ items[] = {""};
+ itemSpawn = 0;
+ markerType = 2;
+ markerRadius = 180;
+ markerText = "Trader House Recon";
+ initcall = "[] spawn {uavMission1Obj = selectRandom (nearestObjects [axeUAV,[""HOUSE""],2500]);EPOCH_taskMarkerPos = getPosATL uavMission1Obj;};";
+ callEventBinTask = 0;
+ diag1Condition = "true";
+ dialogue1[] = {"I need some recon on a nearby house","We need intelligence on a potential trader location.","Help us gather intel on a trader house !"};
+ diagSquelch = 60;
+ diag2Condition = "EPOCH_taskMarkerPos distance axeUAV > 450";
+ dialogue2[] = {"I have marked your map, it will be nearby.","Check you map, there is a marker near a safehouse","Search your map for the landing zone, near a traders safehouse."};
+ diag3Condition = "EPOCH_taskMarkerPos distance axeUAV < 450";
+ dialogue3[] = {"Land it nearby and switch off the engine.","You need to land by the house, quietly.","Drop the UAV in the marker, then keep quiet."};
+ failedCondition = "!('B_UavTerminal' in assignedItems player) || !(alive axeUAV)";
+ abandonDist = -1;
+ abandonTime = 2200;
+ failed[] = {"Oh dear, Mission Over !","Mission Failed !"};
+ cleanUp = 1;
+ completeCondition = "!(isengineOn axeUAV) && EPOCH_taskMarkerPos distance axeUAV < 275";
+ reward[] = {"ItemGoldBar","ItemGoldBar"};
+ completed1[] = {"Great work, here's your reward."};
+ completedCALL = "player connectTerminalToUAV objNull;[(driver axeUAV)] joinSilent grpNull;";
+};
+class uavMission2{
+ author = "axeman";
+ title = "Deliver UAV To Trader";
+ simpleTask = 0;
+ taskLimit = 3;
+ taskCheckTime = 16;
+ triggerDelay = 8;
+ itemSpawn = 0;
+ markerType = 2;
+ markerRadius = 220;
+ markerText = "UAV Trader";
+ initcall = "[] spawn {EPOCH_taskUAVTrader = selectRandom (player nearentities [[""C_Man_1""],10500] select {_x getVariable [""AI_SLOT"",-1] > -1 && player distance _x > 50});EPOCH_taskMarkerPos = getPosATL EPOCH_taskUAVTrader;};";
+ callEventBinTask = 0;
+ diag1Condition = "true";
+ dialogue1[] = {"I need this UAV delivering to my buddy","Recon a rogue trader, land this near his location.","Land this UAV near the target trader."};
+ diagSquelch = 60;
+ diag2Condition = "EPOCH_taskMarkerPos distance axeUAV > 450";
+ dialogue2[] = {"Check your map for his location, you will need to land nearby.","I have marked your map with his location.","Fly to the location marked on your map, then land."};
+ diag3Condition = "EPOCH_taskMarkerPos distance axeUAV < 450";
+ dialogue3[] = {"Get this thing down and the engine off.","Land in the zone and switch your engine off quickly.","Find a landing spot in the area and keep quiet."};
+ failedCondition = "!('B_UavTerminal' in assignedItems player) || !(alive axeUAV)";
+ abandonDist = -1;
+ abandonTime = 2600;
+ failed[] = {"Oh dear, Mission Over !","Mission Failed !"};
+ cleanUp = 1;
+ cleanUpCalls[] = {"player connectTerminalToUAV objNull"};
+ completeCondition = "!(isengineOn axeUAV) && EPOCH_taskMarkerPos distance axeUAV < 275";
+ reward[] = {"ItemGoldBar","ItemGoldBar"};
+ completed1[] = {"Great work, here's your reward."};
+ completedCALL = "player connectTerminalToUAV objNull;[(driver axeUAV)] joinSilent grpNull;";
+};
diff --git a/Sources/epoch_config/Configs/CfgMissionsTasks.hpp b/Sources/epoch_config/Configs/CfgMissionsTasks.hpp
new file mode 100644
index 00000000..f8fa803c
--- /dev/null
+++ b/Sources/epoch_config/Configs/CfgMissionsTasks.hpp
@@ -0,0 +1,20 @@
+class inGameTasks {
+
+ //Preset custom vars for use in task conditions - Count must match
+ //At task start the varNames variables will be added as missionNameSpace variables using the corresponding varData.
+ varName[] = {"_milBuildings","_testVar"};
+ varData[] = {{"Cargo_HQ_base_F","Cargo_Tower_base_F","Cargo_Patrol_base_F"},"""TestVal"""};
+
+ //Filter out building classes from spawn areas. Some buildings just aren't suitable. NB. A garrison (buildingPos) point is required when spawning items in a building.
+ filterBuilds[] = {"Land_i_Addon_03_V1_F","Land_Offices_01_V1_F"};
+
+ //Path to task files (sqf,fsm etc.)
+ file = "epoch_code\compile\missions\tasks";
+ //Path to main task control fsm - NB. Requires manually setting in mission accept sqf.
+ fsmpath = "epoch_code\system";
+
+#include "CfgMissions\CfgTraderDiags.hpp"
+#include "CfgMissions\CfgmissionDelivery.hpp"
+#include "CfgMissions\CfgmissionUav.hpp"
+#include "CfgMissions\CfgmissionMilitary.hpp"
+};
\ No newline at end of file
diff --git a/Sources/epoch_config/Configs/CfgPricing.hpp b/Sources/epoch_config/Configs/CfgPricing.hpp
index b86b1b75..bb407b24 100644
--- a/Sources/epoch_config/Configs/CfgPricing.hpp
+++ b/Sources/epoch_config/Configs/CfgPricing.hpp
@@ -785,7 +785,7 @@ class CfgPricing
class smallbackpack_green_epoch {price = 22;};
class smallbackpack_teal_epoch {price = 22;};
class smallbackpack_pink_epoch {price = 22;};
-
+ class I_UAV_01_backpack_F {price = 22;};
// Marksman DLC
class U_O_FullGhillie_lsh { price = 7; };
class U_O_FullGhillie_sard { price = 7; };
@@ -1033,6 +1033,7 @@ class CfgPricing
class O_Heli_Transport_04_box_EPOCH {price = 2500;};
class O_Heli_Transport_04_covered_EPOCH {price = 2500;};
class B_Heli_Transport_03_unarmed_EPOCH {price = 2500;};
+ class I_UAV_01_F {price = 50;};
class jetski_epoch {price = 500;};
class ebike_epoch {price = 1500;};
diff --git a/Sources/epoch_config/Configs/CfgRemoteExec.hpp b/Sources/epoch_config/Configs/CfgRemoteExec.hpp
index fbef7146..8c8e053b 100644
--- a/Sources/epoch_config/Configs/CfgRemoteExec.hpp
+++ b/Sources/epoch_config/Configs/CfgRemoteExec.hpp
@@ -208,6 +208,22 @@ class CfgRemoteExec
class epoch_server_playersetvariable {
allowedTargets=2;
jip = 0;
+ };
+ class EPOCH_spawn_vehicle {
+ allowedTargets=2;
+ jip = 0;
+ };
+ class EPOCH_Server_missionComms {
+ allowedTargets=2;
+ jip = 0;
+ };
+ class EPOCH_serverLootObject {
+ allowedTargets=2;
+ jip = 0;
+ };
+ class EPOCH_server_createmarker {
+ allowedTargets=2;
+ jip = 0;
};
};
diff --git a/Sources/epoch_config/sandbox_config.hpp b/Sources/epoch_config/sandbox_config.hpp
index eca28b36..726a51fa 100644
--- a/Sources/epoch_config/sandbox_config.hpp
+++ b/Sources/epoch_config/sandbox_config.hpp
@@ -53,6 +53,8 @@ wreckRemovalMaxTime = 360;
disableRandomization[] = {"All"};
#include "Configs\CfgTraderMissions.hpp"
+#include "Configs\CfgMissions.hpp"
+#include "Configs\CfgMissionsTasks.hpp"
#include "Configs\cfgCrafting.hpp"
#include "Configs\cfgPricing.hpp"
#include "Configs\CfgEpochClient.hpp"
diff --git a/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_createObject.sqf b/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_createObject.sqf
index 2adc6d47..4a1dd273 100644
--- a/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_createObject.sqf
+++ b/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_createObject.sqf
@@ -4,7 +4,7 @@
Contributors: Aaron Clark
Description:
- Server side spawing of shipwreck loots
+ Server side spawing of mission objects
Licence:
Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
@@ -12,71 +12,204 @@
Github:
https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_createObject.sqf
*/
-private ["_grp","_driver","_gunner","_commander","_crew","_missionVehList","_obj"];
-params ["_player",["_token","",[""]],"_objType","_clearCargo","_pos",["_objSpc","CAN_COLLIDE"],"_driverType","_gunnerType","_commanderType","_crewType"];
+private ["_grp","_driver","_gunner","_commander","_crew","_missionVehList","_obj","_cfgPricing","_objClass","_vehicles","_backpacks","_weapons","_items","_magazines","_posOut","_posSafe","_inStr"];
+params ["_player",["_token","",[""]],["_objArr",[]],["_pos",[]],["_wepHolder",objNull],["_clearCargo",true],["_objSpc","CAN_COLLIDE"],["_driverType",""],["_gunnerType",""],["_commanderType",""],["_crewType",""],["_doDamage",false]];
-if !([_player,_token]call EPOCH_server_getPToken)exitWith{};
+diag_log format["Epoch Admin: Server_CreateObject: %1 for %2",_objArr, name _player];
-if (count _this != 11) exitWith {diag_log format ["Epoch: Debug: %1 exit with %2",__FILE__,_this]};
+if !([_player,_token]call EPOCH_server_getPToken) exitWith {diag_log format["Epoch Admin: Token failed for %1", name _player];};
+if (typeName _objArr == "STRING") then {if!(_objArr == "")then{_objArr = [_objArr];};};
+if (count _objArr < 1) exitWith {};
-_missionVehList = ["O_UAV_01_F","B_UAV_01_F","I_Boat_Armed_01_minigun_F","B_Heli_Transport_01_F",""];
-if!(_objType in _missionVehList)exitWith{};
+_cfgPricing = 'CfgPricing' call EPOCH_returnConfig;
+_allowedVehicleListName = ["allowedVehiclesList","allowedVehiclesList_CUP"] select EPOCH_modCUPVehiclesEnabled;
+_allowedVehiclesList = getArray(configFile >> "CfgEpoch" >> worldName >> _allowedVehicleListName);
+_vehicles = [];
+_backpacks = [];
+_weapons = [];
+_items = [];
+_magazines = [];
-if !(_pos isEqualTo []) then {
- _pos = (getPosATL _player) findEmptyPosition [1,250,_objType];
- if (count _pos < 1) then {
- _pos = getPosATL _player;
+if (_pos isEqualTo []) then {
+ _pos = (getPosATL _player);
+};
+
+if(count _pos < 3)then{
+_pos set [2,0];
+};
+
+
+//Sort Object Array
+{
+
+ //Weapons / Items
+ if(isClass (configFile >> "CfgWeapons" >> _x))then{
+
+ diag_log format["Epoch: Server_CreateObject: %1 Weapon / Item Found",_x];
+
+ if("ItemCore" in ([configFile >> "CfgWeapons" >> _x, true] call BIS_fnc_returnParents))then{
+ _items pushBack _x;
+ }else{
+ _weapons pushBack _x;
+ };
+
+ };
+
+ //Magazines
+ if(isClass (configFile >> "CfgMagazines" >> _x))then{
+
+ diag_log format["Epoch: Server_CreateObject: %1 Magaxine Found",_x];
+
+ if("ItemCore" in ([configFile >> "CfgMagazines" >> _x, true] call BIS_fnc_returnParents))then{
+ _items pushBack _x;
+ }else{
+ _magazines pushBack _x;
+ };
+
+ };
+
+ //BackPacks / Vehicles
+ if(isClass (configFile >> "CfgVehicles" >> _x))then{
+ if("Bag_Base" in ([configFile >> "CfgVehicles" >> _x, true] call BIS_fnc_returnParents))then{
+ _backpacks pushBack _x;
+ }else{
+
+ diag_log format["Epoch: Server_CreateObject: Vehicle Found %1 - Allowed: %2",_x, _x in _allowedVehiclesList];
+
+ //if(_x in _allowedVehiclesList)then{
+ //Not working ?
+
+ if(_x isKindOf "CAR" || _x isKindOf "AIR")then{
+ //_posSafe = [_pos, 0, 550, 6, 0, 1000, 0] call BIS_fnc_findSafePos;
+ //_posOut = _posSafe findEmptyPosition [1,75,_x];
+ _posOut = _pos;
+ };
+
+ if(_x isKindOf "SHIP")then{
+ _posSafe = [_pos, 0, EPOCH_dynamicVehicleArea, 10, 1, 1000, 0] call BIS_fnc_findSafePos;
+ _posOut = _posSafe findEmptyPosition [1,75,_x];
+ };
+
+ _vehicles pushBack [_x,_posOut];
+ //};
+ };
};
+
+}forEach _objArr;
+
+//Weapons, ammo, items, backpacks
+if(count _weapons > 0 || count _items > 0 || count _magazines > 0 || count _backpacks > 0)then{
+
+if(isNull _wepHolder)then{
+_wepHolder = createVehicle["groundWeaponHolder", _pos, [], 0.0, "CAN_COLLIDE"];
};
-//_doOwner = _this select 10;
-_obj = createVehicle [_objType, _pos, [], 0, _objSpc];
-_obj call EPOCH_server_setVToken;
-addToRemainsCollector[_obj];
-_obj disableTIEquipment true;
-_obj allowdamage false;
-_obj setPosATL _pos;
-_obj setFuel 1;
-//if (_doOwner) then {_obj setOwner (owner _player)};
+ //Weapons
+ if(count _weapons > 0)then{
+ {
+ diag_log format["Epoch: Server_CreateObject: %1 Weapon Spawn",_x];
+ _wepHolder addWeaponCargoGlobal [_x,1];
+ } forEach _weapons;
+ };
+
+ //Items
+ if(count _items > 0)then{
+ {
+ diag_log format["Epoch: Server_CreateObject: %1 Item Spawn",_x];
+ _wepHolder addItemCargoGlobal [_x,1];
+ } forEach _items;
+ };
+
+ //Magazines
+ if(count _magazines > 0)then{
+ {
+ diag_log format["Epoch: Server_CreateObject: %1 Magazine Spawn",_x];
+ _wepHolder addMagazineCargoGlobal [_x,1];
+ } forEach _magazines;
+ };
+
+ //Backpacks
+ if(count _backpacks > 0)then{
+ {
+ diag_log format["Epoch: Server_CreateObject: %1 Backpack Spawn",_x];
+ _wepHolder addBackPackCargoGlobal [_x,1];
+ }forEach _backpacks;
+ };
-if (_clearCargo) then {
- clearWeaponCargoGlobal _obj;
- clearItemCargoGlobal _obj;
- clearMagazineCargoGlobal _obj;
- clearBackpackCargoGlobal _obj;
};
-if (_driverType != "" || _gunnerType != "" ||_commanderType != "") then {
- _grp = createGroup RESISTANCE;
+if(count _vehicles > 0)then{
+ {
+ diag_log format["Epoch: Server_CreateObject: %1 Vehicle Spawn",_x];
+ //Need to create slot to createVehicle a persistent Epoch vehicle.
+ //_obj = [_x select 0, _x select 1, random 360, true, (EPOCH_storedVehicleCount + 1), _player, "CAN_COLLIDE", !_clearCargo, false] call EPOCH_spawn_vehicle;
+
+ _obj = createVehicle[(_x select 0), (_x select 1), [], 15, "CAN_COLLIDE"];
+
+ _obj allowdamage false;
+
+ if (_driverType != "" || _gunnerType != "" || _commanderType != "") then {
+ _grp = createGroup RESISTANCE;
+ };
+
+ if (_driverType != "") then {
+ _driver = _grp createUnit[_driverType, position _obj, [], 1, "CAN_COLLIDE"];
+ _driver assignAsDriver _obj;
+ _driver moveInDriver _obj;
+ //if (_doOwner) then {_driver setOwner (owner _player)};
+ };
+
+ if (_gunnerType != "") then {
+ _gunner = _grp createUnit[_gunnerType, position _obj, [], 1, "CAN_COLLIDE"];
+ _gunner assignAsGunner _obj;
+ _gunner moveInGunner _obj;
+ //if (_doOwner) then {_gunner setOwner (owner _player)};
+ };
+
+ if (_commanderType != "") then {
+ _commander = _grp createUnit[_commanderType, position _obj, [], 1, "CAN_COLLIDE"];
+ _commander assignAsCommander _obj;
+ _commander moveInCommander _obj;
+ //if (_doOwner) then {_commander setOwner (owner _player)};
+ };
+
+ if (_crewType != "") then {
+ _crew = _grp createUnit[_crewType, position _obj, [], 1, "CAN_COLLIDE"];
+ _crew assignAsCargo _obj;
+ _crew moveInCargo _obj;
+ //if (_doOwner) then {_crew setOwner (owner _player)};
+ };
+
+ _obj allowdamage true;
+
+ //Assume is 'crash site' vehicle.
+ if(_doDamage)then{
+ _obj setdamage 1;
+ removeFromRemainsCollector [_obj];
+ _obj call EPOCH_server_setVToken;
+ //WIP - Wait for player to turn up then add back to remains collector. May be less performant that just leaving it for a server restart ?
+ [_obj] spawn {
+ _monitorObj = true;
+ _obj = _this select 0;
+ while{_monitorObj}do{
+ if(count nearestObjects [_obj,["MAN"],28] > 0)then{
+ _monitorObj = false;
+ };
+ uiSleep 30;
+ };
+ while!(_monitorObj)do{
+ if(count nearestObjects [_obj,["MAN"],56] < 1)then{
+ _monitorObj = true;
+ addToRemainsCollector [_obj];
+ };
+ uiSleep 30;
+ };
+ terminate _thisScript;//Testing
+ };
+ };
+
+ }forEach _vehicles;
};
-if (_driverType != "") then {
- _driver = _grp createUnit[_driverType, position _obj, [], 1, "CAN_COLLIDE"];
- _driver assignAsDriver _obj;
- _driver moveInDriver _obj;
- //if (_doOwner) then {_driver setOwner (owner _player)};
-};
-if (_gunnerType != "") then {
- _gunner = _grp createUnit[_gunnerType, position _obj, [], 1, "CAN_COLLIDE"];
- _gunner assignAsGunner _obj;
- _gunner moveInGunner _obj;
- //if (_doOwner) then {_gunner setOwner (owner _player)};
-};
-
-if (_commanderType != "") then {
- _commander = _grp createUnit[_commanderType, position _obj, [], 1, "CAN_COLLIDE"];
- _commander assignAsCommander _obj;
- _commander moveInCommander _obj;
- //if (_doOwner) then {_commander setOwner (owner _player)};
-};
-
-if (_crewType != "") then {
- _crew = _grp createUnit[_crewType, position _obj, [], 1, "CAN_COLLIDE"];
- _crew assignAsCargo _obj;
- _crew moveInCargo _obj;
- //if (_doOwner) then {_crew setOwner (owner _player)};
-};
-_obj allowdamage true;
-diag_log format["Epoch: Spawned Object %1(%5) for %3(%4) at %2",_objType,_pos,name _player,owner _player,owner _obj];
diff --git a/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_missionComms.sqf b/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_missionComms.sqf
new file mode 100644
index 00000000..f4c9cecd
--- /dev/null
+++ b/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_missionComms.sqf
@@ -0,0 +1,30 @@
+/*
+ Author: Andrew Gregory - EpochMod.com
+
+ Contributors:
+
+ Description:
+ Init and pass vars to mission / task control fsm. fsm will dispose if not being used, this function will restart it as required.
+
+ Licence:
+ Arma Public License Share Alike (APL-SA) - https://www.bistudio.com/community/licenses/arma-public-license-share-alike
+
+ Github:
+ https://github.com/EpochModTeam/Epoch/tree/master/Sources/epoch_server/compile/epoch_missions/EPOCH_Server_missionComms.sqf
+*/
+params["_plyr","_token",["_cmd",-1],["_tmpVar", nil],{"_missionIndex",-1],["_item",objNull],["_pos"],[]];
+
+if !([_plyr, _token] call EPOCH_server_getPToken) exitWith{};
+
+if(isNil "missionControlHandle")then{
+missionControlHandle = [] execFSM "x\addons\a3_epoch_server\system\mission_control.fsm";
+diag_log format ["MISSION CONTROL INIT: %1",missionControlHandle];
+
+ //Catch first instant if fsm slow to start - may not be necessary.
+ ["_clientCmd",[_plyr, _cmd, _missionIndex,_item,_pos]] spawn{
+ waitUntil {!(isNil "missionControlHandle")};
+ missionControlHandle setFSMVariable [_this select 0, _this select 1];
+ };
+}else{
+missionControlHandle setFSMVariable ["_clientCmd",[_plyr, _cmd, _missionIndex,_item,_pos]];
+};
diff --git a/Sources/epoch_server/compile/epoch_player/EPOCH_server_loadPlayer.sqf b/Sources/epoch_server/compile/epoch_player/EPOCH_server_loadPlayer.sqf
index 8e65f74b..da1d4fb7 100644
--- a/Sources/epoch_server/compile/epoch_player/EPOCH_server_loadPlayer.sqf
+++ b/Sources/epoch_server/compile/epoch_player/EPOCH_server_loadPlayer.sqf
@@ -320,7 +320,8 @@ if (_this isEqualType []) then {
};
if !(_server_vars isEqualTo[]) then{
- _newPlyr setVariable["SERVER_VARS", _server_vars];
+ _newPlyr setVariable["SERVER_VARS", _server_vars, true];
+ //Used for mission tracking. TODO: collect directly as required rather than broadcast.
};
if (!_canBeRevived) then {
diff --git a/Sources/epoch_server/config.cpp b/Sources/epoch_server/config.cpp
index 423ee82f..21b83e25 100644
--- a/Sources/epoch_server/config.cpp
+++ b/Sources/epoch_server/config.cpp
@@ -122,12 +122,14 @@ class CfgServerFunctions
class server_teleportPlayer {};
class returnConfig {};
class serverCommand {};
+ class server_createMarker {};
};
class epoch_missions {
class Server_createObject {};
class server_airDropCrate {};
class server_fillContainer {};
class Server_createAirDrop {};
+ class Server_missionComms{};
};
class epoch_antagonists {
class server_triggerEvent {};
diff --git a/Sources/epoch_server/system/mission_control.fsm b/Sources/epoch_server/system/mission_control.fsm
new file mode 100644
index 00000000..7289473e
--- /dev/null
+++ b/Sources/epoch_server/system/mission_control.fsm
@@ -0,0 +1,315 @@
+/*%FSM*/
+/*%FSM*/
+/*
+item0[] = {"mission_control",0,4346,-225.000000,-400.000000,-125.000000,-350.000000,0.000000,"mission control"};
+item1[] = {"_",8,218,-225.000000,-300.000000,-125.000000,-250.000000,0.000000,""};
+item2[] = {"start",2,250,-225.000000,-225.000000,-125.000000,-175.000000,0.000000,"start"};
+item3[] = {"wait",4,218,-100.000000,-225.000000,0.000000,-175.000000,0.000000,"wait"};
+item4[] = {"commands",2,250,-100.000000,-100.000000,0.000000,-50.000000,0.000000,"commands"};
+item5[] = {"continue",4,218,-225.000000,-100.000000,-125.000000,-50.000000,10.000000,"continue"};
+item6[] = {"end",4,218,-350.000000,25.000000,-250.000000,75.000000,5.000000,"end"};
+item7[] = {"___2",4,218,25.000000,-225.000000,125.000000,-175.000000,0.000000,"0"};
+item8[] = {"end",1,250,-350.000000,-100.000000,-250.000000,-50.000000,0.000000,"end"};
+item9[] = {"add_player",2,250,150.000000,-225.000000,250.000000,-175.000000,0.000000,"add player"};
+item10[] = {"clean_up",2,250,-225.000000,25.000000,-125.000000,75.000000,0.000000,"clean up"};
+item11[] = {"__",4,218,25.000000,-150.000000,125.000000,-100.000000,0.000000,"1"};
+item12[] = {"remove_player",2,250,150.000000,-150.000000,250.000000,-100.000000,0.000000,"remove player"};
+item13[] = {"",7,210,296.000000,46.000000,304.000000,54.000000,0.000000,""};
+item14[] = {"",7,210,296.000000,-204.000000,304.000000,-196.000000,0.000000,""};
+item15[] = {"",7,210,296.000000,-129.000000,304.000000,-120.999992,0.000000,""};
+item16[] = {"",7,210,296.000000,46.000000,304.000000,54.000000,0.000000,""};
+item17[] = {"_",8,218,150.000000,25.000000,250.000000,75.000000,0.000000,""};
+item18[] = {"check_players",2,250,150.000000,125.000000,250.000000,175.000000,0.000000,"check players"};
+item19[] = {"_",8,218,25.000000,25.000000,125.000000,75.000000,0.000000,""};
+item20[] = {"_",8,218,-100.000000,25.000000,0.000000,75.000000,0.000000,""};
+item21[] = {"client_command_",2,250,25.000000,125.000000,125.000000,175.000000,0.000000,"client" \n "command / messages"};
+item22[] = {"___1",4,218,25.000000,-81.163773,124.999992,-31.163784,0.000000,"2"};
+item23[] = {"hold_var",2,250,149.999969,-81.163773,249.999969,-31.163784,0.000000,"hold var"};
+link0[] = {0,1};
+link1[] = {1,2};
+link2[] = {2,3};
+link3[] = {3,4};
+link4[] = {4,7};
+link5[] = {4,11};
+link6[] = {4,22};
+link7[] = {5,2};
+link8[] = {6,8};
+link9[] = {7,9};
+link10[] = {9,14};
+link11[] = {10,5};
+link12[] = {10,6};
+link13[] = {11,12};
+link14[] = {12,15};
+link15[] = {14,15};
+link16[] = {15,16};
+link17[] = {16,17};
+link18[] = {17,18};
+link19[] = {18,19};
+link20[] = {19,21};
+link21[] = {20,10};
+link22[] = {21,20};
+link23[] = {22,23};
+link24[] = {23,15};
+globals[] = {0.000000,0,0,0,0,640,480,1,319,6316128,1,-356.228333,361.065094,273.349731,-454.917542,719,730,1};
+window[] = {2,-1,-1,-32000,-32000,733,208,1233,208,3,737};
+*//*%FSM*/
+class FSM
+{
+ fsmName = "mission control server";
+ class States
+ {
+ /*%FSM*/
+ class mission_control
+ {
+ name = "mission_control";
+ init = /*%FSM*/"_clientCmd = [];" \n
+ "_plyrArr = [];" \n
+ "" \n
+ "//Vars" \n
+ "_plyArrTmp = [];" \n
+ "" \n
+ "//Held Var" \n
+ "_tmpVar = [];"/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="start";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class start
+ {
+ name = "start";
+ init = /*%FSM*/""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class wait
+ {
+ priority = 0.000000;
+ to="commands";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"count _clientCmd > 0"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class commands
+ {
+ name = "commands";
+ init = /*%FSM*/""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class __
+ {
+ priority = 0.000000;
+ to="remove_player";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"_clientCmd select 1 == 1"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class ___1
+ {
+ priority = 0.000000;
+ to="hold_var";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"_clientCmd select 1 == 2"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class ___2
+ {
+ priority = 0.000000;
+ to="add_player";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"_clientCmd select 1 == 0"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class end
+ {
+ name = "end";
+ init = /*%FSM*/""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class add_player
+ {
+ name = "add_player";
+ init = /*%FSM*/"_plyrArr pushBack [_clientCmd select 0,_clientCmd select 2, _clientCmd select 3];"/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="check_players";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class clean_up
+ {
+ name = "clean_up";
+ init = /*%FSM*/"_clientCmd = [];"/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class continue
+ {
+ priority = 10.000000;
+ to="start";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"count _plyrArr > 0"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class end
+ {
+ priority = 5.000000;
+ to="end";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"count _plyrArr < 1"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class remove_player
+ {
+ name = "remove_player";
+ init = /*%FSM*/"_plyrArrTmp = +_plyrArr;" \n
+ "_plyrArr = [];" \n
+ "{" \n
+ " if!(_x select 0 == _clientCmd select 0)then{" \n
+ " _plyrArr pushBack _x;" \n
+ " };" \n
+ "}forEach _plyrArrTmp;" \n
+ "_plyrArrTmp = [];" \n
+ ""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="check_players";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class check_players
+ {
+ name = "check_players";
+ init = /*%FSM*/""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="client_command_";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class client_command_
+ {
+ name = "client_command_";
+ init = /*%FSM*/""/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="clean_up";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ /*%FSM*/
+ class hold_var
+ {
+ name = "hold_var";
+ init = /*%FSM*/"if( in _plyrArr)then{" \n
+ "" \n
+ "};"/*%FSM*/;
+ precondition = /*%FSM*/""/*%FSM*/;
+ class Links
+ {
+ /*%FSM*/
+ class _
+ {
+ priority = 0.000000;
+ to="check_players";
+ precondition = /*%FSM*/""/*%FSM*/;
+ condition=/*%FSM*/"true"/*%FSM*/;
+ action=/*%FSM*/""/*%FSM*/;
+ };
+ /*%FSM*/
+ };
+ };
+ /*%FSM*/
+ };
+ initState="mission_control";
+ finalStates[] =
+ {
+ "end",
+ };
+};
+/*%FSM*/
\ No newline at end of file