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

Common - Improve persistent lights/lasers #10118

Merged
merged 7 commits into from
Aug 8, 2024
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
1 change: 1 addition & 0 deletions addons/common/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ PREP(setupLocalUnitsHandler);
PREP(setVariableJIP);
PREP(setVariablePublic);
PREP(setVolume);
PREP(setWeaponLightLaserState);
PREP(showHud);
PREP(statusEffect_addType);
PREP(statusEffect_get);
Expand Down
59 changes: 59 additions & 0 deletions addons/common/functions/fnc_setWeaponLightLaserState.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "..\script_component.hpp"
/*
* Author: johnb43
* Toggles the unit's current weapon's light & laser.
* API for persistent lasers. Doesn't work on AI, as they have their own logic.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Weapon light/laser state <BOOL> (default: false)
*
* Return Value:
* None
*
* Example:
* [player, true] call ace_common_fnc_setWeaponLightLaserState
*
* Public: Yes
*/

params [["_unit", objNull, [objNull]], ["_state", false, [false]]];

if (!local _unit || {!alive _unit} || {!(_unit call FUNC(isPlayer))}) exitWith {};

if !(_unit call CBA_fnc_canUseWeapon) exitWith {};

private _currentWeapon = currentWeapon _unit;

// Exit if unit has no weapon selected
if (_currentWeapon == "") exitWith {};

private _weaponIndex = [_unit, _currentWeapon] call FUNC(getWeaponIndex);

// Ignore binoculars
if (_weaponIndex == -1) exitWith {};

_unit setVariable [QGVAR(laserEnabled_) + str _weaponIndex, _state];

// Turn off light/laser (switching between weapons can leave previous weapon laser on)
action ["GunLightOff", _unit];
action ["IRLaserOff", _unit];

// Light/laser is off, don't need to do anything more
if (!_state) exitWith {};

// Turn laser on next frame (if weapon hasn't changed)
[{
params ["_unit", "_currentWeapon"];

private _weaponState = (weaponState _unit) select [0, 3];

if (_weaponState select 0 != _currentWeapon) exitWith {};

action ["GunLightOn", _unit];
action ["IRLaserOn", _unit];

_unit selectWeapon _weaponState;
}, [_unit, _currentWeapon]] call CBA_fnc_execNextFrame;

nil
108 changes: 71 additions & 37 deletions addons/common/functions/fnc_switchPersistentLaser.sqf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "..\script_component.hpp"
/*
* Author: Dystopian
* Author: Dystopian, johnb43
* Controls persistent laser state.
*
* Arguments:
Expand All @@ -17,51 +17,85 @@

params ["_enabled"];

if (!hasInterface) exitwith {};

// Reset state
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
{
ACE_player setVariable [QGVAR(laserEnabled_) + str _x, nil];
} forEach [0, 1, 2];

if (!_enabled) exitWith {
if (isNil QGVAR(laserKeyDownEH)) exitWith {};
["KeyDown", GVAR(laserKeyDownEH)] call CBA_fnc_removeDisplayHandler;

removeUserActionEventHandler ["headlights", "Activate", GVAR(laserKeyDownEH)];

["loadout", GVAR(laserLoadoutEH)] call CBA_fnc_removePlayerEventHandler;
["turret", GVAR(laserTurretEH)] call CBA_fnc_removePlayerEventHandler;
["vehicle", GVAR(laserVehicleEH)] call CBA_fnc_removePlayerEventHandler;
["weapon", GVAR(laserWeaponEH)] call CBA_fnc_removePlayerEventHandler;

GVAR(laserKeyDownEH) = nil;
GVAR(laserLoadoutEH) = nil;
GVAR(laserTurretEH) = nil;
GVAR(laserVehicleEH) = nil;
GVAR(laserWeaponEH) = nil;
};

GVAR(laserKeyDownEH) = ["KeyDown", {
if !((_this select 1) in actionKeys "headlights") exitWith {false};
private _weapon = currentWeapon ACE_player;
private _fnc_getLightLaserState = {
private _currentWeapon = currentWeapon ACE_player;

if (_currentWeapon == "") exitWith {};

// Ignore in vehicle except FFV
if !(ACE_player call CBA_fnc_canUseWeapon) exitWith {};

private _weaponIndex = [ACE_player, _currentWeapon] call FUNC(getWeaponIndex);

if (_weaponIndex == -1) exitWith {};

// Light/laser state only changes in the next frame
[{
ACE_player setVariable [
QGVAR(laserEnabled_) + str (_this select 1),
ACE_player isIRLaserOn (_this select 0) || {ACE_player isFlashlightOn (_this select 0)}
];
}, [_currentWeapon, _weaponIndex]] call CBA_fnc_execNextFrame;
};

// Get current weapon light/laser state
call _fnc_getLightLaserState;

// Update state every time it's changed
GVAR(laserKeyDownEH) = addUserActionEventHandler ["headlights", "Activate", _fnc_getLightLaserState];

// Dropping weapons turns off lights/lasers
GVAR(lastWeapons) = [primaryWeapon ACE_player, handgunWeapon ACE_player, secondaryWeapon ACE_player];

// Monitor weapon addition/removal here
GVAR(laserLoadoutEH) = ["loadout", {
params ["_unit"];

private _weapons = [primaryWeapon _unit, handgunWeapon _unit, secondaryWeapon _unit];

if (_weapons isEqualTo GVAR(lastWeapons)) exitWith {};

GVAR(lastWeapons) = _weapons;

[
{
params ["_weapon", "_laserWasEnabled"];
private _laserEnabled = ACE_player isIRLaserOn _weapon || {ACE_player isFlashlightOn _weapon};
if (_laserEnabled && {_laserWasEnabled} || {!_laserEnabled && {!_laserWasEnabled}}) exitWith {};
private _weaponIndex = [ACE_player, _weapon] call FUNC(getWeaponIndex);
ACE_player setVariable [QGVAR(laserEnabled_) + str _weaponIndex, [nil, true] select _laserEnabled];
},
[_weapon, ACE_player isIRLaserOn _weapon || {ACE_player isFlashlightOn _weapon}]
] call CBA_fnc_execNextFrame;
false
}] call CBA_fnc_addDisplayHandler;

private _laserEH = {
if (sunOrMoon == 1) exitWith {};
params ["_player"];
private _weaponIndex = [_player, currentWeapon _player] call FUNC(getWeaponIndex);
if (
!(_player getVariable [QGVAR(laserEnabled_) + str _weaponIndex, false])
|| {_weaponIndex > 0 && {"" != primaryWeapon _player}} // Arma switches to primary weapon if exists
|| {!(_player call CBA_fnc_canUseWeapon)} // ignore in vehicle except FFV
) exitWith {};
_unit,
_unit getVariable [QGVAR(laserEnabled_) + str ([_unit, currentWeapon _unit] call FUNC(getWeaponIndex)), false]
] call FUNC(setWeaponLightLaserState);
}] call CBA_fnc_addPlayerEventHandler;

private _fnc_switchPersistentLaserEH = {
params ["_unit"];

[
// wait for weapon in "ready to fire" direction
{0.01 > getCameraViewDirection _this vectorDistance (_this weaponDirection currentWeapon _this)},
{{_this action [_x, _this]} forEach ["GunLightOn", "IRLaserOn"]},
_player,
3,
{{_this action [_x, _this]} forEach ["GunLightOn", "IRLaserOn"]}
] call CBA_fnc_waitUntilAndExecute;
_unit,
_unit getVariable [QGVAR(laserEnabled_) + str ([_unit, currentWeapon _unit] call FUNC(getWeaponIndex)), false]
] call FUNC(setWeaponLightLaserState);
};

GVAR(laserLoadoutEH) = ["loadout", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserTurretEH) = ["turret", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserVehicleEH) = ["vehicle", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserWeaponEH) = ["weapon", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserTurretEH) = ["turret", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserVehicleEH) = ["vehicle", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserWeaponEH) = ["weapon", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;