Skip to content

Commit

Permalink
Merge pull request #368 from dijksterhuis/daccong-ctf-again
Browse files Browse the repository at this point in the history
DacCong: Fully functioning Capture The Flag system.
  • Loading branch information
dijksterhuis authored Aug 15, 2024
2 parents 1b77025 + ac79bb8 commit 198115b
Show file tree
Hide file tree
Showing 11 changed files with 408 additions and 98 deletions.
2 changes: 2 additions & 0 deletions mission/config/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions mission/config/notifications.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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};
Expand All @@ -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};
Expand Down
4 changes: 2 additions & 2 deletions mission/config/subconfigs/tasks/defend/tasks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions mission/config/subconfigs/tasks/primary/tasks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
50 changes: 36 additions & 14 deletions mission/functions/systems/actions/fn_action_lower_flag.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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 ["<t color='#0000FF'>%1</t>", "Lower Enemy Flag"];
private _actionText = format ["<t color='#FF0000'>%1</t>", "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)",
Expand All @@ -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;
Expand Down
48 changes: 31 additions & 17 deletions mission/functions/systems/actions/fn_action_reraise_flag.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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 ["<t color='#0000FF'>%1</t>", "Re-Raise The Flag"];
private _actionText = format ["<t color='#0000FF'>%1</t>", "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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit 198115b

Please sign in to comment.