diff --git a/mission/config/functions.hpp b/mission/config/functions.hpp
index de89d8a2..3d00a5db 100644
--- a/mission/config/functions.hpp
+++ b/mission/config/functions.hpp
@@ -222,6 +222,8 @@ class CfgFunctions
file = "functions\systems\dac_cong";
class daccong_respawns_delete_all {};
class capture_player {};
+ class ctf_handle_flag_height_change {};
+ class ctf_broadcast_notify_immediate {};
}
//Gameplay director, responsible for main game progression and flow.
diff --git a/mission/config/notifications.hpp b/mission/config/notifications.hpp
index b4c1e784..09ff96c5 100644
--- a/mission/config/notifications.hpp
+++ b/mission/config/notifications.hpp
@@ -379,7 +379,7 @@ class CfgNotifications
class DacCongCapturedFlag
{
- title = "Protect The Flag!";
+ title = "Flag Captured!";
description = "You are failure! Dac Cong have captured the flag!";
priority = 6;
color[] = {1,0,0,1};
@@ -388,7 +388,7 @@ class CfgNotifications
class BlueforRaisingFlag
{
- title = "Raise The Flag!";
+ title = "Raising Flag!";
description = "Bluefor are raising the flag.";
priority = 6;
color[] = {0.2,0.3,1,1};
@@ -397,7 +397,7 @@ class CfgNotifications
class BlueforRaisedFlag
{
- title = "Raise The Flag!";
+ title = "Raised Flag!";
description = "Bluefor have raised the flag!";
priority = 6;
color[] = {0.2,0.3,1,1};
diff --git a/mission/config/subconfigs/tasks/defend/tasks.hpp b/mission/config/subconfigs/tasks/defend/tasks.hpp
index 0999074f..edb6f123 100644
--- a/mission/config/subconfigs/tasks/defend/tasks.hpp
+++ b/mission/config/subconfigs/tasks/defend/tasks.hpp
@@ -28,13 +28,13 @@ class defend_counterattack : task
class defend_zone
{
taskname = "Hold the Zone";
- taskdesc = "Hold the zone for 30 minutes, or until hostiles are eliminated.";
+ taskdesc = "Defend the Zone from enemy counterattack.";
};
class defend_fob
{
taskname = "Defend the FOB";
- taskdesc = "Defend the FOB from counterattack for 30 minutes, or hostile forces are eliminated.";
+ taskdesc = "Defend the FOB from enemy counterattack.";
};
class defend_flag
diff --git a/mission/config/subconfigs/tasks/primary/tasks.hpp b/mission/config/subconfigs/tasks/primary/tasks.hpp
index 05d0d529..3206ce61 100644
--- a/mission/config/subconfigs/tasks/primary/tasks.hpp
+++ b/mission/config/subconfigs/tasks/primary/tasks.hpp
@@ -41,6 +41,18 @@ class capture_zone : task
taskdesc = "Build a respawn so we can reinforce the Forward Operating Base.";
};
+ class build_landing_pad
+ {
+ taskname = "Build FOB Landing Pad";
+ taskdesc = "Build a landing pad so helos can land near the FOB. Emphasis on near!";
+ };
+
+ class build_rearm_repair_refuel
+ {
+ taskname = "Build FOB Rearm/Repair/Refuel Station";
+ taskdesc = "Build a Vehicle Rearm/Repair/Refuel location at the FOB. Possibly next to the helipad.";
+ };
+
class build_flag
{
taskname = "Build FOB Flag";
diff --git a/mission/functions/systems/actions/fn_action_lower_flag.sqf b/mission/functions/systems/actions/fn_action_lower_flag.sqf
index 62660647..f089352b 100644
--- a/mission/functions/systems/actions/fn_action_lower_flag.sqf
+++ b/mission/functions/systems/actions/fn_action_lower_flag.sqf
@@ -4,24 +4,42 @@
Public: No
Description:
- Dac Cong players can approach a mission critical (player built) flag in a base
- and then lower it, causing a mission objective to fail.
+ Dac Cong players can approach a mission critical (player built)
+ flag in a base and then lower it, causing a mission objective
+ to fail.
+
+ WARNING: This is attached to **PLAYERS**, running in **player** locality.
Parameter(s): none
Returns:
Example(s):
+ call vn_mf_fnc_action_lower_flag;
*/
-private _actionText = format ["%1", "Lower Enemy Flag"];
+private _actionText = format ["%1", "Lower Flag"];
private _actionIdleIcon = "custom\holdactions\holdAction_interact_ca.paa";
private _actionProgressIcon = "custom\holdactions\holdAction_danger_ca.paa";
-private _isOpfor = "side player == east";
+private _isOpfor = "side player isEqualTo east";
private _isInRangeOf = "player distance cursorObject < 5";
-private _isValidObjectType = "typeOf cursorObject in ['vn_flag_usa', 'vn_flag_aus', 'vn_flag_arvn', 'vn_flag_nz']";
-private _isObjectiveFlag = "cursorObject getVariable ['canLower', false]";
+private _validFlagsArr = "['vn_flag_usa', 'vn_flag_aus', 'vn_flag_arvn', 'vn_flag_nz']";
+private _isValidObjectType = format [
+ "typeOf cursorObject in %1",
+ _validFlagsArr
+];
+
+/*
+vn_mf_bn_dc_target_flag is publicVariable'd when the flag is built
+within the fn_task_pri_capture code
+
+we need to do this otherwise dac cong could be lowering the wrong flag.
+need to use a publicVar, else we'd need to remoteExec constantly as part
+of condition to show... but mike force hold actions are attached to the PLAYER
+which means constantly running remoteExec's whenever a player is looking at ANYTHING.
+*/
+private _isObjectiveFlag = "!(isNil 'vn_mf_bn_dc_target_flag') && (cursorObject isEqualTo vn_mf_bn_dc_target_flag)";
private _conditionToShow = format [
"(%1 && %2 && %3 && %4)",
@@ -34,23 +52,27 @@ private _conditionToShow = format [
private _conditionToProgress = "true";
private _codeOnStart = {
- allPlayers apply {["DacCongCapturingFlag", []] remoteExec ["para_c_fnc_show_notification", _x]};
+ params ["_target", "_caller", "_actionId", "_arguments"];
+ ["DacCongCapturingFlag"] remoteExec ["vn_mf_fnc_ctf_broadcast_notify_immediate", 2];
};
private _codeOnTick = {
params ["_target", "_caller", "_actionId", "_arguments", "_progress", "_maxProgress"];
- private _startingFlagHeight = cursorObject getVariable ["currentHeight", flagAnimationPhase cursorObject];
- private _newHeight = _startingFlagHeight * (1 - (_progress / _maxProgress));
- cursorObject setFlagAnimationPhase _newHeight;
+ [vn_mf_bn_dc_target_flag, _progress, _maxProgress, -1] remoteExec ["vn_mf_fnc_ctf_handle_flag_height_change", 2];
};
+/*
private _codeOnComplete = {
- [cursorObject] remoteExec ["deleteVehicle", 2];
- allPlayers apply {["DacCongCapturedFlag", []] remoteExec ["para_c_fnc_show_notification", _x]};
+ params ["_target", "_caller", "_actionId", "_arguments"];
};
+
private _codeOnInterrupted = {
- cursorObject setVariable ["currentHeight", flagAnimationPhase cursorObject];
+ params ["_target", "_caller", "_actionId", "_arguments"];
};
+*/
+
+private _codeOnComplete = {};
+private _codeOnInterrupted = {};
private _extraArgsArr = [];
-private _actionDurationSeconds = 20;
+private _actionDurationSeconds = 10;
private _actionPriority = 100;
private _actionRemoveOnComplete = false;
private _showWhenUncon = false;
diff --git a/mission/functions/systems/actions/fn_action_reraise_flag.sqf b/mission/functions/systems/actions/fn_action_reraise_flag.sqf
index dbf7d69e..eb215185 100644
--- a/mission/functions/systems/actions/fn_action_reraise_flag.sqf
+++ b/mission/functions/systems/actions/fn_action_reraise_flag.sqf
@@ -4,54 +4,68 @@
Public: No
Description:
- Dac Cong have lowered a mission critical flag.
- Bluefor need to raise it to 100% again.
+ Dac Cong players have lowered a mission critical (player built)
+ flag in a base. Bluefor need to raise it to 100% again.
+
+ WARNING: This is attached to **PLAYERS**, running in **player** locality.
Parameter(s): none
Returns:
Example(s):
- call vn_mf_fnc_action_capture_player;
+ call vn_mf_fnc_action_reraise_flag;
*/
-private _actionText = format ["%1", "Re-Raise The Flag"];
+private _actionText = format ["%1", "Raise Flag"];
private _actionIdleIcon = "custom\holdactions\holdAction_interact_ca.paa";
private _actionProgressIcon = "custom\holdactions\holdAction_interact_ca.paa";
-private _isNotOpfor = "side player == west";
+private _isNotOpfor = "(side player) isEqualTo west";
private _isInRangeOf = "player distance cursorObject < 5";
-private _isValidObjectType = "typeOf cursorObject in ['vn_flag_usa', 'vn_flag_aus', 'vn_flag_arvn', 'vn_flag_nz']";
-private _isObjectiveFlag = "(flagAnimationPhase cursorObject) != 1";
+private _validFlagsArr = "['vn_flag_usa', 'vn_flag_aus', 'vn_flag_arvn', 'vn_flag_nz']";
+private _isValidObjectType = format [
+ "typeOf cursorObject in %1",
+ _validFlagsArr
+];
+private _isObjectiveFlag = "!(isNil 'vn_mf_bn_dc_target_flag') && (cursorObject isEqualTo vn_mf_bn_dc_target_flag)";
+private _isFlagLowered = "((flagAnimationPhase cursorObject) isNotEqualTo 1)";
+// bluefor can raise the flag only if it has been lowered
private _conditionToShow = format [
- "(%1 && %2 && %3 && %4)",
+ "(%1 && %2 && %3 && %4 && %5)",
_isNotOpfor,
_isInRangeOf,
_isValidObjectType,
- _isObjectiveFlag
+ _isObjectiveFlag,
+ _isFlagLowered
];
private _conditionToProgress = "true";
private _codeOnStart = {
- allPlayers apply {["BlueforRaisingFlag", []] remoteExec ["para_c_fnc_show_notification", _x]};
+ params ["_target", "_caller", "_actionId", "_arguments"];
+ ["BlueforRaisingFlag"] remoteExec ["vn_mf_fnc_ctf_broadcast_notify_immediate", 2];
};
private _codeOnTick = {
params ["_target", "_caller", "_actionId", "_arguments", "_progress", "_maxProgress"];
- private _startingFlagHeight = cursorObject getVariable ["currentHeight", flagAnimationPhase cursorObject];
- private _newHeight = _startingFlagHeight + ((1 - _startingFlagHeight) * (_progress / _maxProgress));
- cursorObject setFlagAnimationPhase _newHeight;
+ [vn_mf_bn_dc_target_flag, _progress, _maxProgress, 1] remoteExec ["vn_mf_fnc_ctf_handle_flag_height_change", 2];
};
+
+/*
private _codeOnComplete = {
- cursorObject setVariable ["currentHeight", flagAnimationPhase cursorObject];
- allPlayers apply {["BlueforRaisedFlag", []] remoteExec ["para_c_fnc_show_notification", _x]};
+ params ["_target", "_caller", "_actionId", "_arguments"];
};
+
private _codeOnInterrupted = {
- cursorObject setVariable ["currentHeight", flagAnimationPhase cursorObject];
+ params ["_target", "_caller", "_actionId", "_arguments"];
};
+*/
+
+private _codeOnComplete = {};
+private _codeOnInterrupted = {};
private _extraArgsArr = [flagAnimationPhase cursorObject];
-private _actionDurationSeconds = 20;
+private _actionDurationSeconds = 10;
private _actionPriority = 100;
private _actionRemoveOnComplete = false;
private _showWhenUncon = false;
diff --git a/mission/functions/systems/dac_cong/fn_ctf_broadcast_notify_immediate.sqf b/mission/functions/systems/dac_cong/fn_ctf_broadcast_notify_immediate.sqf
new file mode 100644
index 00000000..8403ccf6
--- /dev/null
+++ b/mission/functions/systems/dac_cong/fn_ctf_broadcast_notify_immediate.sqf
@@ -0,0 +1,62 @@
+/*
+ File: fn_ctf_broadcast_notify_immediate.sqf
+ Author: "DJ" Dijksterhuis
+ Public: No
+
+ Description:
+ Display a notification for all players via a remoteExec callback.
+
+ Used to perform a global notification broadcast out to all players
+ from a specific player locality.
+
+ player -> server -> all players
+
+ Means the specific player client isn't sending out remoteExec instructions to
+ all connected players, hopefully mitigating some desync/latency issues and enabling
+ use to implement a CfgRemoteExec later on.
+
+ TODO: Refactor this out to core/helpers?
+ TODO: Rename? Should be like fn_broadcast_global_notification.sqf
+
+ Parameter(s):
+ - _notificationClass -- class name of the notification to show [STRING]
+ - _args -- arguments for string replacement in notification description text [ARRAY]
+
+ Returns: nothing
+
+ Example(s):
+ // from player locality
+ // remote execs this script on the server
+ // which then remoteExecs a notification for all clients (and server, see note below)
+ ["FireInTheHole"] remoteExec ["vn_mf_fnc_ctf_broadcast_notify_immediate", 2];
+
+ // from server locality
+ ["FireInTheHole"] call vn_mf_fnc_ctf_broadcast_notify_immediate;
+*/
+
+params [
+ "_notificationClass",
+ ["_args", []]
+];
+
+if (!isServer) exitWith {
+ ["ERROR", "Function should only run on server!"] call para_g_fnc_log;
+};
+
+if (_notificationClass isEqualTo "") exitWith {
+ ["ERROR", format ["Function passed an empty string for _notificationClass! value=%1", _notificationClass]] call para_g_fnc_log;
+};
+
+if !(_notificationClass isEqualType "testvalue") exitWith {
+ ["ERROR", format ["Function passed non-string for _notificationClass! value=%1", _notificationClass]] call para_g_fnc_log;
+};
+
+if !(_args isEqualType []) exitWith {
+ ["ERROR", format ["Function passed non-array for _args! value=%1", _args]] call para_g_fnc_log;
+};
+
+// This *should* be -2 --> but then notifications don't work on player hosted (local development)
+// cba to optimise this right now. it'll be fine for the moment.
+[_notificationClass, _args] remoteExec ["para_c_fnc_show_notification", 0];
+
+nil;
\ No newline at end of file
diff --git a/mission/functions/systems/dac_cong/fn_ctf_handle_flag_height_change.sqf b/mission/functions/systems/dac_cong/fn_ctf_handle_flag_height_change.sqf
new file mode 100644
index 00000000..e3292b86
--- /dev/null
+++ b/mission/functions/systems/dac_cong/fn_ctf_handle_flag_height_change.sqf
@@ -0,0 +1,74 @@
+/*
+ File: fn_ctf_handle_flag_height_change.sqf
+ Author: "DJ" Dijksterhuis
+ Public: No
+
+ Description:
+ Handle lowering/raising the flag server side.
+
+ Parameter(s):
+ _target -- flag we'll be raising / lowering
+ _progress -- how many steps
+ _maxProgress -- total steps
+ _direction -- -1/+1 for lower/raise
+
+ Returns: nothing
+
+ Example(s):
+ // lower
+ [_target, 4, 24, -1] call vn_mf_fnc_ctf_handle_flag_height_change;
+
+ // raise
+ [_target, 4, 24, 1] call vn_mf_fnc_ctf_handle_flag_height_change;
+*/
+
+params ["_target", "_progress", "_maxProgress", "_direction"];
+
+private _tickRate = 3;
+
+// only change things every 3 holdAction ticks to ensure we're not spamming clients
+// with a massive amount of changes (always a total of 24 ticks)
+if ((_progress mod _tickRate ) isEqualTo 0) then {
+
+ private _startingFlagHeight = flagAnimationPhase _target;
+ private _newHeight = _startingFlagHeight;
+
+ // -1 ---> dac cong lowering the flag
+ // +1 ---> bluefor raising the flag
+
+ if (_direction isEqualTo -1) then {
+
+ _newHeight = _startingFlagHeight - (_tickRate / _maxProgress);
+
+ if (_newHeight <= 0) exitWith {
+
+ // global command, no need to remoteExec
+ deleteVehicle _target;
+
+ // broadcast notification out to all players
+ ["DacCongCapturedFlag"] call vn_mf_fnc_ctf_broadcast_notify_immediate;
+
+ // clear the JIP queue for flag height.
+ remoteExec ["", "JIP_DACCONG_CTF_FLAG_HEIGHT"];
+ };
+
+ } else {
+
+ _newHeight = _startingFlagHeight + (_tickRate / _maxProgress);
+
+ if (_newHeight >= 1) exitWith {
+
+ // broadcast the the new flag height globally with JIP ID (includes server)
+ [_target, 1] remoteExec ["setFlagAnimationPhase", 0, "JIP_DACCONG_CTF_FLAG_HEIGHT"];
+
+ // broadcast notification out to all players
+ ["BlueforRaisedFlag"] call vn_mf_fnc_ctf_broadcast_notify_immediate;
+
+ };
+ };
+ // set the new height globally via JIP queue so new players also see the flag at the right height
+ // includes changing it on the server
+ [_target, _newHeight] remoteExec ["setFlagAnimationPhase", 0, "JIP_DACCONG_CTF_FLAG_HEIGHT"];
+};
+
+nil;
\ No newline at end of file
diff --git a/mission/functions/tasks/defend/fn_task_defend_counterattack.sqf b/mission/functions/tasks/defend/fn_task_defend_counterattack.sqf
index 14328e84..101b9ae3 100644
--- a/mission/functions/tasks/defend/fn_task_defend_counterattack.sqf
+++ b/mission/functions/tasks/defend/fn_task_defend_counterattack.sqf
@@ -25,7 +25,8 @@ params ["_taskDataStore"];
/*
Constants
*/
-_taskDataStore setVariable ["holdDuration", 30 * 60];
+_taskDataStore setVariable ["holdDuration", 40 * 60];
+_taskDataStore setVariable ["flagTimerReduction", 10 * 60];
_taskDataStore setVariable ["failureDuration", 5 * 60];
// get the counterattack time remaining for this specific zone
@@ -45,7 +46,11 @@ _taskDataStore setVariable ["fnc_update_hold_time", {
// update hold duration. if not previously set the counterattack
// will use the default holdDuration value defined above.
if (_holdTimeRemaining >= 0) then {
- diag_log "DEBUG: Updating current zone's counterattack time remaining from profile DB.";
+ diag_log format [
+ "DEBUG: Updating current zone's counterattack time remaining from profile DB: timeS=%1 timeM=%2",
+ _holdTimeRemaining,
+ _holdTimeRemaining / 60
+ ];
_tds setVariable ["holdDuration", _holdTimeRemaining];
};
}];
@@ -84,11 +89,6 @@ _taskDataStore setVariable ["INIT", {
private _marker = _tds getVariable "taskMarker";
private _markerPos = getMarkerPos _marker;
- /*
- // present in SGD Mike Force, but not used anywhere.
- private _hqs = (localNamespace getVariable ["sites_hq", []]) inAreaArray _marker;
- */
-
private _prepTime = _tds getVariable ["prepTime", 180];
_marker setMarkerColor "ColorYellow";
@@ -113,6 +113,8 @@ _taskDataStore setVariable ["INIT", {
private _candidate_bases_to_attack = para_g_bases inAreaArray _base_search_area apply {
[_x getVariable "para_g_current_supplies", _x]
};
+
+ // base with most supplies is likely the main fob
_candidate_bases_to_attack sort false;
// candidate FOBs exist
@@ -136,7 +138,7 @@ _taskDataStore setVariable ["INIT", {
_tds setVariable ["fob_exists", true];
- // nearest objects might be buggy
+ // candidate flags can only exist within the established fob
private _possibleFlags = nearestObjects [
[_attackPos select 0, _attackPos select 1],
@@ -144,13 +146,38 @@ _taskDataStore setVariable ["INIT", {
para_g_max_base_radius
];
- if (count _possibleFlags > 0) then {
- private _flag = _possibleFlags select 0;
- _tds setVariable ["flag", _flag];
+ // need to check if they are a paradigm built object!
+ private _paraBuiltFlags = _possibleFlags select {not isNull (_x getVariable ["para_g_building", objNull])};
+
+ if (count _paraBuiltFlags > 0) then {
+
+ _taskDataStore setVariable ["flag_exists", true];
+
+ /*
+ shorten the counterattack duration by 15 minutes
+ if this is post server restart this value should get overwritten when
+ we run `_taskDataStore getVariable "fnc_update_hold_time")` below
+ */
+
+ private _holdDuration = _taskDataStore getVariable "holdDuration";
+ private _timerReduction = _taskDataStore getVariable "flagTimerReduction";
+
+ _taskDataStore setVariable ["holdDuration", _holdDuration - _timerReduction];
+
+ private _flagsWithDistance = _paraBuiltFlags apply {
+ [_x distance2D _attackPos, _x]
+ };
+
+ _flagsWithDistance sort true;
+
+ private _flag_to_attack = (_flagsWithDistance # 0 ) # 1;
+
+ _tds setVariable ["flag", _flag_to_attack];
_tds setVariable ["flag_exists", true];
+
diag_log format [
"Counterattack: Suitable flag discovered: %1",
- getPos _flag
+ getPos _flag_to_attack
];
};
@@ -243,36 +270,51 @@ _taskDataStore setVariable ["prepare_zone", {
_tds setVariable ["lastCheck", serverTime];
[_tds getVariable "holdDuration"] call (_tds getVariable "_fnc_notify_attack_remaining");
+
+ // we'll always have one of the "defend_fob" or "defend_zone" tasks active
+ // both need a red circle around the area that needs defending as players
+ // must hold that area to complete the task.
[_tds] call (_tds getVariable "_fnc_create_circle_area");
-
- if ((_tds getVariable ["flag_exists", false]) && (_tds getVariable ["fob_exists", false])) exitWith {
-
- // used in the players action to check if players are looking at the right flag.
- // we set it now so the flag cannot be lowered during the prepare counterattack phase
- // but can be lowered during the upcoming defned thr flag phase
- (_tds getVariable "flag") setVariable ["canLower", true];
- [
- "SUCCEEDED",
- [
- ["defend_fob", _tds getVariable "attackPos"],
- ["defend_flag", getPos (_tds getVariable "flag")]
- ]
- ] call _fnc_finishSubtask;
- };
- if (_tds getVariable ["fob_exists", false]) exitWith {
- [
- "SUCCEEDED",
- [["defend_fob", _tds getVariable "attackPos"]]
- ] call _fnc_finishSubtask;
+ // set up the next batch of tasks.
+ // doing a series of switch-case pushback statements is tidier / more compact
+ private _next_tasks = [];
+
+ private _fob_exists = _tds getVariable ["fob_exists", false];
+ private _flag_exists = _tds getVariable ["flag_exists", false];
+
+ switch (true) do {
+ // NOTE -- flag must be built within an established fob
+ case (_fob_exists && _flag_exists) : {
+ /*
+ Set the publicVariable that allows opfor/bluefor to respectively
+ lower/raise the flag as part of the hold action.
+
+ do this as late as possible to ensure opfor cannot lower the flag
+ before the counterattack timer actually starts.
+
+ NOTE: public variables are bad. but we we need to pass a variable
+ out of the task's scope and locality so there is no other option.
+
+ this variable broadcast only happens once -- when we are switching from
+ prepare to the actual defend tasks. so it should not severly impact network
+ performance as we do not frequently rebroadcast.
+ */
+ vn_mf_bn_dc_target_flag = _tds getVariable "flag";
+ publicVariable "vn_mf_bn_dc_target_flag";
+
+ _next_tasks pushBack ["defend_flag", getPos (_tds getVariable "flag")];
+ _next_tasks pushBack ["defend_fob", _tds getVariable "attackPos"];
+ };
+ case (_fob_exists) : {
+ _next_tasks pushBack ["defend_fob", _tds getVariable "attackPos"];
+ };
+ default {
+ _next_tasks pushBack ["defend_zone", _tds getVariable "attackPos"];
+ };
};
- // no other options left
- // chuck some AI in the zone and hope they bump into players
- [
- "SUCCEEDED",
- [["defend_zone", _tds getVariable "attackPos"]]
- ] call _fnc_finishSubtask;
+ ["SUCCEEDED", _next_tasks] call _fnc_finishSubtask;
}];
/*
@@ -350,6 +392,21 @@ _taskDataStore setVariable ["_fnc_check_ai_failure_condition", {
/*
+remove all the network'd variables and JIP queue ID for any flags.
+
+parameters: None
+*/
+_taskDataStore setVariable ["_fnc_remove_flag_network_vars", {
+ // broadcast that the flag no longer exists.
+ vn_mf_bn_dc_target_flag = nil;
+ publicVariable "vn_mf_bn_dc_target_flag";
+
+ // clear the JIP queue for flag height, not necessary anymore
+ remoteExec ["", "JIP_DACCONG_CTF_FLAG_HEIGHT"];
+}];
+
+
+/*
no one built a FOB, so AI are just going to move to the centre of the zone
parameters: _taskDataStore (_tds)
@@ -422,17 +479,24 @@ parameters: _taskDataStore (_tds)
_taskDataStore setVariable ["defend_flag", {
params ["_tds"];
private _flag = _tds getVariable "flag";
+
+ // check if the main task has completed
+ // the ctf defend task can only complete once the main defend task is also completed
private _status = [_tds] call (_tds getVariable "_fnc_check_ai_failure_condition");
/*
failure -- flag object has been deleteVehicle'd
occurs when either
- - Dac Cong full lowered the flag through the action
+ - Dac Cong full lowered the flag through the action (deleteVehicle'd)
- the flag has been hammered out of existence (Bluefor tried to be clever)
+ - a zeus has deleted the flag (badAdmin)
*/
- if (isNull _flag) exitWith {
+ if (isNull _flag || isNil "vn_mf_bn_dc_target_flag") exitWith {
+
+ call (_tds getVariable ["_fnc_remove_flag_network_vars", {}]);
+
["CounterAttackExtended"] remoteExec ["para_c_fnc_show_notification", 0];
["FAILED"] call _fnc_finishSubtask;
["FAILED"] call _fnc_finishTask;
@@ -442,6 +506,9 @@ _taskDataStore setVariable ["defend_flag", {
// (30 minutes passed or AI objective has been wiped out)
if (_status == "SUCCESS") exitWith {
+
+ call (_tds getVariable ["_fnc_remove_flag_network_vars", {}]);
+
_tds setVariable ["flagDefended", true];
["SUCCEEDED"] call _fnc_finishSubtask;
};
@@ -462,12 +529,12 @@ _taskDataStore setVariable ["FINISH", {
[_tds getVariable "attackObjective"] call para_s_fnc_ai_obj_finish_objective;
deleteMarker (_tds getVariable ["CircleAreaMarkerName", "activeDefendCircle"]);
- if !(isNull (_tds getVariable ["flag", objNull])) then {
- (_tds getVariable "flag") setVariable ["canLower", false];
- };
+ // do this yet again just in case someone tries to complete tasks via commands
+ call (_tds getVariable ["_fnc_remove_flag_network_vars", {}]);
// force reset the timer to -1 as either the phase was completed
// or the task was forced through with a command
// save current time remaining to the profile DB
[_tds] call (_taskDataStore getVariable "fnc_reset_db_time_remain");
+
}];
diff --git a/mission/functions/tasks/primary/fn_task_pri_capture.sqf b/mission/functions/tasks/primary/fn_task_pri_capture.sqf
index af246034..0bd05c3c 100644
--- a/mission/functions/tasks/primary/fn_task_pri_capture.sqf
+++ b/mission/functions/tasks/primary/fn_task_pri_capture.sqf
@@ -112,8 +112,8 @@ _taskDataStore setVariable ["build_fob", {
private _possibleBases = para_g_bases inAreaArray [
getMarkerPos (_taskDataStore getVariable "taskMarker"),
- selectMax (getMarkerSize (_taskDataStore getVariable "taskMarker") apply {abs _x}),
- selectMax (getMarkerSize (_taskDataStore getVariable "taskMarker") apply {abs _x}),
+ selectMax ((getMarkerSize "activeZoneCircle") apply {abs _x}),
+ selectMax ((getMarkerSize "activeZoneCircle") apply {abs _x}),
0
];
@@ -130,44 +130,101 @@ _taskDataStore setVariable ["build_fob", {
_taskDataStore setVariable ["fob", _possibleBases select 0];
_taskDataStore setVariable ["fob_position_2d", [_fobPos3DASL select 0, _fobPos3DASL select 1]];
+
private _nextTasks = [
- ["build_respawn", (_taskDataStore getVariable "fob_position_2d") getPos [50, 90]],
- ["build_flag", (_taskDataStore getVariable "fob_position_2d") getPos [50, 270]]
+ ["build_respawn", (_taskDataStore getVariable "fob_position_2d") getPos [50, 0]],
+ ["build_flag", (_taskDataStore getVariable "fob_position_2d") getPos [50, 90]],
+ ["build_landing_pad", (_taskDataStore getVariable "fob_position_2d") getPos [50, 180]],
+ ["build_rearm_resupply", (_taskDataStore getVariable "fob_position_2d") getPos [50, 270]]
];
+
["SUCCEEDED", _nextTasks] call _fnc_finishSubtask;
};
}];
-_taskDataStore setVariable ["build_respawn", {
- params ["_taskDataStore"];
+_taskDataStore setVariable ["_fnc_have_built_buildings", {
+ params ["_tds", "_types"];
private _candidates = nearestObjects [
- _taskDataStore getVariable "fob_position_2d",
- ["Land_vn_guardhouse_01", "Land_vn_b_trench_bunker_01_01", "Land_vn_hootch_01_01"],
+ _tds getVariable "fob_position_2d",
+ _types,
para_g_max_base_radius
];
- if !(_candidates isEqualTo []) then {
- _taskDataStore setVariable ["flag_built", true];
+ /*
+ need to check if they are a paradigm built object!
+ otherwise the objective disappears in places like MSS leghorn
+ once FOB is built
+
+ the para_g_building variable is a simple object assigned to
+ the actual arma object, housing all the paradigm building variables.
+ */
+
+ private _para_built_object_first_idx = _candidates findIf {not isNull (_x getVariable ["para_g_building", objNull])};
+
+ (_para_built_object_first_idx > -1)
+}];
+
+
+_taskDataStore setVariable ["build_respawn", {
+ params ["_tds"];
+
+ private _building_types = [
+ "Land_vn_guardhouse_01",
+ "Land_vn_b_trench_bunker_01_01",
+ "Land_vn_hootch_01_01"
+ ];
+ private _building_exists = [_tds, _building_types] call (_tds getVariable "_fnc_have_built_buildings");
+
+ if (_building_exists) then {
+ ["SUCCEEDED"] call _fnc_finishSubtask;
+ };
+}];
+
+_taskDataStore setVariable ["build_landing_pad", {
+ params ["_tds"];
+
+ private _building_types = ["Land_vn_b_helipad_01"];
+ private _building_exists = [_tds, _building_types] call (_tds getVariable "_fnc_have_built_buildings");
+
+ if (_building_exists) then {
+ ["SUCCEEDED"] call _fnc_finishSubtask;
+ };
+}];
+
+_taskDataStore setVariable ["build_rearm_repair_refuel", {
+ params ["_tds"];
+
+ private _building_types = [
+ "vn_b_ammobox_supply_07",
+ "vn_b_ammobox_supply_08",
+ "vn_b_ammobox_supply_09",
+ "Land_vn_usaf_fueltank_75_01"
+ ];
+ private _building_exists = [_tds, _building_types] call (_tds getVariable "_fnc_have_built_buildings");
+
+ if (_building_exists) then {
["SUCCEEDED"] call _fnc_finishSubtask;
};
}];
_taskDataStore setVariable ["build_flag", {
- params ["_taskDataStore"];
+ params ["_tds"];
- private _candidates = nearestObjects [
- _taskDataStore getVariable "fob_position_2d",
- ["vn_flag_usa", "vn_flag_aus", "vn_flag_arvn", "vn_flag_nz"],
- para_g_max_base_radius
+ private _building_types = [
+ "vn_flag_usa",
+ "vn_flag_aus",
+ "vn_flag_arvn",
+ "vn_flag_nz"
];
+ private _building_exists = [_tds, _building_types] call (_tds getVariable "_fnc_have_built_buildings");
- if !(_candidates isEqualTo []) then {
- _taskDataStore setVariable ["flag_built", true];
+ if (_building_exists) then {
["SUCCEEDED"] call _fnc_finishSubtask;
};
}];
+
_taskDataStore setVariable ["AFTER_STATES_RUN", {
params ["_taskDataStore"];
diff --git a/mission/stringtable.xml b/mission/stringtable.xml
index 731ca602..33d43e99 100644
--- a/mission/stringtable.xml
+++ b/mission/stringtable.xml
@@ -729,8 +729,8 @@
The enemy counter-attack was successful. Zone %1 has been lost.
- Enemy counter-attack is succeeding. Timer extended!
- Enemy counter-attack is succeeding. Timer extended!
+ Enemy counter-attack succeeded. Another wave is incoming!
+ Enemy counter-attack succeeded. Another wave is incoming!
No sandbags in inventory