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