diff --git a/description.ext b/description.ext
index 1a99b15b..014b17bc 100644
--- a/description.ext
+++ b/description.ext
@@ -27,10 +27,34 @@ minPlayerDistance = 500; // The minimum distance between corpse or wreck and nea
// FA3 - Respawn Settings
-respawn = 1;
-respawndelay = 3;
-respawnOnStart = 0;
-respawnTemplates[] = {"F_Spectator"};
+respawn = 3;
+respawnDialog = 0;
+respawndelay = -1;
+respawnOnStart = -1;
+respawnButton = 0;
+respawnTemplates[] = {"F_Respawn", "Tickets", "Counter"};
+
+// ============================================================================================
+
+// FA3 - Respawn templates
+// DO NOT REMOVE OR DISABLE THIS BLOCK OF CODE
+
+
+// ============================================================================================
+class CfgRespawnTemplates
+{
+ class F_Respawn
+ {
+ respawnDelay = 30;
+ onPlayerRespawn = "f_fnc_respawn";
+ onPlayerKilled = "f_fnc_respawnKilled";
+ };
+ class F_Spectator
+ {
+ onPlayerRespawn = "f_fnc_activateSpectator";
+ };
+};
+
// ============================================================================================
@@ -269,6 +293,17 @@ class Params
default = 0;
};
+// FA3 - Respawn Tickets Parameters
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+ class f_param_respawnTickets
+ {
+ title = "Respawn tickets per side";
+ values[] = {0,10,25,50,2000};
+ texts[] = {"None", "10", "25", "50", "2000"};
+ default = 10;
+ };
+
// ============================================================================================
// FA3 - Caching
@@ -357,23 +392,6 @@ class CfgDebriefing
};
-
-
-// ============================================================================================
-
-// FA3 - Respawn templates
-// DO NOT REMOVE OR DISABLE THIS BLOCK OF CODE
-
-
-// ============================================================================================
-class CfgRespawnTemplates
-{
- class F_Spectator
- {
- onPlayerRespawn = "f\spect\fn_activateSpectator.sqf";
- };
-};
-
// ============================================================================================
// FA3 - Functions
@@ -420,3 +438,5 @@ class RscTitles
// UI elements for the medical system
#include "f\medical\f_FAMUI.hpp"
};
+
+#include "f\respawn\f_respawnDisplays.hpp"
\ No newline at end of file
diff --git a/f/assignGear/f_assignGear_3IFB_standard.sqf b/f/assignGear/f_assignGear_3IFB_standard.sqf
index 24cefa14..5dce2180 100644
--- a/f/assignGear/f_assignGear_3IFB_standard.sqf
+++ b/f/assignGear/f_assignGear_3IFB_standard.sqf
@@ -588,6 +588,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_3IFB_v.sqf";
diff --git a/f/assignGear/f_assignGear_aaf_standard.sqf b/f/assignGear/f_assignGear_aaf_standard.sqf
index adf01dc2..fadfdbd3 100644
--- a/f/assignGear/f_assignGear_aaf_standard.sqf
+++ b/f/assignGear/f_assignGear_aaf_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_aaf_v.sqf";
diff --git a/f/assignGear/f_assignGear_csatPacific_standard.sqf b/f/assignGear/f_assignGear_csatPacific_standard.sqf
index 86bd7b1a..96989e00 100644
--- a/f/assignGear/f_assignGear_csatPacific_standard.sqf
+++ b/f/assignGear/f_assignGear_csatPacific_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_csat_v.sqf";
diff --git a/f/assignGear/f_assignGear_csat_standard.sqf b/f/assignGear/f_assignGear_csat_standard.sqf
index e092a1db..2537306e 100644
--- a/f/assignGear/f_assignGear_csat_standard.sqf
+++ b/f/assignGear/f_assignGear_csat_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_csat_v.sqf";
diff --git a/f/assignGear/f_assignGear_ctrg_standard.sqf b/f/assignGear/f_assignGear_ctrg_standard.sqf
index 8342ba1c..221e084e 100644
--- a/f/assignGear/f_assignGear_ctrg_standard.sqf
+++ b/f/assignGear/f_assignGear_ctrg_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_ctrg_v.sqf";
diff --git a/f/assignGear/f_assignGear_fia_standard.sqf b/f/assignGear/f_assignGear_fia_standard.sqf
index f7d7d70e..2ecf98f0 100644
--- a/f/assignGear/f_assignGear_fia_standard.sqf
+++ b/f/assignGear/f_assignGear_fia_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_fia_v.sqf";
diff --git a/f/assignGear/f_assignGear_gendarmerie.sqf b/f/assignGear/f_assignGear_gendarmerie.sqf
index 661e1889..dfbc4979 100644
--- a/f/assignGear/f_assignGear_gendarmerie.sqf
+++ b/f/assignGear/f_assignGear_gendarmerie.sqf
@@ -336,6 +336,19 @@ switch (_typeofUnit) do
_unit addmagazines [_chemred,1];
_unit addmagazines [_chemyellow,1];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// CARGO: CAR - room for 10 weapons and 50 cargo items
case "v_car":
{
diff --git a/f/assignGear/f_assignGear_ldf_standard.sqf b/f/assignGear/f_assignGear_ldf_standard.sqf
index 6637783f..8e0911ad 100644
--- a/f/assignGear/f_assignGear_ldf_standard.sqf
+++ b/f/assignGear/f_assignGear_ldf_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_ldf_v.sqf";
diff --git a/f/assignGear/f_assignGear_natoPacific_standard.sqf b/f/assignGear/f_assignGear_natoPacific_standard.sqf
index 03900428..d5d1e3dd 100644
--- a/f/assignGear/f_assignGear_natoPacific_standard.sqf
+++ b/f/assignGear/f_assignGear_natoPacific_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_nato_v.sqf";
diff --git a/f/assignGear/f_assignGear_natoWoodland_standard.sqf b/f/assignGear/f_assignGear_natoWoodland_standard.sqf
index b859678c..cac5dd51 100644
--- a/f/assignGear/f_assignGear_natoWoodland_standard.sqf
+++ b/f/assignGear/f_assignGear_natoWoodland_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_nato_v.sqf";
diff --git a/f/assignGear/f_assignGear_nato_standard.sqf b/f/assignGear/f_assignGear_nato_standard.sqf
index 37b66ce2..332d47dd 100644
--- a/f/assignGear/f_assignGear_nato_standard.sqf
+++ b/f/assignGear/f_assignGear_nato_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_nato_v.sqf";
diff --git a/f/assignGear/f_assignGear_npr_standard.sqf b/f/assignGear/f_assignGear_npr_standard.sqf
index 1ec078a5..03940a8e 100644
--- a/f/assignGear/f_assignGear_npr_standard.sqf
+++ b/f/assignGear/f_assignGear_npr_standard.sqf
@@ -589,6 +589,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_npr_v.sqf";
diff --git a/f/assignGear/f_assignGear_spetsnaz_standard.sqf b/f/assignGear/f_assignGear_spetsnaz_standard.sqf
index e046f89d..01b5484d 100644
--- a/f/assignGear/f_assignGear_spetsnaz_standard.sqf
+++ b/f/assignGear/f_assignGear_spetsnaz_standard.sqf
@@ -593,6 +593,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glmag, 10];
_unit addmagazines [_grenade, 2];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_spetsnaz_v.sqf";
diff --git a/f/assignGear/f_assignGear_syndikat_standard.sqf b/f/assignGear/f_assignGear_syndikat_standard.sqf
index c6f5ccfe..b41a6809 100644
--- a/f/assignGear/f_assignGear_syndikat_standard.sqf
+++ b/f/assignGear/f_assignGear_syndikat_standard.sqf
@@ -588,6 +588,19 @@ switch (_typeofUnit) do
_unit addmagazines [_glriflemag_tr, 2];
_unit addmagazines [_glmag, 5];
};
+// Respawn Loadout:
+ case "respawn":
+ {
+ _unit addmagazines [_riflemag, 1];
+ _unit addweapon _rifle;
+ _unit addmagazines [_smokegrenade, 3];
+ _unit addmagazines [_riflemag, 2];
+ _unit addmagazines [_riflemag_tr, 1];
+ _unit addmagazines [_grenade, 2];
+ {
+ _unit setUnitTrait [_x#0, _x#1];
+ } forEach (_unit getVariable ["f_var_unitTraits",[]]);
+ };
// Include the loadouts for vehicles and crates:
#include "f_assignGear_syndikat_v.sqf";
diff --git a/f/assignGear/fn_assignGear.sqf b/f/assignGear/fn_assignGear.sqf
index 430b1d1a..77e411b7 100644
--- a/f/assignGear/fn_assignGear.sqf
+++ b/f/assignGear/fn_assignGear.sqf
@@ -7,7 +7,9 @@
// The following interprets what has been passed to this script
params[
["_typeofUnit", "", [""]],
- ["_unit", objNull, [objNull]]
+ ["_unit", objNull, [objNull]],
+ ["_faction", ""],
+ ["_isRespawn",false]
];
private _isMan = _unit isKindOf "CAManBase"; // We check if we're dealing with a soldier or a vehicle
_typeofUnit = toLower _typeofUnit; // Tidy input for SWITCH/CASE statements, expecting something like : r = Rifleman, co = Commanding Officer, rat = Rifleman (AT)
@@ -18,8 +20,9 @@ _typeofUnit = toLower _typeofUnit; // Tidy input for SWITCH/CASE statements, exp
// The following code detects what faction the unit's slot belongs to, and stores
// it in the private variable _faction. It can also be passed as an optional parameter.
-private _faction = toLower (param[2, ([_unit] call f_fnc_virtualFaction)]);
-
+if (_faction == "") then {
+ _faction = toLower ([_unit] call f_fnc_virtualFaction);
+};
// ====================================================================================
// INSIGNIA
@@ -38,7 +41,7 @@ _insignia_styles = [_insignia_style_NATO,_insignia_style_CSAT];
// ====================================================================================
// Universal: assign EOD flags to engineer classes
-if (_typeofUnit in ["eng","engm"]) then {
+if ((_typeofUnit in ["eng","engm"]) or (_isRespawn && {(_unit getVariable ["f_var_eodFlagAction",-1]) > -1})) then {
[_unit] call f_fnc_assignEODflags;
};
@@ -56,6 +59,7 @@ if !(local _unit) exitWith {};
// A public variable is set on the unit, indicating their type. This is mostly relevant for the FA3 respawn component
_unit setVariable ["f_var_assignGear",_typeofUnit,true];
+_unit setVariable ["f_var_assignGearFaction",_faction,true];
// ====================================================================================
@@ -283,7 +287,6 @@ if (_isMan) then {
// This variable simply tracks the progress of the gear assignation process, for other
// scripts to reference.
-
_unit setVariable ["f_var_assignGear_done",true,true];
// ====================================================================================
@@ -299,4 +302,4 @@ if (isNil "_carbine") then { //_carbine should exist unless no faction has been
};
};
-// ====================================================================================
+// ====================================================================================
\ No newline at end of file
diff --git a/f/casualtiesCap/f_CasualtiesCapCheck.sqf b/f/casualtiesCap/f_CasualtiesCapCheck.sqf
index 4e9ee63c..4ce4c739 100644
--- a/f/casualtiesCap/f_CasualtiesCapCheck.sqf
+++ b/f/casualtiesCap/f_CasualtiesCapCheck.sqf
@@ -18,7 +18,7 @@ sleep 0.1;
// DECLARE PRIVATE VARIABLES
-private ["_grps", "_side", "_factionsOnly", "_countAliveUnits", "_started", "_remaining"];
+private ["_grps", "_side", "_factionsOnly", "_countAliveUnits", "_started", "_remaining", "_ticketsRemaining", "_respawn_tickets"];
// ====================================================================================
@@ -33,11 +33,11 @@ private ["_grps", "_side", "_factionsOnly", "_countAliveUnits", "_started", "_re
// 4: = If in side mode, only units from these faction(s) will be included (e.g. ["blu_f"])
params [
- ["_sideorgrps", sideUnknown, [sideUnknown,[]]],
- ["_pc", 100, [0]],
- ["_end", 1, [0,{}]],
- ["_onlyPlayable", true, [true]],
- ["_factions",[], [[]]]
+ ["_sideorgrps", sideUnknown, [sideUnknown,[]]],
+ ["_pc", 100, [0]],
+ ["_end", 1, [0,{}]],
+ ["_onlyPlayable", true, [true]],
+ ["_factions",[], [[]]]
];
// ====================================================================================
@@ -47,77 +47,96 @@ params [
if(_sideorgrps isEqualType sideUnknown) then
{
- // SIDE MODE
+ // SIDE MODE
- _side = _sideorgrps;
+ _side = _sideorgrps;
_factionsOnly = count _factions > 0;
_countAliveUnits = {
- // switchableUnits is to support SP; there playableUnits is empty
- // Conversely swichableUnits is empty in MP on the DS. So, one of these will always be empty
- private _eligibleUnits = if(_onlyPlayable) then {(playableUnits + switchableUnits)} else {allUnits};
+ // switchableUnits is to support SP; there playableUnits is empty
+ // Conversely swichableUnits is empty in MP on the DS. So, one of these will always be empty
+ private _eligibleUnits = if(_onlyPlayable) then {(playableUnits + switchableUnits)} else {allUnits};
private _filteredUnits = if(_factionsOnly) then
{
- _eligibleUnits select {(side _x == _side) && (([_x] call f_fnc_virtualFaction) in _factions)};
+ _eligibleUnits select {(side _x == _side) && (([_x] call f_fnc_virtualFaction) in _factions)};
}
else
{
- _eligibleUnits select {side _x == _side};
+ _eligibleUnits select {side _x == _side};
};
{alive _x} count _filteredUnits;
};
+ _ticketsRemaining = {
+ [_side] call BIS_fnc_respawnTickets;
+ };
- // DEBUG
- if (f_param_debugMode == 1) then
- {
- systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): CasCap operating in SIDE mode. _side = %1, _onlyPlayable = %2, _factionsOnly = %3, _factions = %4",_side,_onlyPlayable,_factionsOnly,_factions];
- };
+ // DEBUG
+ if (f_param_debugMode == 1) then
+ {
+ systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): CasCap operating in SIDE mode. _side = %1, _onlyPlayable = %2, _factionsOnly = %3, _factions = %4",_side,_onlyPlayable,_factionsOnly,_factions];
+ };
}
else
{
- // GROUP MODE
+ // GROUP MODE
// COLLECT GROUPS TO CHECK
// If a groups variable was passed we collect all relevant groups
- _grps = [];
-
- sleep 1;
- {
- private _Tgrp = call compile format ["%1",_x];
- if(!isNil "_Tgrp") then
- {
- _grps pushBackUnique _Tgrp;
- };
- } forEach _sideorgrps;
+ _grps = [];
+
+ sleep 1;
+ {
+ private _Tgrp = call compile format ["%1",_x];
+ if(!isNil "_Tgrp") then
+ {
+ _grps pushBackUnique _Tgrp;
+ };
+ } forEach _sideorgrps;
// FAULT CHECK
- // Check if any groups were found. If not, exit with an error message
+ // Check if any groups were found. If not, exit with an error message
- if (count _grps == 0) exitWith {
- systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): No groups found, _sideorgrps = %1, _grps = %2",_sideorgrps,_grps];
- };
+ if (count _grps == 0) exitWith {
+ systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): No groups found, _sideorgrps = %1, _grps = %2",_sideorgrps,_grps];
+ };
- _countAliveUnits = {
- {alive _x} count (flatten (_grps apply {units _x}));
- };
+ _countAliveUnits = {
+ {alive _x} count (flatten (_grps apply {units _x}));
+ };
+
+ _ticketsRemaining = {
+ // check if tickets exist for the group itself or the group's side.
+ _tickets_remaining = 0;
+ {
+ private _tickets_check = [_x] call BIS_fnc_respawnTickets; // update ticket count if group has tickets applied;
+ if (_tickets_check > 0) then {
+ _tickets_remaining = _tickets_check;
+ };
+ private _tickets_check = [side _x] call BIS_fnc_respawnTickets; // update ticket count if group's side has tickets applied;
+ if (_tickets_check > 0) then {
+ _tickets_remaining = _tickets_check;
+ };
+ } foreach _grps;
+ _tickets_remaining // return some number of tickets if at least one group or side has > 0 tickets
+ };
// DEBUG
- if (f_param_debugMode == 1) then
- {
- systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): CasCap operating in GROUP mode. _grps = %1",_grps];
- };
+ if (f_param_debugMode == 1) then
+ {
+ systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): CasCap operating in GROUP mode. _grps = %1",_grps];
+ };
};
// ====================================================================================
// CREATE STARTING VALUES
// A initial count is made of units in the groups listed in _grps.
-_started = [] call _countAliveUnits;
+_started = call _countAliveUnits;
// DEBUG
if (f_param_debugMode == 1) then
{
- systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): _started = %1",_started];
+ systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): _started = %1",_started];
};
// ====================================================================================
@@ -129,18 +148,19 @@ if (f_param_debugMode == 1) then
while {true} do
{
- // Call the local function to determine how many units are still alive
- _remaining = [] call _countAliveUnits;
+ // Call the local function to determine how many units are still alive
+ _remaining = call _countAliveUnits;
+ _respawn_tickets = call _ticketsRemaining;
- // DEBUG
- if (f_param_debugMode == 1) then
- {
- systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): _remaining = %1",_remaining];
- };
+ // DEBUG
+ if (f_param_debugMode == 1) then
+ {
+ systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): _remaining = %1",_remaining];
+ };
- if (_remaining == 0 || ((_started - _remaining) / _started) >= (_pc / 100)) exitWith {};
+ if (_respawn_tickets <= 0 && {_remaining == 0 || ((_started - _remaining) / _started) >= (_pc / 100)}) exitWith {};
- sleep 6;
+ sleep 6;
};
// ====================================================================================
@@ -149,11 +169,11 @@ while {true} do
// Depending on input, either MPEnd or the parsed code itself is called
if (_end isEqualType 0) exitWith {
- [_end] call f_fnc_mpEnd;
+ [_end] call f_fnc_mpEnd;
};
if (_end isEqualType {}) exitWith {
- _end remoteExec ["bis_fnc_spawn", 0];
+ _end remoteExec ["bis_fnc_spawn", 0];
};
systemChat format ["DEBUG (f\casualtiesCap\f_CasualtiesCapCheck.sqf): Ending didn't fire, should either be code or scalar. _end = %1, typeName _end: %2",_end,typeName _end];
diff --git a/f/functions.hpp b/f/functions.hpp
index c1e5e2fd..3feab4de 100644
--- a/f/functions.hpp
+++ b/f/functions.hpp
@@ -83,6 +83,17 @@ class F // Defines the "owner"
class mapClickTeleportRemoveAction{};
class mapClickTeleportBriefing{};
};
+ class respawn
+ {
+ file = "f\respawn";
+ class respawn{};
+ class respawnBriefing{};
+ class respawnBeaconAction{};
+ class respawnBeaconDeploy{};
+ class respawnBeaconTeleport{};
+ class respawnKilled{};
+ class respawnTerminalAction{};
+ };
class nametag
{
file = "f\nametag\functions";
diff --git a/f/medical/fn_famAddHealAction.sqf b/f/medical/fn_famAddHealAction.sqf
index 548ad418..bf10d087 100644
--- a/f/medical/fn_famAddHealAction.sqf
+++ b/f/medical/fn_famAddHealAction.sqf
@@ -11,52 +11,14 @@ if (_unit == player) exitWith {};
// Variables to streamline balancing/updates
private _healIcon = "a3\ui_f\data\igui\cfg\holdactions\holdaction_revive_ca.paa"; //Icon to Display
private _healProg = "(_target distance _caller < 3) && {alive _target && !(_target getVariable ['f_var_fam_conscious',true])}"; // This one is always the same, start condition varies by unit type.
-private _healTime = 6; // Action Duration
-private _healMedicTime = 4.5; // Action Duration
+private _healTime = 14; // Action Duration
+private _healMedicTime = 8.5; // Action Duration
// Starting Code
private _healCodeStart = {
// this is needed to protect against BI bugs that remove all actions.
_caller setVariable ["f_var_fam_flag",true];
-
- // Match medic animation speed to speed modifier.
- if (_caller getUnitTrait 'medic') then {
- _caller setAnimSpeedCoef 1.25;
- };
-
- if (stance _caller == "PRONE") then {
- // Rifle or Binocular
- if ((currentWeapon _caller == binocular _caller) || (currentWeapon _caller == primaryWeapon _caller && {primaryWeapon _caller != ""})) exitWith {
- _caller playMove "ainvppnemstpslaywrfldnon_medicother";
- };
- // Nothing
- if (currentWeapon _caller == "") exitWith {
- _caller playMove "ainvppnemstpslaywnondnon_medicother";
- };
- // Pistol
- if (currentWeapon _caller == handgunWeapon _caller && {primaryWeapon _caller != ""}) exitWith {
- _caller playMove "ainvppnemstpslaywpstdnon_medicother";
- };
- } else {
- // Rifle or Binocular
- if ((currentWeapon _caller == binocular _caller) || (currentWeapon _caller == primaryWeapon _caller && {primaryWeapon _caller != ""})) exitWith {
- _caller playMove "ainvpknlmstpslaywrfldnon_medicother";
- };
- // Nothing
- if (currentWeapon _caller == "") exitWith {
- _caller playMove "ainvpknlmstpslaywnondnon_medicother";
- };
- // Launcher
- if (currentWeapon _caller == secondaryWeapon _caller && {primaryWeapon _caller != ""}) exitWith {
- _caller playMove "ainvpknlmstpslaywlnrdnon_medicother";
- };
- // Pistol
- if (currentWeapon _caller == handgunWeapon _caller && {primaryWeapon _caller != ""}) exitWith {
- _caller playMove "ainvpknlmstpslaywpstdnon_medicother";
- };
- };
- // Let the wounded know someone is trying to save them.
- if !(_target getVariable ['f_var_fam_conscious',true]) then {[["Someone is helping you", "PLAIN"]] remoteExec ["titleText",_target];}; // TODO Test?
+ _caller playAction "medicStart";
};
// Progress Code
@@ -66,6 +28,7 @@ private _healCodeProg = {};
private _healCodeComp = {
// this is needed to protect against BI bugs that remove all actions.
_caller setVariable ["f_var_fam_flag",false];
+ _caller playAction "medicStop";
// Medic heals to full only if they have a medikit. TODO CLS Support?
if (_caller getUnitTrait 'Medic' && (_caller call f_fnc_famHasFAK >= 1)) then {
@@ -88,13 +51,7 @@ private _healCodeComp = {
private _healCodeInt = {
// this is needed to protect against BI bugs that remove all actions.
_caller setVariable ["f_var_fam_flag",false];
-
- // Exit animation
- if (animationState _caller find "ppne" != -1) then {
- _caller switchMove "AinvPpneMstpSlayWnonDnon_medicOut";
- } else {
- _caller switchMove "AinvPknlMstpSlayWnonDnon_medicOut";
- };
+ _caller playAction "medicStop";
};
// ====================================================================================
diff --git a/f/medical/fn_famDamageHandler.sqf b/f/medical/fn_famDamageHandler.sqf
index a94de9ba..44d8fc6a 100644
--- a/f/medical/fn_famDamageHandler.sqf
+++ b/f/medical/fn_famDamageHandler.sqf
@@ -59,6 +59,16 @@ if (vehicle _unit isKindof "Air" && {driver vehicle _unit == _unit}) then {
};
_newDamage = _currentDamage + _newHit;
+// Prevent outright death
+if (_newDamage > 0.95) then {
+ if !(_unit getVariable ["f_var_fam_conscious",true]) then {
+ _newDamage = _currentDamage + (_newHit min 0.005);
+ } else {
+ _newDamage = 0.95;
+ };
+ _unit setVariable ["f_var_fam_forcedown",true];
+ _unit setVariable ["f_var_fam_forcedownparams",[_source,_selection,_projectile]];
+};
// Down you on a big hit.
if (_selection != "" && {!(_selection in ["hands","arms"]) && {_hitSize > 2 || {_hitSize > 1 && random 2 > 1}}}) then {
diff --git a/f/medical/fn_famEH.sqf b/f/medical/fn_famEH.sqf
index 7014fc7a..27200ab8 100644
--- a/f/medical/fn_famEH.sqf
+++ b/f/medical/fn_famEH.sqf
@@ -6,7 +6,7 @@ params ["_unit"];
// ====================================================================================
// When they die
-_ehKilled = _unit addEventHandler ["Killed", {
+private _ehKilled = _unit addEventHandler ["Killed", {
params ["_unit"];
// EXIT
// This occurs after death, make sure that none of the wounded affects carry over.
@@ -27,12 +27,14 @@ _ehKilled = _unit addEventHandler ["Killed", {
// store name on corpse for future diagnosis.
_unit setVariable ["f_var_fam_corpse",name _unit,true];
+ _unit setVariable ["f_var_fam_bleed",false,true];
+ _unit setVariable ["f_var_fam_conscious",true,true];
}];
// ====================================================================================
// Treatment Feedback
-_ehHeal = _unit addEventHandler ["HandleHeal", {
+private _ehHeal = _unit addEventHandler ["HandleHeal", {
// notification correction for self FAK usage.
params ["_injured", "_healer"];
@@ -56,10 +58,20 @@ _ehHeal = _unit addEventHandler ["HandleHeal", {
}];
+// ====================================================================================
+// Respawn handling
+private _ehRespawn = _unit addEventHandler ["Respawn", {
+ params ["_unit"];
+ if !(local _unit) exitWith {};
+ if !(_unit isKindOf "VirtualMan_F") then {
+ _unit setVariable ["f_var_fam_actionsAdded",false,true];
+ [_unit] remoteExec ["f_fnc_famAddAllActions", 0, ("f_jip_famAddAllActions" + netId _unit)];
+ };
+}];
// ====================================================================================
waitUntil {sleep 0.1; f_param_mission_timer <= 0}; // need to wait until post safeStart for this.
// Handle Damage
_ehDamage = _unit addEventHandler ["HandleDamage",{_this call f_fnc_famDamageHandler;}];
-_unit setVariable ["f_var_fam_allEHs",[_ehDamage,_ehKilled,_ehHeal]];
\ No newline at end of file
+_unit setVariable ["f_var_fam_allEHs",[_ehDamage,_ehKilled,_ehHeal,_ehRespawn]];
\ No newline at end of file
diff --git a/f/medical/fn_famInit.sqf b/f/medical/fn_famInit.sqf
index 15102ccd..731daeea 100644
--- a/f/medical/fn_famInit.sqf
+++ b/f/medical/fn_famInit.sqf
@@ -46,7 +46,9 @@ waitUntil{!isNull player && {player == player}};
if (!hasInterface) exitWith {};
if (player getVariable ["f_var_fam_initDone",false]) exitWith {
- systemChat "FAM init already run!";
+ if (f_param_debugMode == 1) then {
+ systemChat "DEBUG (fn_famInit.sqf): FAM init already run!";
+ };
};
// ====================================================================================
@@ -69,7 +71,7 @@ _unit setVariable ["f_var_fam_forcedown",false];
_unit setVariable ["f_var_fam_hasfak",false];
_unit setVariable ["f_var_fam_hasbandage",false];
_unit getVariable ["f_var_fam_flag",false];
-_unit setVariable ["f_var_fam_actions",false];
+_unit setVariable ["f_var_fam_actionsAdded",false];
[_unit] spawn f_fnc_famLoop;
@@ -87,7 +89,7 @@ if (count (_unit getVariable ["f_var_fam_allEHs",[]]) == 0) then {
if (!(_unit getVariable ["f_var_fam_actions",false]) && {hasInterface}) then {
- [_unit] remoteExec ["f_fnc_famAddAllActions", 0, ("f_jip_famAddAllActions" + (_unit call BIS_fnc_netId))];
+ [_unit] remoteExec ["f_fnc_famAddAllActions", 0, ("f_jip_famAddAllActions" + netId _unit)];
_unit setVariable ["f_var_fam_actions",true,true];
};
@@ -115,4 +117,7 @@ if (isNil "f_var_fam_briefingDone") then {
[] call f_fnc_famBriefing;
};
-player setVariable ["f_var_fam_initDone",true,true];
\ No newline at end of file
+player setVariable ["f_var_fam_initDone",true];
+if (f_param_debugMode == 1) then {
+ systemChat "DEBUG (fn_famInit.sqf): FAM init run on local player";
+};
\ No newline at end of file
diff --git a/f/medical/fn_famLoop.sqf b/f/medical/fn_famLoop.sqf
index 837b20cb..23e519aa 100644
--- a/f/medical/fn_famLoop.sqf
+++ b/f/medical/fn_famLoop.sqf
@@ -21,6 +21,27 @@ while {alive _unit && {local _unit}} do {
};
// ====================================================================================
+ // Timeout for being downed
+ private _knockoutTime = _unit getVariable ["f_var_fam_knockOutTime", serverTime];
+ if ((serverTime - _knockOutTime) > 180) then {
+ if (isNull (uiNamespace getVariable ["f_var_fam_respawnDisplay",displayNull])) then {
+ uiNamespace setVariable ["f_var_fam_respawnDisplay",findDisplay 46 createDisplay "f_respawnUI"];
+ };
+ };
+ // If the unit is in a dead vehicle, eject them (if vehicle is on the ground and at very low speed) or kill them (if it isn't)
+ if (!(isNull objectParent _unit) && {!alive objectParent _unit}) then {
+ sleep 3;
+ private _parent = objectParent _unit;
+ if (!(isNull _parent) && {!alive _parent}) then {
+ if (((getPos _parent select 2) < 5) && {(vectorMagnitude velocity _parent) < 4.2}) then {
+ moveOut _unit;
+ } else {
+ _unit setDamage 1;
+ break;
+ };
+ };
+ };
+
// PASSOUT TEST
// Force Unit Down above damage threshold.
if (damage _unit >= 0.9 && {_unit getVariable ["f_var_fam_conscious",true]}) then {
@@ -125,7 +146,7 @@ while {alive _unit && {local _unit}} do {
_tick = selectRandom [0.001,0.002,0.004]; // slower rate closer to death.
} else {
_tick = selectRandom [0.06,0.08,0.11]; // faster rate until you are forced down.
- if (_currentDamage + _tick >= 1) then {_tick = 0.01}; //careful not to overdamage you with the bleed.
+ if (_currentDamage + _tick >= 0.99) then {_tick = 0.01}; //careful not to overdamage you with the bleed.
};
{ // save current hands and legs damage.
diff --git a/f/medical/fn_famPassOut.sqf b/f/medical/fn_famPassOut.sqf
index 64a7214e..701f2b7b 100644
--- a/f/medical/fn_famPassOut.sqf
+++ b/f/medical/fn_famPassOut.sqf
@@ -112,6 +112,9 @@ if (isPlayer _unit) then {
};
};
+_unit setVariable ["f_var_fam_knockOutTime", serverTime, true];
+
+[_unit, "f_fam_knockOut", [_unit]] call BIS_fnc_callScriptedEventHandler;
// VISUAL EFFECTS
// Create a loop for the wounded visual effects.
_unit spawn {
diff --git a/f/medical/fn_famWakeUp.sqf b/f/medical/fn_famWakeUp.sqf
index ac0b28d9..5af5c114 100644
--- a/f/medical/fn_famWakeUp.sqf
+++ b/f/medical/fn_famWakeUp.sqf
@@ -22,6 +22,8 @@ for "_i" from 2 to 5 do {
_i enableChannel true;
};
+_unit setVariable ["f_var_fam_knockOutTime",nil,true];
+
// check for radio channels
[_unit] spawn f_fnc_radioCheckChannels;
@@ -80,6 +82,10 @@ if(local _unit) then
};
};
+if (_unit == player) then {
+ (uiNamespace getVariable ["f_var_fam_respawnDisplay", displayNull]) closeDisplay 1;
+};
+
// exit if they are dead
if (damage _unit >= 1) exitWith {};
// ====================================================================================
@@ -89,6 +95,8 @@ titleText ["","PLAIN"];
_unit setCaptive false;
+[_unit, "f_fam_wakeUp", [_unit]] call BIS_fnc_callScriptedEventHandler;
+
// DELAYED RESETS
_unit spawn {
diff --git a/f/missionConditions/f_conditionNotes.sqf b/f/missionConditions/f_conditionNotes.sqf
index 1446f413..29859219 100644
--- a/f/missionConditions/f_conditionNotes.sqf
+++ b/f/missionConditions/f_conditionNotes.sqf
@@ -70,5 +70,6 @@ _diaryText = _diaryText + format ["
Mo
// Insert final result into briefing
+waitUntil {!isNil "f_script_briefing"};
waitUntil {scriptDone f_script_briefing};
player createDiaryRecord ["diary", ["Mission Conditions", _diaryText]];
diff --git a/f/radio/fn_radioAddHandlers.sqf b/f/radio/fn_radioAddHandlers.sqf
index 52825393..be4c4789 100644
--- a/f/radio/fn_radioAddHandlers.sqf
+++ b/f/radio/fn_radioAddHandlers.sqf
@@ -11,7 +11,7 @@ params [["_respawned",false]];
waitUntil {(!isNull player && {player == player}) && !(isNil "f_var_radioChannelsUnified")};
// Add player to the correct channels if they have a backpack
-[player] spawn f_fnc_radioCheckChannels;
+player spawn f_fnc_radioCheckChannels;
// Now bail if they've already been handled, unless they respawned in which case they do need the actions adding
if (player getVariable ["f_var_radioHandlersAdded",false] && !_respawned) exitWith {};
@@ -24,44 +24,44 @@ if _respawned exitWith {};
// Update channels if they drop a backpack
player addEventHandler ["put", {
- params ["_unit", "_container", "_item"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they take a backpack
player addEventHandler ["take", {
- params ["_unit", "_container", "_item"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they open their inventory
player addEventHandler ["inventoryOpened", {
- params ["_unit", "_container"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they close their inventory
player addEventHandler ["inventoryClosed", {
- params ["_unit", "_container"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they get in a vehicle
player addEventHandler ["getInMan", {
- params ["_unit", "_role", "_vehicle", "_turret"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they get out of a vehicle
player addEventHandler ["getOutMan", {
- params ["_unit", "_role", "_vehicle", "_turret"];
- [_unit] spawn f_fnc_radioCheckChannels;
+ params ["_unit"];
+ _unit spawn f_fnc_radioCheckChannels;
}];
// Update channels if they switch seats in a vehicle
player addEventHandler ["seatSwitchedMan", {
- params ["_unit1", "_unit2", "_vehicle"];
- [_unit1] spawn f_fnc_radioCheckChannels;
+ params ["_unit1"];
+ _unit1 spawn f_fnc_radioCheckChannels;
}];
// Add respawn protection
@@ -85,7 +85,7 @@ if (isNil "f_var_radioPersistentCheck") then {
[] spawn {
while {f_var_radioPersistentCheck} do {
sleep 10;
- [player] spawn f_fnc_radioCheckChannels;
+ player spawn f_fnc_radioCheckChannels;
};
};
};
@@ -98,4 +98,4 @@ if (f_param_debugMode == 1) then
// Check again!
sleep 1;
-[player] spawn f_fnc_radioCheckChannels;
\ No newline at end of file
+player spawn f_fnc_radioCheckChannels;
\ No newline at end of file
diff --git a/f/radio/fn_radioCheckChannels.sqf b/f/radio/fn_radioCheckChannels.sqf
index 116507cc..dfd6b82c 100644
--- a/f/radio/fn_radioCheckChannels.sqf
+++ b/f/radio/fn_radioCheckChannels.sqf
@@ -96,6 +96,10 @@ for "_i" from 1 to 2 do {
if !(_unit getVariable ["f_var_fam_conscious",true]) then {
_channelsToAddTalk = [];
};
+ if !(alive _unit) then {
+ _channelsToAddTalk = [];
+ _channelsToAddListen = [];
+ };
// Remove channels player shouldn't have access to
for "_i" from 1 to f_var_radioChannelCount do {
diff --git a/f/respawn/f_respawnDisplays.hpp b/f/respawn/f_respawnDisplays.hpp
new file mode 100644
index 00000000..b3376e9c
--- /dev/null
+++ b/f/respawn/f_respawnDisplays.hpp
@@ -0,0 +1,115 @@
+class f_respawnUI
+{
+ idd = 3680;
+ duration = 1e+6;
+ access = 0;
+ movingEnable = false;
+ enableSimulation = true;
+ fadeIn = 0;
+ fadeOut = 0;
+ onLoad = "";
+
+ class Controls
+ {
+ class f_respawnControlsGroup : RscControlsGroupNoScrollbars
+ {
+ type = CT_CONTROLS_GROUP;
+ idc = -1;
+ style = 0;
+ x = safeZoneX + safeZoneW * 0.39;
+ y = safeZoneY + safeZoneH * 0.22;
+ w = safeZoneW * 0.22;
+ h = safeZoneH * 0.1;
+ onLoad = "";
+ class HScrollbar
+ {
+ height = 0;
+ width = 0;
+ shadow = 0;
+ };
+ class VScrollbar
+ {
+ height = 0;
+ width = 0;
+ };
+
+ class Controls
+ {
+ class f_respawnBackground : RscText
+ {
+ type = CT_STATIC;
+ idc = 3689;
+ x = 0;
+ y = 0;
+ w = safeZoneW * 0.25;
+ h = safeZoneH * 0.095;
+ style = 0;
+ text = "";
+ colorBackground[] = {0.05,0.05,0.05,0.7};
+ };
+ class f_respawnStatusText : RscStructuredText
+ {
+ type = CT_STRUCTURED_TEXT;
+ idc = 3681;
+ x = safeZoneW * 0.027;
+ y = safeZoneH * 0.032;
+ w = safeZoneW * 0.22;
+ h = safeZoneH * 0.02;
+ style = 0;
+ text = "You have been unconscious for more than 3 minutes.";
+ colorBackground[] = {0.8863,0.7294,0.7294,0};
+ colorText[] = {1,1,0.302,1};
+ font = "PuristaMedium";
+ sizeEx = (((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1);
+
+ };
+ class f_respawnStatus2Text : RscStructuredText
+ {
+ type = CT_STRUCTURED_TEXT;
+ idc = 3682;
+ x = safeZoneW * 0.027;
+ y = safeZoneH * 0.057;
+ w = safeZoneW * 0.22;
+ h = safeZoneH * 0.02;
+ style = 0;
+ text = "Wait for revive or click this button to respawn.";
+ colorBackground[] = {0.8863,0.7294,0.7294,0};
+ colorText[] = {1,1,0.302,1};
+ font = "PuristaMedium";
+ sizeEx = (((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1);
+ };
+ class f_respawnTitleText : RscStructuredText
+ {
+ type = CT_STRUCTURED_TEXT;
+ idc = 3683;
+ x = 0;
+ y = 0;
+ w = safeZoneW * 0.22;
+ h = safeZoneH * 0.019;
+ style = 0;
+ text = "FA3 Respawn";
+ colorBackground[] = {0.1,0.1,0.1,1};
+ colorText[] = {1,1,1,1};
+ font = "PuristaMedium";
+ sizeEx = (((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1);
+ };
+ class f_respawnButton : RscButton
+ {
+ type = CT_BUTTON;
+ idc = 3684;
+ x = safeZoneW * 0.003;
+ y = safeZoneH * 0.025;
+ w = safeZoneW * 0.02;
+ h = safeZoneH * 0.063;
+ style = 0;
+ text = "";
+ colorBackground[] = {1,1,1,1};
+ colorFocused[] = {0.98,0.51,0,1};
+ colorFocused2[] = {0.98,0.51,0,1};
+ colorBackGroundActive[] = {0.98,0.51,0,1};
+ action = "player setDamage 1; (uiNamespace getVariable ['f_var_fam_respawnDisplay', displayNull]) closeDisplay 1;";
+ };
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/f/respawn/fn_respawn.sqf b/f/respawn/fn_respawn.sqf
new file mode 100644
index 00000000..d6a17374
--- /dev/null
+++ b/f/respawn/fn_respawn.sqf
@@ -0,0 +1,33 @@
+// FA3 - Respawn Module - Respawn Event
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function is executed from the FA3 Respawn Template in description.ext and should not be used for other purposes.
+This function relies on the f_respawnBase object being present in the mission - a proxy object used to set the player's position on spawning, and to gauge when they've left the respawn base.
+Example:
+onPlayerRespawn = "f_fnc_respawn";
+
+Arguments: as automatically passed to onPlayerRespawn.sqf
+=========================== */
+params ["_newUnit", "_oldUnit"];
+
+waitUntil {local _newUnit};
+
+["respawn", _newUnit, _oldUnit getVariable ["f_var_assignGearFaction", toLower ([_oldUnit] call f_fnc_virtualFaction)], true] call f_fnc_assignGear;
+
+call f_fnc_terminateSpectator;
+private _newTickets = [side group _newUnit] call BIS_fnc_respawnTickets;
+private _respawnText = format ["[%1] You have respawned. %2 tickets remaining.", side group _newUnit, _newTickets];
+systemChat _respawnText;
+
+_newUnit assignTeam (_oldUnit getVariable ["f_var_lastTeamColour","MAIN"]);
+
+_newUnit allowDamage false;
+_newUnit setPosASL getPosASL f_respawnBase;
+
+waitUntil {
+ sleep 2;
+ (_newUnit distance f_respawnBase) > 100;
+};
+_newUnit allowDamage true;
+_newUnit setCaptive false;
\ No newline at end of file
diff --git a/f/respawn/fn_respawnBeaconAction.sqf b/f/respawn/fn_respawnBeaconAction.sqf
new file mode 100644
index 00000000..950a8186
--- /dev/null
+++ b/f/respawn/fn_respawnBeaconAction.sqf
@@ -0,0 +1,42 @@
+// FA3 - Respawn Module - Beacon Summon Action
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function is executed from fn_respawnBeaconDeploy, or manually by the missionmaker. It must be executed on all machines with JIP persistence.
+It adds an action to the given object, allowing it to act as an FA3 Respawn Beacon, used to summon players of your side from the respawn base.
+Example:
+[_object] remoteExec ["f_fnc_respawnBeaconAction",0,true];
+_object call f_fnc_respawnBeaconAction;
+
+Arguments:
+0. Target (object) - object to add the action to
+1. Radius (number) - Optional - radius for the action. Increase it for large objects as the radius is measured from object centre. Default: 3
+=========================== */
+
+params ["_object",["_radius",3]];
+
+private _condition = format ["(isNull objectParent _this) && {(_this distance _target) < %1}", _radius];
+
+[
+ _object,
+ "Call reinforcements to rally point",
+ "a3\ui_f_oldman\data\igui\cfg\holdactions\meet_ca.paa",
+ "a3\ui_f_oldman\data\igui\cfg\holdactions\meet_ca.paa",
+ _condition,
+ _condition,
+ {
+ private _text = format ["[%1] Searching for ready reinforcements...", str side group _caller];
+ systemChat _text;
+ },
+ {},
+ {
+ _caller spawn f_fnc_respawnBeaconTeleport;
+ },
+ {},
+ [],
+ 5,
+ 10,
+ false,
+ false,
+ true
+] call BIS_fnc_holdActionAdd;
\ No newline at end of file
diff --git a/f/respawn/fn_respawnBeaconDeploy.sqf b/f/respawn/fn_respawnBeaconDeploy.sqf
new file mode 100644
index 00000000..ea14e1d8
--- /dev/null
+++ b/f/respawn/fn_respawnBeaconDeploy.sqf
@@ -0,0 +1,89 @@
+// FA3 - Respawn Module - Beacon Placement
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function is typically executed by the FA3 Respawn Player Actions briefing tab, but it can be used in other contexts if needed. It must be executed in a scheduled environment, and should be executed only on one machine at a time.
+Example:
+[player] spawn f_fnc_respawnBeaconDeploy
+
+Arguments:
+0. Unit (object) - Living unit which will place the beacon, ideally the local player.
+=========================== */
+
+params ["_caller"];
+// Exit if you don't meet basic conditions
+if !(isNull objectParent _caller) exitWith {
+ systemChat "Can't place rally beacon while in a vehicle.";
+};
+if !(_caller == leader _caller) exitWith {
+ systemChat "Only group leaders can place a rally beacon.";
+};
+// Check cooldown
+private _side = str side group _caller;
+private _timerVarName = format ["f_var_lastRespawnBeacon_%1", _side];
+private _cooldown = serverTime - (missionNamespace getVariable [_timerVarName, serverTime - 301]);
+if (_cooldown < 300) exitWith {
+ private _text = format ["[%1] Rally beacon on cooldown: %2", _side, [_cooldown, "MM:SS"] call BIS_fnc_secondsToString];
+ systemChat _text;
+};
+
+_caller playActionNow "MedicOther";
+private _text = format ["[%1] %2 is deploying a rally beacon.", _side, name _caller];
+[_text] remoteExec ["systemChat"];
+
+sleep 5;
+
+if !(alive _caller) exitWith {};
+// Check 3 possible positions
+{
+ // Aim about waist height
+ private _position = _caller modelToWorldWorld [0,1.5,0.8];
+ private _positionATL = ASLtoATL _position;
+ private _heightATL = _positionATL select 2;
+ // Can't place flag below terrain
+ if (_heightATL < -2.5) then { continue };
+ // If it's not too far below terrain, adjust up
+ if (_heightATL < 0.1) then {
+ _position = _position vectorAdd [0,0, - _heightATL];
+ };
+ // Determine whether a valid surface is within vertical range
+ private _intersects = lineIntersectsSurfaces [_position, _position vectorAdd [0,0,-2.5], _caller, objNull, true, 1, "GEOM"];
+ if (count _intersects > 0) then {
+ private _intersection = _intersects select 0;
+ // Can't place on or in vehicles
+ if (["Air","LandVehicle","Ship"] findIf {(_intersection select 2) isKindOf _x} > -1) then { continue };
+
+ _position = _intersection select 0;
+ private _beacon = createSimpleObject ["OmniDirectionalAntenna_01_olive_F", [0,0,0]];
+ [_beacon, false] remoteExec ["setPhysicsCollisionFlag",0,true];
+ _beacon setPosASL _position;
+
+ playSound3D ["A3\Sounds_F_AoW\SFX\Showcase_Future\place_flag.wss",_beacon,false,_position, 2, 1, 25];
+ _beacon setVectorUp [0,0,1];
+ _beacon setDir (getDir _caller - 90);
+
+ private _smokeType = ["SmokeShellRed_Infinite", "SmokeShellBlue_Infinite", "SmokeShellGreen_Infinite", "SmokeShellPurple_Infinite", "SmokeShellYellow_Infinite","SmokeShellWhite_Infinite","SmokeShellWhite_Infinite","SmokeShellWhite_Infinite","SmokeShellWhite_Infinite","SmokeShellWhite_Infinite"] select ((side group _caller) call BIS_fnc_sideID);
+ private _smoke = _smokeType createVehicle [0,0,0];
+ _smoke setPosASL _position;
+ _beacon setVariable ["f_beaconSmoke",_smoke,true];
+
+ private _sphere = "Sign_Sphere100cm_Geometry_F" createVehicle [0,0,0];
+ _sphere setObjectTextureGlobal [0, ""];
+ _sphere setPosASL (_position vectorAdd [0,0,0.5]);
+ [_sphere] remoteExec ["f_fnc_respawnBeaconAction",0,true];
+ _beacon setVariable ["f_beaconSphere",_sphere,true];
+
+ // If we got this far we can skip any remaining positions
+ private _varName = format ["f_var_respawnBeacon_%1", _side];
+ private _oldBeacon = missionNamespace getVariable [_varName, objNull];
+ deleteVehicle ((attachedObjects _oldBeacon) + [_oldBeacon getVariable ["f_beaconSmoke",objNull], _oldBeacon, _oldBeacon getVariable ["f_beaconSphere",objNull]]);
+ missionNamespace setVariable [_varName, _beacon, true];
+ break;
+ };
+} forEach [[0,1.5,0.8],[0,0.75,0.8],[0,0.1,0.1]];
+
+// Cooldown marker
+missionNamespace setVariable [_timerVarName, serverTime, true];
+
+private _text = format ["[%1] %2 deployed a rally beacon.", _side, name _caller];
+[_text] remoteExec ["systemChat"];
\ No newline at end of file
diff --git a/f/respawn/fn_respawnBeaconTeleport.sqf b/f/respawn/fn_respawnBeaconTeleport.sqf
new file mode 100644
index 00000000..62c6b07a
--- /dev/null
+++ b/f/respawn/fn_respawnBeaconTeleport.sqf
@@ -0,0 +1,55 @@
+// FA3 - Respawn Module - Teleport
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function handles teleporting a unit to their side's FA3 Respawn Beacon or deployment vehicle.
+Example:
+[player] call f_fnc_respawnTeleport
+
+If using a deployment vehicle, you must have a vehicle with name f_var_respawnBeacon_west (_east, _guer, etc) for your players force.
+
+Arguments:
+0. Unit (object) - Living unit which will be teleported.
+=========================== */
+params ["_caller"];
+
+private _sideString = str side group _caller;
+
+private _varName = format ["f_var_respawnBeacon_%1", _sideString];
+private _respawnBeacon = missionNamespace getVariable [_varname, objNull];
+
+if (isNull _respawnBeacon) exitWith {
+ systemChat format ["[%1] No available rally point for your side.", _sideString];
+};
+
+private _readyUnits = (playableUnits + switchableUnits) select {(side group _x == side group _caller) && {(_x distance f_respawnTerminal) < 100}};
+if (count _readyUnits < 1) exitWith {
+ systemChat format ["[%1] No available reinforcements for your side.", _sideString];
+};
+
+if (typeOf _respawnBeacon == "OmniDirectionalAntenna_01_olive_F") exitWith {
+ {
+ private _text = format ["[%1] %2 is deploying to the rally point.", _sideString, name _x];
+ [_text] remoteExec ["systemChat"];
+ private _randomNumber = random [0.5, 1, 1.5];
+ private _pos = (getPosASL _respawnBeacon) vectorAdd [_randomNumber, random [-1, 0, 1], 0];
+ _x setPosASL _pos;
+ } forEach _readyUnits;
+};
+
+if (_respawnBeacon isKindOf "AllVehicles") exitWith {
+ if (!alive _respawnBeacon) exitWith {
+ systemChat "Rally point vehicle has been destroyed! Please wait for a new deployment point.";
+ };
+ {
+ if (_respawnBeacon emptyPositions "Cargo" >= 1) then {
+ private _text = format ["[%1] %2 is deploying to the rally point vehicle.", _sideString, name _x];
+ [_text] remoteExec ["systemChat"];
+ [_x,_respawnBeacon] remoteExec ["moveInCargo"];
+ } else {
+ breakWith { systemChat "Rally point vehicle has no available cargo seats, please try again." };
+ };
+ sleep 0.3;
+ } forEach _readyUnits;
+};
+
diff --git a/f/respawn/fn_respawnBriefing.sqf b/f/respawn/fn_respawnBriefing.sqf
new file mode 100644
index 00000000..765a86a1
--- /dev/null
+++ b/f/respawn/fn_respawnBriefing.sqf
@@ -0,0 +1,49 @@
+// FA3 - Respawn Module - Briefing
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This module is activated in init.sqf.
+Example:
+0 spawn f_fnc_respawnBriefing
+
+Arguments:
+0. mode: 0 - deployable beacons, 1 - teleport to vehicle, 2 - respawn and wait for pickup
+=========================== */
+if !(hasInterface) exitWith {};
+if !(isNil "f_var_respawn_briefingDone") exitWith{};
+
+params ["_respawnMode"];
+
+waitUntil {scriptDone f_script_briefing};
+_str_deploy = "to be deployed to your side's deployment vehicle.";
+
+if (_respawnMode == 0) then {
+ player createDiaryRecord ["fa3_actions",["FA3 Rally Point","
+
+The FA3 Respawn system allows team leaders to deploy a rally point for their side. You can use this rally point to summon respawning players.
+
+Placing this rally point will remove any previously-placed rally point for your side. You can only place this rally point if you are the leader of your group. There is a 5-minute cooldown after placing a beacon before another beacon for that side can be placed.
+
+Place rally point"
+ ]];
+ _str_deploy = "to be deployed to your side's rally point.
Group leaders can place their side's rally point from the FA3 Player Actions briefing menu.";
+};
+
+if (_respawnMode == 2) then {
+ _str_deploy = "for pickup by an allied transport.";
+};
+
+waitUntil {!isNil "f_script_loadoutNotes"};
+waitUntil {scriptDone f_script_loadoutNotes};
+
+player createDiaryRecord ["diary", ["FA3 Respawn",format ["
+
+If you have been unconscious for 3 minutes straight, you will have the option to respawn. After a brief timeout, you will respawn at a neutral base location.
+
+At the base, you will have access to a terminal, which you can use to spectate your team, while you wait %2
+
+Your side has %1 respawn tickets at mission start.
+",f_param_respawnTickets,_str_deploy]]];
+
+// Set a variable so this won't be generated again by subsequent inits
+f_var_respawn_briefingDone = true;
\ No newline at end of file
diff --git a/f/respawn/fn_respawnKilled.sqf b/f/respawn/fn_respawnKilled.sqf
new file mode 100644
index 00000000..e05425aa
--- /dev/null
+++ b/f/respawn/fn_respawnKilled.sqf
@@ -0,0 +1,17 @@
+// FA3 - Respawn Module - Player Killed Event
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function is executed from the FA3 Respawn Template in description.ext and should not be used for other purposes.
+Example:
+onPlayerKilled = "f_fnc_respawnKilled";
+
+Arguments: as automatically passed to onPlayerKilled.sqf
+=========================== */
+
+private _unit = _this#0;
+_unit setVariable ["f_var_lastTeamColour",assignedTeam _unit,true];
+_unit setVariable ["f_var_unitTraits", getAllUnitTraits _unit, true];
+_unit spawn f_fnc_radioCheckChannels;
+sleep 3;
+_this spawn f_fnc_activateSpectator;
\ No newline at end of file
diff --git a/f/respawn/fn_respawnTerminalAction.sqf b/f/respawn/fn_respawnTerminalAction.sqf
new file mode 100644
index 00000000..918cd83b
--- /dev/null
+++ b/f/respawn/fn_respawnTerminalAction.sqf
@@ -0,0 +1,55 @@
+// FA3 - Respawn Module - Terminal Action
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+
+/* ========================
+This function is executed from init.sqf.
+Two objects must be defined as global variables in the mission for this function to operate: f_respawnTerminal, an object which players can interact with to teleport and spectate; and f_respawnBase, a proxy object which is used as their spawn position upon respawning.
+Example:
+0 spawn f_fnc_terminalAction
+
+Arguments:
+None
+=========================== */
+if (isNil "f_respawnTerminal") exitWith {
+ systemChat "FA3 Respawn: Critical: Respawn Terminal object is not present or not correctly named f_respawnTerminal.";
+};
+if (isNil "f_respawnBase") exitWith {
+ systemChat "FA3 Respawn: Critical: Respawn Base object is not present or not correctly named f_respawnBase.";
+};
+
+[
+ f_respawnTerminal,
+ "Spectate your team",
+ "a3\ui_f\data\igui\cfg\holdactions\holdaction_search_ca.paa",
+ "a3\ui_f\data\igui\cfg\holdactions\holdaction_search_ca.paa",
+ "isNull objectParent _this",
+ "isNull objectParent _this",
+ {
+ private _text = format ["[%1] Launching side spectator. Press ESC to exit spectator.", str side group _caller];
+ systemChat _text;
+ },
+ {},
+ {
+ _caller spawn {
+ private _text = format ["[%1] Launched side spectator. Press ESC to exit spectator. Select units in the left panel to spectate.", str side group _this];
+ systemChat _text;
+ call f_fnc_activateSpectator;
+ waitUntil { !isNull findDisplay 60492 };
+ (findDisplay 60492) displayAddEventHandler ["keyDown",{
+ params ["", "_key"];
+ if (_key == 1) then {
+ (findDisplay 60492) displayRemoveEventHandler [_thisEvent,_thisEventHandler];
+ call f_fnc_terminateSpectator;
+ true;
+ };
+ }];
+ };
+ },
+ {},
+ [],
+ 2,
+ 0,
+ false,
+ false,
+ true
+] call BIS_fnc_holdActionAdd;
\ No newline at end of file
diff --git a/f/spect/fn_activateSpectator.sqf b/f/spect/fn_activateSpectator.sqf
index d64b86d5..865fcac5 100644
--- a/f/spect/fn_activateSpectator.sqf
+++ b/f/spect/fn_activateSpectator.sqf
@@ -1,23 +1,30 @@
// FA3 - Spectator component
if (f_param_debugMode == 1) then {
- diag_log "activating spectator";
+ diag_log "FA3 Spectator: activating spectator";
};
-// 'Cinematic' delay before spectator activates
-sleep 3;
+params ["","","","",["_isFullSpectator",false]];
// Disable post-processing effects
// Borrowed from BIS_fnc_respawnSpectator
- waitUntil {missionnamespace getvariable ["BIS_fnc_feedback_allowDeathScreen", true]};
-BIS_fnc_feedback_allowPP = false;
+if ((0 call BIS_fnc_missionRespawnType) == 1) then {
+ waitUntil {missionnamespace getvariable ["BIS_fnc_feedback_allowDeathScreen", true]};
+ BIS_fnc_feedback_allowPP = false;
+};
-// Create a new (alive) unit to prevent draw3D bug with floating head tags
-// Credit to SilentSpike: https://github.com/acemod/ACE3/pull/5868
-private _cameraUnit = (createGroup sideLogic) createUnit ["VirtualMan_F", player, [], 0, "NONE"];
-_cameraUnit enableSimulation false;
-selectPlayer _cameraUnit;
+if (_isFullSpectator or (!(alive player) && ([side group player] call BIS_fnc_respawnTickets) < 1)) then {
+ // Create a new (alive) unit to prevent draw3D bug with floating head tags
+ // Credit to SilentSpike: https://github.com/acemod/ACE3/pull/5868
+ private _cameraUnit = (createGroup sideLogic) createUnit ["VirtualMan_F", player, [], 0, "NONE"];
+ _cameraUnit enableSimulation false;
+ selectPlayer _cameraUnit;
-["Initialize", [player, [], true, true, true, false, true, true, true, true]] call BIS_fnc_EGSpectator;
+ ["Initialize", [player, [], true, true, true, false, true, true, true, true]] call BIS_fnc_EGSpectator;
+
+} else {
+ ["Initialize", [player, [side group player], false, false, false, false, false, true, true, true]] call BIS_fnc_EGSpectator;
+
+};
// Disable direct chat to prevent ghosts interacting with the living
5 enableChannel false;
\ No newline at end of file
diff --git a/init.sqf b/init.sqf
index d7301774..a7f9324d 100644
--- a/init.sqf
+++ b/init.sqf
@@ -172,6 +172,18 @@ f_var_viewDistance_crewOnly = true;
// ====================================================================================
+// FA3 - Respawn
+// Credits and documentation: https://github.com/folkarps/F3/wiki
+if isServer then {
+ {
+ [_x, f_param_respawnTickets] call BIS_fnc_respawnTickets;
+ } forEach [east, west, independent, civilian];
+};
+0 spawn f_fnc_respawnBriefing; // 0 - deployable beacons, 1 - teleport to vehicle, 2 - wait for pickup
+0 spawn f_fnc_respawnTerminalAction;
+
+// ====================================================================================
+
// FA3 - Skulls
// Credits and documentation: https://github.com/folkarps/F3/wiki