Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

365 FCS system #366

Merged
merged 21 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions f/brakeOverride/fn_brakeOverride.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// F3 - Driver's Brake Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
/*
This component allows players to disable the automatic brakes of any ground vehicle they're driving. It is enabled by default in init.sqf.
*/

// Don't add the action if it's already got one
if (player getVariable ["f_var_hasDriverAction",false]) exitWith { diag_log "brakeOverride: tried to add driver action on something that already has it"};

// Add the action
player addAction [
"Disable automatic brakes (brake to re-engage)",
{
params ["_target", "_caller", "_actionId", "_arguments"];
[vehicle _target,true] remoteExec ["disableBrakes",vehicle _target];
},
"",
10,
false,
true,
"",
"(driver (vehicle _this) == _this) && {(!brakesDisabled vehicle _this) && ((vehicle _this) isKindOf 'LandVehicle') && !((vehicle _this) isKindOf 'StaticWeapon')}"
];

// Add the variable to prove it's already done
player setVariable ["f_var_hasDriverAction",true];
2 changes: 2 additions & 0 deletions f/disableThermals/fn_disableThermals.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ if (isServer) then {
// This is an allowed vehicle, ignore it
} else {
_vehicleToCheck disableTIEquipment true;
_vehicleToCheck setVariable ["f_var_TIDisabled",true,true];
}
} foreach vehicles;
};
Expand All @@ -49,6 +50,7 @@ if (hasinterface && isNil "f_eh_disableThermals") then {

if ({_assembled isKindOf _x} count f_var_disableThermals_allowedTypes == 0) then {
_assembled disableTIEquipment true;
_vehicleToCheck setVariable ["f_var_TIDisabled",true,true];
}
}];
};
28 changes: 28 additions & 0 deletions f/fcs/fn_fcsBriefing.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// F3 - FCS Component Briefing Generator
// Credits and documentation: https://github.com/folkarps/F3/wiki
/*
This function generates a briefing tab describing the operation of the F3 FCS. It is called from f_fnc_fcsInit, if the tab has not already been generated by a previous call.
*/
// ====================================================================================

if (!hasInterface) exitWith {}; // Exit if not a player.

_fcs = player createDiaryRecord ["diary", ["F3 Enhanced FCS","
<br/>
Some vehicles in this mission are fitted with enhanced fire control systems. This adds some extra functionality relating to gunnery and targeting.
<br/><br/>
<font size='18'>COMMANDER'S OVERRIDE</font>
<br/>
The enhanced FCS allows the commander to automatically point the main gun at a target of their choosing. When the commander selects the Commander's Override from the action menu, the main gun will automatically traverse and elevate until it is pointing at the centre of the targeted object.
<br/>
The commander must be aiming directly at an object to activate the override. Open ground or sky won't work. There must also be a gunner present for the override to work. The override will engage for a maximum of 4 seconds before releasing control.
<br/><br/>
<font size='18'>FCS DAMAGE</font>
<br/>
When the vehicle is struck by high-calibre weapons, there's a chance the FCS will suffer damage. If the FCS is damaged, the Commander's Override will be disabled, as well as the gun zeroing and auto-leading functions and all night vision equipment.
<br/>
The FCS can be repaired by a player with engineering training (for example, an F3 vehicle driver) when they are in the gunner's seat.
"]];

// Set a variable so this won't be generated again by subsequent inits
f_var_fcs_briefingDone = true;
24 changes: 24 additions & 0 deletions f/fcs/fn_fcsCommanderOverride.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// F3 - FCS/Commander's Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
// Originally from: https://github.com/NikkoJT/njt_fcs (integrated with permission)

// This function is called when the commander issues a TC override from the action defined in fcs_init

params ["_vehicle","_caller"];

// If there's no valid target under the commander's crosshair, tell them and do nothing else
if (isNull cursorObject) then {
["NO TARGET",1] remoteExec ["f_fnc_fcsLocalWarning",commander _vehicle];
} else {
// Get the position of the centre of the targeted object at the time of the override
_overrideTarget = (cursorObject modelToWorldWorld (boundingCenter cursorObject));
// Order the gunner to aim their camera at the target position
[_vehicle,[_overrideTarget,_vehicle unitTurret (gunner _vehicle),true]] remoteExec ["lockCameraTo",gunner _vehicle];
// Display a HUD indicator for the gunner
["TC OVERRIDE",2] remoteExec ["f_fnc_fcsLocalWarning",gunner _vehicle];
// Handle cooldown on override
_vehicle setVariable ["f_var_fcsCommanderOverride_cooldown",true,true];
sleep 4;
[_vehicle,[objNull,_vehicle unitTurret (gunner _vehicle),true]] remoteExec ["lockCameraTo",gunner _vehicle];
_vehicle setVariable ["f_var_fcsCommanderOverride_cooldown",false,true];
};
42 changes: 42 additions & 0 deletions f/fcs/fn_fcsFailure.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// F3 - FCS/Commander's Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
// Originally from: https://github.com/NikkoJT/njt_fcs (integrated with permission)

// This function is used in the Hit EH defined in fcs_init. It determines whether a given hit causes an FCS failure.

params ["_target","_projectile","_isDirect"];

private _projectileClass = "";
private _warheadType = "";
private _randomNumber = 0;

if (_target getVariable ["f_var_fcs_failure",false]) exitWith {
// diag_log "FCS: target already has an FCS failure"
};

// Determine whether the projectile is an anti-tank weapon
_projectileClass = typeOf _projectile;
if !(_projectileClass isKindOf ["Default",configFile >> "CfgAmmo"]) exitWith {
//diag_log "FCS: hit by something other than a weapon"
};
_warheadType = (configProperties [configFile >> "CfgAmmo" >> _projectileClass >> "warheadName"]) select 0;
if !(_warheadType in ["AP","HEAT","TandemHEAT"]) exitWith {
// diag_log "FCS: projectile not HEAT or AP"
};
if !(_isDirect) exitWith {
// diag_log "FCS: splash damage only"
};

// 5% of qualifying hits should trigger this
_randomNumber = floor (random 20);
if !(_randomNumber == 10) exitWith {
// diag_log "FCS: projectile not randomly selected"
};

// Hit turns off the NV and TI and sets an appropriate variable on the vehicle. Hopefully later it will also turn off stabilisation (BI blocked)
_target disableNVGEquipment true;
_target disableTIEquipment true;
_target setVariable ["f_var_fcs_failure",true,true];

// Spawn ongoing stuff that affects the vehicle until repaired
[_target] spawn f_fnc_fcsPersistentEffects;
110 changes: 110 additions & 0 deletions f/fcs/fn_fcsInit.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// F3 - FCS/Commander's Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
// Originally from: https://github.com/NikkoJT/njt_fcs (integrated with permission)

/*
This component adds two main functions to a vehicle it's called on:
1. Commander's Override
The Commander's Override allows the commander to automatically point the gun at whatever object they're looking at.
2. FCS failure simulation
When the vehicle is hit by a high-calibre weapon, there is a small chance of an FCS failure, disabling the TC override, laser rangefinder, and NVDs, and force-setting the gunner's zeroing.
A unit with the repair trait can reset the FCS from the gunner's seat.
(If and when BI adds the ability to disable turret stabilisation by script, it will do that too)

Execution, all clients:
[_vehicle] call f_fnc_fcsInit;

Or example (warning: classnames are case sensitive):
_fcsvehicles = vehicles select {typeOf _x in ["I_APC_Wheeled_03_cannon_F","I_APC_tracked_03_cannon_F"]};
{[_x] call f_fnc_fcsInit} forEach _fcsvehicles;

An option to activate this component is pre-placed in the F3 init.sqf

*/

// Doesn't need to run on DS or HC
if !(hasInterface) exitWith {};

params ["_vehicle"];

if !(_vehicle isKindOf "LandVehicle") exitWith { diag_log "FCS: tried to run on something that isn't a vehicle" };

if (_vehicle getVariable ["f_var_fcs_hasEH",false]) exitWith { diag_log "FCS: tried to run on something that already has FCS set up"};

// If the FCS briefing tab hasn't been added already, add it.
if (isNil "f_var_fcs_briefingDone") then {
[] call f_fnc_fcsBriefing;
};

// Commander's override action
_vehicle addAction
[
"Commander's override",
{
params ["_target", "_caller", "_actionId", "_arguments"];
[_target,_caller] call f_fnc_fcsCommanderOverride;
},
nil,
1.5,
false,
true,
"",
"(_this == commander _target) && {!(isNull gunner _target) && !(_target getVariable [""f_var_fcsCommanderOverride_cooldown"",false]) && !(_target getVariable [""f_var_fcs_failure"",false])}",
0,
false,
"",
""
];


// Hit EH for FCS failure
_vehicle addEventHandler ["HitPart",{
(_this select 0) params ["_target", "_shooter", "_projectile", "_position", "_velocity", "_selection", "_ammo", "_vector", "_radius", "_surfaceType", "_isDirect"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is a direct hit (isDirect == true), will it always be the first element in _this? Otherwise, shouldn't this loop through each of the parts hit (the sub-arrays of _this) to check if any are direct hits?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm checking on this to be sure, but in testing the observed trigger rate seems to be appropriate for the initial impact being first, or at least a direct hit being first enough of the time to be in the right ballpark.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. If it seems to be having the desired effect then no issue

// Call the actual failure evaluator
[_target,_projectile,_isDirect] call f_fnc_fcsFailure;
}];

_vehicle setVariable ["f_var_fcs_hasEH",true];

// Hold action to repair FCS failure
// Players with repair trait in the gunner's seat of a vehicle with failed stabiliser can repair it
[
_vehicle, // Target
"Reset Fire Control System", // Title
"\a3\ui_f_oldman\data\IGUI\Cfg\holdactions\repair_ca.paa", // Idle icon
"\a3\ui_f_oldman\data\IGUI\Cfg\holdactions\repair_ca.paa", // Progress icon
"(_target getVariable [""f_var_fcs_failure"",false]) && (gunner _target == _this) && (_this getUnitTrait ""engineer"")", // Condition to show
"(_target getVariable [""f_var_fcs_failure"",false]) && (gunner _target == _this) && (_this getUnitTrait ""engineer"")", // Condition to progress
{}, // Code on start
{}, // Code on tick
{
params ["_target", "_caller", "_actionId", "_arguments"];
// Clear failure states
_target setVariable ["f_var_fcs_failure",false,true];
_target disableNVGEquipment false;
// Re-enable TI unless F3 says we shouldn't
if !(_target getVariable ["f_var_TIDisabled",false]) then {
_target disableTIEquipment false;
};
}, // Code on completed
{}, // Code on interrupt
[], // Arguments to pass
10, // Duration
1, // Priority
false, // Remove on completion
false, // Show when unconscious
true // Show on screen
] call BIS_fnc_holdActionAdd;

// Action to prevent rangefinder use during FCS failure
_vehicle addAction ["FCS failure - repair required", // Title
{
hint "Someone familiar with maintenance can reset the FCS.";
}, // Code
"", // Arguments
10, // Priority
false, // Show window
true, // Hide on use
"gunElevAuto", // Shortcut
"(_this == gunner _target) && {_target getVariable [""f_var_fcs_failure"",false]}" // Condition
];
20 changes: 20 additions & 0 deletions f/fcs/fn_fcsLocalWarning.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// F3 - FCS/Commander's Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
// Originally from: https://github.com/NikkoJT/njt_fcs (integrated with permission)

// This function shows HUD indicators when the commander's override either lacks a target or is in operation.

params ["_text","_delay"];

disableSerialization;

if (cameraView == "GUNNER") then {
private _overrideWarningDisplay = findDisplay 46 ctrlCreate ["RscStructuredText", 4404];
_overrideWarningDisplay ctrlSetPosition [0.5, 0.7,0.5,0.5];
_overrideWarningDisplay ctrlSetStructuredText parseText ("<t shadow='0' size='1.1'>" + _text + "</t>");
_overrideWarningDisplay ctrlSetTextColor [1,0.1,0.1,1];
_overrideWarningDisplay ctrlSetFont "PuristaBold";
_overrideWarningDisplay ctrlCommit 0;
sleep _delay;
ctrlDelete _overrideWarningDisplay;
};
40 changes: 40 additions & 0 deletions f/fcs/fn_fcsPersistentEffects.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// F3 - FCS/Commander's Override system
// Credits and documentation: https://github.com/folkarps/F3/wiki
// Originally from: https://github.com/NikkoJT/njt_fcs (integrated with permission)

// This component handles the FCS failure symptoms, such as the HUD warning and zeroing overrides. It's launched when an FCS failure is determined by the Hit EH added in fcs_init.

params ["_target"];

// It's all a big loop
while {(_target getVariable ["f_var_fcs_failure",false]) && (alive _target)} do {

// Check whether there is a gunner
if !(isNull (gunner _target)) then {
_currentGunner = gunner _target;
{
// Get the muzzles for every weapon on the main turret and force set their zeroing
private _targetWeapon = _x;
private _targetWeaponMuzzles = getArray (configFile >> "CfgWeapons" >> _x >> "muzzles");
{
_targetMuzzle = _targetWeapon;
if !(_x == "this") then {
_targetMuzzle = _x;
};
_zeroCheck = _currentGunner setWeaponZeroing [_targetWeapon,_targetMuzzle,1];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is setWeaponZeroing Global-Argument,Global-Effect?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wiki helpfully does not say. I think I remember testing it and having it work as expected on remote units, but I'll have to check again to prove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I saw the wiki didn't say which is why I asked. If you've tested previously it's probably fine

if !(_zeroCheck) then {
diag_log format ["FCS: Weapon zeroing failure for %1",_targetWeapon]
} else {
// diag_log format ["Zeroing set for %1",_targetWeapon]
};
} forEach _targetWeaponMuzzles;
} forEach (_target weaponsTurret [0]);

// Show a visual warning to the gunner - remoteExec'd to be local and only displayed when they are in the optics
["FCS FAILURE",0.5] remoteExec ["f_fnc_fcsLocalWarning",_currentGunner,false];

};

sleep 0.8;

};
14 changes: 14 additions & 0 deletions f/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@ class F // Defines the "owner"
file = "f\dynamicViewDistance";
class ehSetViewDistance {};
};
class fcs
{
file = "f\fcs";
class fcsInit{};
class fcsCommanderOverride{};
class fcsFailure{};
class fcsPersistentEffects{};
class fcsLocalWarning{};
class fcsBriefing{};
};
class brakeOverride
{
file = "f\brakeOverride";
class brakeOverride{};
class radio
{
file = "f\radio";
Expand Down
18 changes: 16 additions & 2 deletions init.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ f_var_viewDistance_crewOnly = true;

// ====================================================================================

// F3 - Commander's Override and FCS failure
// Credits and documentation: https://github.com/folkarps/F3/wiki

// [vehicleName] call f_fnc_fcsInit;
// { _x call f_fnc_fcsInit; } forEach [vehicle1,vehicle2,vehicle3];

// ====================================================================================

// F3 - Driver's Brake Override
// Credits and documentation: https://github.com/folkarps/F3/wiki

[] spawn f_fnc_brakeOverride;

// ====================================================================================

// F3 - MapClick Teleport
// Credits and documentation: https://github.com/folkarps/F3/wiki

Expand Down Expand Up @@ -219,8 +234,6 @@ f_var_viewDistance_crewOnly = true;

// ====================================================================================

// ====================================================================================

// F3 - Radio Channels
// Credits and documentation: https://github.com/folkarps/F3/wiki
// True to split channels by radio backpack type. Else one channel for all.
Expand All @@ -236,3 +249,4 @@ f_var_viewDistance_crewOnly = true;
// waitUntil {(!isNil f_var_radioChannelsUnified)}

// ====================================================================================