mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Rename Advanced Throwing component to be in-line with other advanced_ components (#4318)
* Rename Advanced Throwing component to be in-line with other advanced_ components * Rename wiki page as well * Add redirect from old wiki page
This commit is contained in:
31
addons/advanced_throwing/functions/fnc_canPrepare.sqf
Normal file
31
addons/advanced_throwing/functions/fnc_canPrepare.sqf
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Author: Jonpas
|
||||
* Checks if a throwable can be prepared.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Can Prepare <BOOL>
|
||||
*
|
||||
* Example:
|
||||
* [unit] call ace_advanced_throwing_fnc_canPrepare
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
GVAR(enabled) &&
|
||||
|
||||
#ifndef DEBUG_MODE_FULL
|
||||
{_unit getVariable [QGVAR(lastThrownTime), CBA_missionTime - 3] < CBA_missionTime - 2} && // Prevent throwing in quick succession
|
||||
#else
|
||||
{true} &&
|
||||
#endif
|
||||
|
||||
{!(call EFUNC(common,isFeatureCameraActive))} &&
|
||||
{!EGVAR(common,isReloading)} &&
|
||||
{[_unit, objNull, ["isNotInside", "isNotSitting"/*, "isNotOnLadder"*/]] call EFUNC(common,canInteractWith)} && // Ladder needs positioning fixes on throw
|
||||
{_unit call CBA_fnc_canUseWeapon} // Disable in non-FFV seats due to surface detection issues
|
31
addons/advanced_throwing/functions/fnc_canThrow.sqf
Normal file
31
addons/advanced_throwing/functions/fnc_canThrow.sqf
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Author: Jonpas
|
||||
* Checks if a throwable can be thrown.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Can Throw <BOOL>
|
||||
*
|
||||
* Example:
|
||||
* [unit] call ace_advanced_throwing_fnc_canThrow
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
if !(_unit getVariable [QGVAR(inHand), false]) exitWith {false};
|
||||
|
||||
if (vehicle _unit != _unit) exitWith {
|
||||
private _startPos = eyePos _unit;
|
||||
private _aimLinePos = AGLToASL (positionCameraToWorld [0, 0, 1]);
|
||||
private _intersections = lineIntersectsSurfaces [_startPos, _aimLinePos, _unit, objNull, false];
|
||||
//TRACE_1("Intersections",_intersections);
|
||||
|
||||
(_intersections select {(vehicle _unit) in (_x select 3)}) isEqualTo []
|
||||
};
|
||||
|
||||
true
|
88
addons/advanced_throwing/functions/fnc_drawArc.sqf
Normal file
88
addons/advanced_throwing/functions/fnc_drawArc.sqf
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Author: Zapat, Dslyecxi, Jonpas
|
||||
* Draws throw arc.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* Flight path (just for debug) <ARRAY>
|
||||
*
|
||||
* Example:
|
||||
* call ace_advanced_throwing_fnc_drawArc
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Disable drawing when intersecting with the vehicle
|
||||
if !([ACE_player] call FUNC(canThrow)) exitWith {
|
||||
drawIcon3D ["\a3\ui_f\data\igui\cfg\actions\obsolete\ui_action_cancel_manualfire_ca.paa", [1, 0, 0, 1], positionCameraToWorld [0, 0, 1], 1, 1, 0, "", 1];
|
||||
};
|
||||
|
||||
private _activeThrowable = ACE_player getVariable [QGVAR(activeThrowable), objNull];
|
||||
|
||||
// Exit during switches and similar where object can be null for a very short amount of time
|
||||
if (isNull _activeThrowable) exitWith {};
|
||||
|
||||
private _dropMode = ACE_player getVariable [QGVAR(dropMode), false];
|
||||
private _throwType = ACE_player getVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
|
||||
private _throwSpeed = ACE_player getVariable [QGVAR(throwSpeed), THROW_SPEED_DEFAULT];
|
||||
|
||||
private _direction = [THROWSTYLE_NORMAL_DIR, THROWSTYLE_HIGH_DIR] select (_throwType == "high" || {_dropMode});
|
||||
private _velocity = [_throwSpeed, _throwSpeed / THROWSTYLE_HIGH_VEL_COEF / 1.25] select (_throwType == "high");
|
||||
_velocity = [_velocity, THROWSTYLE_DROP_VEL] select _dropMode;
|
||||
|
||||
private _viewStart = AGLToASL (positionCameraToWorld [0, 0, 0]);
|
||||
private _viewEnd = AGLToASL (positionCameraToWorld _direction);
|
||||
|
||||
private _initialVelocity = (vectorNormalized (_viewEnd vectorDiff _viewStart)) vectorMultiply (_velocity);
|
||||
private _prevTrajASL = getPosASLVisual _activeThrowable;
|
||||
|
||||
private _pathData = [];
|
||||
|
||||
for "_i" from 0.05 to 1.45 step 0.1 do {
|
||||
private _newTrajASL = (getPosASLVisual _activeThrowable) vectorAdd (_initialVelocity vectorMultiply _i) vectorAdd ([0, 0, -4.9] vectorMultiply (_i * _i));
|
||||
private _cross = 0;
|
||||
|
||||
if (_newTrajASL distance (getPosASLVisual ACE_player) <= 20) then {
|
||||
if ((ASLToATL _newTrajASL) select 2 <= 0) then {
|
||||
_cross = 1
|
||||
} else {
|
||||
// Even vanilla throwables go through glass, only "GEOM" LOD will stop it but that will also stop it when there is glass in a window
|
||||
if (lineIntersects [_prevTrajASL, _newTrajASL]) then {
|
||||
_cross = 2;
|
||||
};
|
||||
};
|
||||
|
||||
private _iDim = linearConversion [20, 0, _newTrajASL distance (getPosASLVisual ACE_player), 0.3, 2.5, true];
|
||||
private _alpha = linearConversion [20, 0, _newTrajASL distance (getPosASLVisual ACE_player), 0.05, 0.7, true];
|
||||
private _movePerc = linearConversion [3, 0, vectorMagnitude (velocity ACE_player), 0, 1, true];
|
||||
_alpha = _alpha * _movePerc;
|
||||
|
||||
private _col = [ [1, 1, 1, _alpha], [0, 1, 0, _alpha], [1, 0, 0, _alpha] ] select _cross;
|
||||
|
||||
if (_cross != 2 && {lineIntersects [eyePos ACE_player, _newTrajASL]}) then {
|
||||
_col set [3, 0.1]
|
||||
};
|
||||
|
||||
_pathData pushBack [_col, ASLToAGL _newTrajASL, _iDim];
|
||||
};
|
||||
|
||||
if (_cross > 0) exitWith {};
|
||||
|
||||
_prevTrajASL = _newTrajASL;
|
||||
};
|
||||
|
||||
reverse _pathData;
|
||||
// To get the sort order correct from our POV, particularly when using outlined dots
|
||||
{
|
||||
_x params ["_col", "_newTrajAGL", "_iDim"];
|
||||
drawIcon3D ["\a3\ui_f\data\gui\cfg\hints\icon_text\group_1_ca.paa", _col, _newTrajAGL, _iDim, _iDim, 0, "", 2];
|
||||
|
||||
#ifdef DRAW_THROW_PATH
|
||||
drawIcon3D ["", _col, _newTrajAGL, _iDim, _iDim, 0, str (ACE_player distance _newTrajAGL), 2, 0.05, "RobotoCondensed"];
|
||||
#endif
|
||||
} forEach _pathData;
|
||||
|
||||
_pathData
|
140
addons/advanced_throwing/functions/fnc_drawThrowable.sqf
Normal file
140
addons/advanced_throwing/functions/fnc_drawThrowable.sqf
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas, SilentSpike
|
||||
* Handles drawing the currently selected or cooked throwable.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* call ace_advanced_throwing_fnc_drawThrowable
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if (dialog || {!(ACE_player getVariable [QGVAR(inHand), false])} || {!([ACE_player] call FUNC(canPrepare))}) exitWith {
|
||||
[ACE_player, "In dialog or no throwable in hand or cannot prepare throwable"] call FUNC(exitThrowMode);
|
||||
};
|
||||
|
||||
private _primed = ACE_player getVariable [QGVAR(primed), false];
|
||||
private _activeThrowable = ACE_player getVariable [QGVAR(activeThrowable), objNull];
|
||||
|
||||
// Exit if throwable died primed in hand
|
||||
if (isNull _activeThrowable && {_primed}) exitWith {
|
||||
[ACE_player, "Throwable died primed in hand"] call FUNC(exitThrowMode);
|
||||
};
|
||||
|
||||
private _throwable = currentThrowable ACE_player;
|
||||
|
||||
// Inventory check
|
||||
if (_throwable isEqualTo [] && {!_primed}) exitWith {
|
||||
[ACE_player, "No valid throwables"] call FUNC(exitThrowMode);
|
||||
};
|
||||
|
||||
private _throwableMag = _throwable param [0, "#none"];
|
||||
|
||||
// Get correct throw power for primed grenade
|
||||
if (_primed) then {
|
||||
private _ammoType = typeOf _activeThrowable;
|
||||
_throwableMag = GVAR(ammoMagLookup) getVariable _ammoType;
|
||||
if (isNil "_throwableMag") then {
|
||||
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
|
||||
// Just use HandGrenade as it has an average initSpeed value
|
||||
_throwableMag = "HandGrenade";
|
||||
};
|
||||
};
|
||||
|
||||
// Some throwables have different classname for magazine and ammo
|
||||
// Primed magazine may be different, read speed before checking primed magazine!
|
||||
private _throwSpeed = getNumber (configFile >> "CfgMagazines" >> _throwableMag >> "initSpeed");
|
||||
|
||||
// Reduce power of throw over shoulder and to sides
|
||||
private _unitDirVisual = getDirVisual ACE_player;
|
||||
private _cameraDir = getCameraViewDirection ACE_player;
|
||||
_cameraDir = (_cameraDir select 0) atan2 (_cameraDir select 1);
|
||||
|
||||
private _phi = abs (_cameraDir - _unitDirVisual) % 360;
|
||||
_phi = [_phi, 360 - _phi] select (_phi > 180);
|
||||
|
||||
private _power = linearConversion [0, 180, _phi - 30, 1, 0.3, true];
|
||||
ACE_player setVariable [QGVAR(throwSpeed), _throwSpeed * _power];
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
hintSilent format ["Heading: %1\nPower: %2\nSpeed: %3\nThrowMag: %4", _phi, _power, _throwSpeed * _power, _throwableMag];
|
||||
#endif
|
||||
|
||||
private _throwableType = getText (configFile >> "CfgMagazines" >> _throwableMag >> "ammo");
|
||||
|
||||
if (!([ACE_player] call FUNC(canThrow)) && {!_primed}) exitWith {
|
||||
if (!isNull _activeThrowable) then {
|
||||
deleteVehicle _activeThrowable;
|
||||
};
|
||||
};
|
||||
|
||||
if (isNull _activeThrowable || {(_throwableType != typeOf _activeThrowable) && {!_primed}}) then {
|
||||
if (!isNull _activeThrowable) then {
|
||||
deleteVehicle _activeThrowable;
|
||||
};
|
||||
_activeThrowable = _throwableType createVehicleLocal [0, 0, 0];
|
||||
_activeThrowable enableSimulation false;
|
||||
ACE_player setVariable [QGVAR(activeThrowable), _activeThrowable];
|
||||
};
|
||||
|
||||
// Exit in case of explosion in hand
|
||||
if (isNull _activeThrowable) exitWith {
|
||||
[ACE_player, "No active throwable (explosion in hand)"] call FUNC(exitThrowMode);
|
||||
};
|
||||
|
||||
// Exit if locality changed (someone took the throwable from hand)
|
||||
if (!local _activeThrowable && {ACE_player getVariable [QGVAR(localityChanged), true]}) exitWith {
|
||||
[ACE_player, "Throwable locality changed"] call FUNC(exitThrowMode);
|
||||
};
|
||||
|
||||
// Set position
|
||||
private _posHeadRel = ACE_player selectionPosition "head";
|
||||
|
||||
private _leanCoef = (_posHeadRel select 0) - 0.15; // 0.15 counters the base offset
|
||||
// Don't take leaning into account when weapon is lowered due to jiggling when walking side-ways (bandaid)
|
||||
if (abs _leanCoef < 0.15 || {vehicle ACE_player != ACE_player} || {weaponLowered ACE_player}) then {
|
||||
_leanCoef = 0;
|
||||
};
|
||||
|
||||
private _posCameraWorld = AGLToASL (positionCameraToWorld [0, 0, 0]);
|
||||
_posHeadRel = _posHeadRel vectorAdd [-0.03, 0.01, 0.15]; // Bring closer to eyePos value
|
||||
private _posFin = AGLToASL (ACE_player modelToWorldVisual _posHeadRel);
|
||||
|
||||
private _throwType = ACE_player getVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
|
||||
|
||||
// Orient it nicely, point towards player
|
||||
_activeThrowable setDir (_unitDirVisual + 90);
|
||||
|
||||
private _pitch = [-30, -90] select (_throwType == "high");
|
||||
[_activeThrowable, _pitch, 0] call BIS_fnc_setPitchBank;
|
||||
|
||||
|
||||
if (ACE_player getVariable [QGVAR(dropMode), false]) then {
|
||||
_posFin = _posFin vectorAdd (AGLToASL (positionCameraToWorld [_leanCoef, 0, ACE_player getVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT]]));
|
||||
|
||||
// Even vanilla throwables go through glass, only "GEOM" LOD will stop it but that will also stop it when there is no glass in a window
|
||||
if (lineIntersects [_posCameraWorld, _posFin vectorDiff _posCameraWorld]) then {
|
||||
ACE_player setVariable [QGVAR(dropDistance), ((ACE_player getVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT]) - 0.1) max DROP_DISTANCE_DEFAULT];
|
||||
};
|
||||
} else {
|
||||
private _xAdjustBonus = [0, -0.075] select (_throwType == "high");
|
||||
private _yAdjustBonus = [0, 0.1] select (_throwType == "high");
|
||||
private _cameraOffset = [_leanCoef, 0, 0.3] vectorAdd [-0.1, -0.15, -0.03] vectorAdd [_xAdjustBonus, _yAdjustBonus, 0];
|
||||
|
||||
_posFin = _posFin vectorAdd (AGLToASL (positionCameraToWorld _cameraOffset));
|
||||
|
||||
if (vehicle ACE_player != ACE_player) then {
|
||||
// Counteract vehicle velocity including acceleration
|
||||
private _vectorDiff = (velocity (vehicle ACE_player)) vectorMultiply (time - (ACE_player getVariable [QGVAR(lastTick), time]) + 0.01);
|
||||
_posFin = _posFin vectorAdd _vectorDiff;
|
||||
ACE_player setVariable [QGVAR(lastTick), time];
|
||||
};
|
||||
};
|
||||
|
||||
_activeThrowable setPosASL (_posFin vectorDiff _posCameraWorld);
|
50
addons/advanced_throwing/functions/fnc_exitThrowMode.sqf
Normal file
50
addons/advanced_throwing/functions/fnc_exitThrowMode.sqf
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Exits throw mode.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Reason <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [unit, "reason"] call ace_advanced_throwing_fnc_exitThrowMode
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_reason"];
|
||||
TRACE_2("params",_unit,_reason);
|
||||
|
||||
if !(_unit getVariable [QGVAR(inHand), false]) exitWith {};
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
systemChat format ["Exit Throw Mode: %1", _reason];
|
||||
#endif
|
||||
|
||||
if !(_unit getVariable [QGVAR(primed), false]) then {
|
||||
deleteVehicle (_unit getVariable [QGVAR(activeThrowable), objNull]);
|
||||
};
|
||||
|
||||
_unit setVariable [QGVAR(inHand), false];
|
||||
_unit setVariable [QGVAR(primed), false];
|
||||
_unit setVariable [QGVAR(activeThrowable), objNull];
|
||||
_unit setVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
|
||||
_unit setVariable [QGVAR(throwSpeed), THROW_SPEED_DEFAULT];
|
||||
_unit setVariable [QGVAR(dropMode), false];
|
||||
_unit setVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT];
|
||||
|
||||
// Remove controls hint (check if ever enabled is inside the function)
|
||||
call EFUNC(interaction,hideMouseHint);
|
||||
|
||||
// Remove throw action
|
||||
[_unit, "DefaultAction", _unit getVariable [QGVAR(throwAction), -1]] call EFUNC(common,removeActionEventHandler);
|
||||
|
||||
// Remove throw arc draw
|
||||
if (!isNil QGVAR(draw3DHandle)) then {
|
||||
removeMissionEventHandler ["Draw3D", GVAR(draw3DHandle)];
|
||||
GVAR(draw3DHandle) = nil;
|
||||
};
|
25
addons/advanced_throwing/functions/fnc_getMuzzle.sqf
Normal file
25
addons/advanced_throwing/functions/fnc_getMuzzle.sqf
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Retrieve muzzle name from config.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Magazine Classname <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* "magazine" call ace_advanced_throwing_fnc_getMuzzle
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_magazineClassname"];
|
||||
|
||||
_magazineClassname = toLower _magazineClassname;
|
||||
private _throwMuzzles = getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles");
|
||||
|
||||
_throwMuzzles = _throwMuzzles select {_magazineClassname in ((getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines")) apply {toLower _x})};
|
||||
|
||||
[_throwMuzzles select 0, ""] select (_throwMuzzles isEqualTo [])
|
33
addons/advanced_throwing/functions/fnc_moduleInit.sqf
Normal file
33
addons/advanced_throwing/functions/fnc_moduleInit.sqf
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Author: Jonpas
|
||||
* Initializes the Advanced Throwing module.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Logic <OBJECT>
|
||||
* 1: Synchronized Units <ARRAY>
|
||||
* 2: Module Activated <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [logic, [unit1, unit2], true] call ace_advanced_throwing_fnc_moduleInit
|
||||
*
|
||||
* Public:
|
||||
* No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if (!isServer) exitWith {};
|
||||
|
||||
params ["_logic", "_units", "_activated"];
|
||||
|
||||
if (!_activated) exitWith {};
|
||||
|
||||
[_logic, QGVAR(enabled), "enabled"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(showThrowArc), "showThrowArc"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(showMouseControls), "showMouseControls"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(enablePickUp), "enablePickUp"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(enablePickUpAttached), "enablePickUpAttached"] call EFUNC(common,readSettingFromModule);
|
||||
|
||||
ACE_LOGINFO_1("Advanced Throwing Module Initialized. Enabled: %1",GVAR(enabled));
|
45
addons/advanced_throwing/functions/fnc_onKeyDown.sqf
Normal file
45
addons/advanced_throwing/functions/fnc_onKeyDown.sqf
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Key down event.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Control <CONTROL>
|
||||
* 1: Key <NUMBER>
|
||||
* 2: Shift <BOOL>
|
||||
* 3: Ctrl <BOOL>
|
||||
* 4: Alt <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [control, 5, false, true, false] call ace_advanced_throwing_fnc_onKeyDown
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if !(ACE_player getVariable [QGVAR(inHand), false]) exitWith {false};
|
||||
|
||||
params ["", "_key", "_shift", "_ctrl", "_alt"];
|
||||
|
||||
// Exit if any of the action keys is pressed
|
||||
{
|
||||
if (_key in _x) exitWith {
|
||||
[ACE_player, "Pressed a key that cycles us out of throwables"] call FUNC(exitThrowMode);
|
||||
};
|
||||
} forEach [
|
||||
actionKeys "ReloadMagazine",
|
||||
actionKeys "Handgun",
|
||||
actionKeys "Binoculars",
|
||||
actionKeys "SwitchWeapon",
|
||||
actionKeys "Optics",
|
||||
actionKeys "NextWeapon",
|
||||
actionKeys "PrevWeapon",
|
||||
actionKeys "OpticsTemp",
|
||||
actionKeys "SwitchPrimary",
|
||||
actionKeys "SwitchHandgun",
|
||||
actionKeys "SwitchSecondary"
|
||||
];
|
||||
|
||||
false
|
46
addons/advanced_throwing/functions/fnc_onMouseButtonDown.sqf
Normal file
46
addons/advanced_throwing/functions/fnc_onMouseButtonDown.sqf
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Mouse button down event.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_advanced_throwing_fnc_onMouseButtonDown
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if !(ACE_player getVariable [QGVAR(inHand), false]) exitWith {};
|
||||
|
||||
params ["", "_key"];
|
||||
|
||||
// Left mouse button
|
||||
// "DefaultAction" doesn't get executed when in driver seat or in FFV seat with weapon lowered
|
||||
if (_key == 0) exitWith {
|
||||
if (!isNull (ACE_player getVariable [QGVAR(activeThrowable), objNull])) then {
|
||||
// Look gets automatically pointed at weapon direction on first LMB press when in FFV seat, require weapon to be up if in vehicle
|
||||
private _inVehicle = vehicle ACE_player != ACE_player;
|
||||
if (!_inVehicle || {_inVehicle && {!weaponLowered ACE_player}}) then {
|
||||
[ACE_player] call FUNC(throw);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
private _primed = ACE_player getVariable [QGVAR(primed), false];
|
||||
|
||||
// Right mouse button
|
||||
if (_key == 1) exitWith {
|
||||
if (!_primed) then {
|
||||
[ACE_player, "Storing throwable"] call FUNC(exitThrowMode);
|
||||
};
|
||||
};
|
||||
|
||||
// Middle mouse button
|
||||
if (_key == 2 && {!_primed}) exitWith {
|
||||
[ACE_player, true] call FUNC(prime);
|
||||
};
|
48
addons/advanced_throwing/functions/fnc_onMouseScroll.sqf
Normal file
48
addons/advanced_throwing/functions/fnc_onMouseScroll.sqf
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Mouse scroll wheel changed event.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_advanced_throwing_fnc_onMouseScroll
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if !(ACE_player getVariable [QGVAR(inHand), false]) exitWith {};
|
||||
|
||||
params ["", "_amount"];
|
||||
|
||||
if (ACE_player getVariable [QGVAR(dropMode), false]) then {
|
||||
private _dropDistance = ACE_player getVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT];
|
||||
if (_amount < 0) then {
|
||||
// Move closer
|
||||
ACE_player setVariable [QGVAR(dropDistance), (_dropDistance - 0.1) max DROP_DISTANCE_DEFAULT];
|
||||
} else {
|
||||
// Move further
|
||||
ACE_player setVariable [QGVAR(dropDistance), (_dropDistance + 0.1) min 1];
|
||||
};
|
||||
|
||||
// Limit distance in vehicle
|
||||
if (vehicle ACE_player != ACE_player) then {
|
||||
ACE_player setVariable [QGVAR(dropDistance), (ACE_player getVariable [QGVAR(dropDistance), DROP_DISTANCE_DEFAULT]) min 0.5];
|
||||
};
|
||||
} else {
|
||||
private _throwType = ACE_player getVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
|
||||
if (_amount < 0) then {
|
||||
if (_throwType == "high") then {
|
||||
ACE_player setVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
|
||||
};
|
||||
} else {
|
||||
if (_throwType == "normal") then {
|
||||
ACE_player setVariable [QGVAR(throwType), "high"];
|
||||
};
|
||||
};
|
||||
TRACE_2("Change Throw Type",_amount,ACE_player getVariable QGVAR(throwType));
|
||||
};
|
61
addons/advanced_throwing/functions/fnc_pickUp.sqf
Normal file
61
addons/advanced_throwing/functions/fnc_pickUp.sqf
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Author: Jonpas
|
||||
* Picks up a throwable from the ground.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Pick Up Helper <OBJECT>
|
||||
* 1: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [helper, player] call ace_advanced_throwing_fnc_pickUp
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_helper", "_unit"];
|
||||
TRACE_2("params",_helper,_unit);
|
||||
|
||||
private _activeThrowable = _helper getVariable [QGVAR(throwable), objNull];
|
||||
|
||||
if (isNull _activeThrowable) exitWith {TRACE_2("throwable is null",_helper,_activeThrowable);};
|
||||
|
||||
// Detach if attached (to vehicle for example or another player)
|
||||
private _attachedTo = attachedTo _activeThrowable;
|
||||
if (!isNull _attachedTo) then {
|
||||
private _attachedList = _attachedTo getVariable [QEGVAR(attach,attached), []];
|
||||
{
|
||||
_x params ["_xObject"];
|
||||
if (_activeThrowable == _xObject) exitWith {
|
||||
TRACE_2("removing from ace_attach",_attachedTo,_attachedList);
|
||||
_attachedList deleteAt _forEachIndex;
|
||||
_attachedTo setVariable [QEGVAR(attach,attached), _attachedList, true];
|
||||
};
|
||||
} forEach _attachedList;
|
||||
detach _activeThrowable;
|
||||
};
|
||||
|
||||
// Change locality for manipulation (some commands require local object, such as setVelocity)
|
||||
if (!local _activeThrowable) then {
|
||||
["ace_setOwner", [_activeThrowable, CBA_clientID]] call CBA_fnc_serverEvent;
|
||||
|
||||
// Mark when it's safe to exit throw mode (locality change has delay)
|
||||
_unit setVariable [QGVAR(localityChanged), false];
|
||||
[{
|
||||
// Becomes local or times out
|
||||
local (_this select 0) || {(_this select 1) + 5 < CBA_missionTime}
|
||||
}, {
|
||||
(_this select 2) setVariable [QGVAR(localityChanged), true];
|
||||
}, [_activeThrowable, CBA_missionTime, _unit]] call CBA_fnc_waitUntilAndExecute;
|
||||
};
|
||||
|
||||
// Invoke listenable event
|
||||
["ace_throwablePickedUp", [_activeThrowable, _unit, _attachedTo]] call CBA_fnc_localEvent;
|
||||
|
||||
_unit setVariable [QGVAR(primed), true];
|
||||
_unit setVariable [QGVAR(activeThrowable), _activeThrowable];
|
||||
|
||||
_unit call FUNC(prepare);
|
50
addons/advanced_throwing/functions/fnc_prepare.sqf
Normal file
50
addons/advanced_throwing/functions/fnc_prepare.sqf
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Prepares throwable or selects the next.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [unit] call ace_advanced_throwing_fnc_prepare
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
TRACE_1("params",_unit);
|
||||
|
||||
// Select next throwable if one already in hand
|
||||
if (_unit getVariable [QGVAR(inHand), false]) exitWith {
|
||||
TRACE_1("inHand",_unit);
|
||||
if (!(_unit getVariable [QGVAR(primed), false])) then {
|
||||
TRACE_1("not primed",_unit);
|
||||
[_unit] call EFUNC(weaponselect,selectNextGrenade);
|
||||
};
|
||||
};
|
||||
|
||||
// Try selecting next throwable if none currently selected
|
||||
if ((isNull (_unit getVariable [QGVAR(activeThrowable), objNull])) && {(currentThrowable _unit) isEqualTo []} && {!([_unit] call EFUNC(weaponselect,selectNextGrenade))}) exitWith {
|
||||
TRACE_1("no throwables",_unit);
|
||||
};
|
||||
|
||||
|
||||
_unit setVariable [QGVAR(inHand), true];
|
||||
|
||||
// Add controls hint
|
||||
call FUNC(updateControlsHint);
|
||||
|
||||
// Add throw action to suppress weapon firing (not possible to suppress mouseButtonDown event)
|
||||
_unit setVariable [QGVAR(throwAction), [_unit, "DefaultAction", {true}, {true}] call EFUNC(common,addActionEventHandler)];
|
||||
|
||||
// Draw throwable and throw arc if enabled
|
||||
GVAR(draw3DHandle) = addMissionEventHandler ["Draw3D", {
|
||||
call FUNC(drawThrowable);
|
||||
if (GVAR(showThrowArc)) then {
|
||||
call FUNC(drawArc);
|
||||
};
|
||||
}];
|
57
addons/advanced_throwing/functions/fnc_prime.sqf
Normal file
57
addons/advanced_throwing/functions/fnc_prime.sqf
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Primes the throwable, creates global throwable vehicle and throws Fired XEH.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Show Hint <BOOL> (default: false)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [unit] call ace_advanced_throwing_fnc_prime
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", ["_showHint", false]];
|
||||
TRACE_2("params",_unit,_showHint);
|
||||
|
||||
_unit setVariable [QGVAR(primed), true];
|
||||
|
||||
// Remove item before cooking to prevent weaponselect showing more throwables than there actually are in inventory
|
||||
private _throwableMag = (currentThrowable _unit) select 0;
|
||||
_unit removeItem _throwableMag;
|
||||
|
||||
private _throwableType = getText (configFile >> "CfgMagazines" >> _throwableMag >> "ammo");
|
||||
private _muzzle = _throwableMag call FUNC(getMuzzle);
|
||||
|
||||
// Create actual throwable globally
|
||||
private _activeThrowableOld = _unit getVariable [QGVAR(activeThrowable), objNull];
|
||||
private _activeThrowable = createVehicle [_throwableType, _activeThrowableOld, [], 0, "CAN_COLLIDE"];
|
||||
_unit setVariable [QGVAR(activeThrowable), _activeThrowable];
|
||||
deleteVehicle _activeThrowableOld;
|
||||
|
||||
// Throw Fired XEH
|
||||
[QGVAR(throwFiredXEH), [
|
||||
_unit, // unit
|
||||
"Throw", // weapon
|
||||
_muzzle, // muzzle
|
||||
_muzzle, // mode
|
||||
_throwableType, // ammo
|
||||
_throwableMag, // magazine
|
||||
_activeThrowable // projectile
|
||||
]] call CBA_fnc_globalEvent;
|
||||
|
||||
if (_showHint) then {
|
||||
// Show primed hint
|
||||
private _displayNameShort = getText (configFile >> "CfgMagazines" >> _throwableMag >> "displayNameShort");
|
||||
private _picture = getText (configFile >> "CfgMagazines" >> _throwableMag >> "picture");
|
||||
|
||||
[[_displayNameShort, localize LSTRING(Primed)] joinString " ", _picture] call EFUNC(common,displayTextPicture);
|
||||
|
||||
// Change controls hint for RMB
|
||||
call FUNC(updateControlsHint);
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Author: PabstMirror, Jonpas
|
||||
* When interact_menu starts rendering (from "interact_keyDown" event).
|
||||
* Add pick up helpers to all nearby throwables and keep setting them to their position (setVariable and attachTo does not work on CfgAmmo).
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* Nothing
|
||||
*
|
||||
* Example:
|
||||
* call ace_advanced_throwing_fnc_renderPickUpInteraction
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
[{
|
||||
params ["_args", "_idPFH"];
|
||||
_args params ["_setPosition", "_addedPickUpHelpers", "_throwablesHelped", "_nearThrowables"];
|
||||
|
||||
// isNull is necessarry to prevent rare error when ending mission with interact key down
|
||||
if (EGVAR(interact_menu,keyDown) && {!isNull ACE_player}) then {
|
||||
// Rescan when player moved >5 meters from last pos, nearObjects is costly
|
||||
if ((getPosASL ACE_player) distance _setPosition > 5) then {
|
||||
// IR throwbles inherit from GrenadeCore, others from GrenadeHand, IR Chemlights are special snowflakes
|
||||
_nearThrowables = ACE_player nearObjects ["GrenadeHand", PICK_UP_DISTANCE];
|
||||
_nearThrowables append (ACE_player nearObjects ["GrenadeCore", PICK_UP_DISTANCE]);
|
||||
_nearThrowables append (ACE_player nearObjects ["ACE_Chemlight_IR_Dummy", PICK_UP_DISTANCE]);
|
||||
|
||||
{
|
||||
if (!(_x in _throwablesHelped) && {GVAR(enablePickUpAttached) || {!GVAR(enablePickUpAttached) && {isNull (attachedTo _x)}}}) then {
|
||||
TRACE_2("Making PickUp Helper",_x,typeOf _x);
|
||||
private _pickUpHelper = QGVAR(pickUpHelper) createVehicleLocal [0, 0, 0];
|
||||
|
||||
_pickUpHelper attachTo [_x, [0, 0, 0]];
|
||||
_pickUpHelper setVariable [QGVAR(throwable), _x];
|
||||
|
||||
_addedPickUpHelpers pushBack _pickUpHelper;
|
||||
_throwablesHelped pushBack _x;
|
||||
};
|
||||
nil
|
||||
} count _nearThrowables;
|
||||
|
||||
_args set [0, getPosASL ACE_player];
|
||||
_args set [3, _nearThrowables];
|
||||
};
|
||||
|
||||
// Make sure helper is on correct location as it will not automatically move
|
||||
// attachTo is not supported with CfgAmmo, it is only used to get location
|
||||
{
|
||||
// Only handling with attachTo works nicely
|
||||
_x attachTo [_x getVariable [QGVAR(throwable), objNull], [0, 0, 0]];
|
||||
nil
|
||||
} count _addedPickUpHelpers;
|
||||
} else {
|
||||
TRACE_1("Cleaning Pick Up Helpers",count _addedPickUpHelpers);
|
||||
{deleteVehicle _x} count _addedPickUpHelpers;
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
}, 0, [(getPosASL ACE_player) vectorAdd [-100, 0, 0], [], [], []]] call CBA_fnc_addPerFrameHandler;
|
85
addons/advanced_throwing/functions/fnc_throw.sqf
Normal file
85
addons/advanced_throwing/functions/fnc_throw.sqf
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Author: Dslyecxi, Jonpas
|
||||
* Throw selected throwable.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* unit call ace_advanced_throwing_fnc_throw
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
TRACE_1("params",_unit);
|
||||
|
||||
// Prime the throwable if it hasn't been cooking already
|
||||
// Next to proper simulation this also has to happen before delay for orientation of the throwable to be set
|
||||
if (!(_unit getVariable [QGVAR(primed), false])) then {
|
||||
[_unit] call FUNC(prime);
|
||||
};
|
||||
|
||||
[_unit, "ThrowGrenade"] call EFUNC(common,doGesture);
|
||||
|
||||
// Pass position to reset later because animation may change it in certain stances
|
||||
[{
|
||||
params ["_unit", "_activeThrowable", "_posThrown", "_throwType", "_throwSpeed", "_dropMode"];
|
||||
TRACE_6("delayParams",_unit,_activeThrowable,_posThrown,_throwType,_throwSpeed,_dropMode);
|
||||
|
||||
// Reset position in case animation changed it
|
||||
_activeThrowable setPosASL _posThrown;
|
||||
|
||||
// Launch actual throwable
|
||||
private _direction = [THROWSTYLE_NORMAL_DIR, THROWSTYLE_HIGH_DIR] select (_throwType == "high" || {_dropMode});
|
||||
private _velocity = [_throwSpeed, _throwSpeed / THROWSTYLE_HIGH_VEL_COEF / 1.25] select (_throwType == "high");
|
||||
_velocity = [_velocity, THROWSTYLE_DROP_VEL] select _dropMode;
|
||||
|
||||
private _p2 = (eyePos _unit) vectorAdd (AGLToASL (positionCameraToWorld _direction)) vectorDiff (AGLToASL (positionCameraToWorld [0, 0, 0]));
|
||||
private _p1 = AGLtoASL (_activeThrowable modelToWorldVisual [0, 0, 0]);
|
||||
|
||||
private _newVelocity = (_p1 vectorFromTo _p2) vectorMultiply _velocity;
|
||||
|
||||
// Adjust for throwing from inside vehicles, where we have a vehicle-based velocity that can't be compensated for by a human
|
||||
if (vehicle _unit != _unit) then {
|
||||
_newVelocity = _newVelocity vectorAdd (velocity (vehicle _unit));
|
||||
};
|
||||
|
||||
// Drop if unit dies during throw process
|
||||
if (alive _unit) then {
|
||||
_activeThrowable setVelocity _newVelocity;
|
||||
};
|
||||
|
||||
_unit setVariable [QGVAR(lastThrownTime), CBA_missionTime];
|
||||
|
||||
// Invoke listenable event
|
||||
["ace_throwableThrown", [_unit, _activeThrowable]] call CBA_fnc_localEvent;
|
||||
}, [
|
||||
_unit,
|
||||
_unit getVariable [QGVAR(activeThrowable), objNull],
|
||||
getPosASLVisual (_unit getVariable [QGVAR(activeThrowable), objNull]),
|
||||
_unit getVariable [QGVAR(throwType), THROW_TYPE_DEFAULT],
|
||||
_unit getVariable [QGVAR(throwSpeed), THROW_SPEED_DEFAULT],
|
||||
_unit getVariable [QGVAR(dropMode), false]
|
||||
], 0.3] call CBA_fnc_waitAndExecute;
|
||||
|
||||
|
||||
#ifdef DRAW_THROW_PATH
|
||||
GVAR(predictedPath) = call FUNC(drawArc); // save the current throw arc
|
||||
GVAR(flightPath) = [];
|
||||
[_unit getVariable QGVAR(activeThrowable)] spawn {
|
||||
params ["_grenade"];
|
||||
while {!isNull _grenade} do {
|
||||
GVAR(flightPath) pushBack ASLtoAGL getPosASL _grenade;
|
||||
sleep 0.05;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// Stop rendering arc and doing rendering magic while throw is happening
|
||||
[_unit, "Completed a throw fully"] call FUNC(exitThrowMode);
|
28
addons/advanced_throwing/functions/fnc_throwFiredXEH.sqf
Normal file
28
addons/advanced_throwing/functions/fnc_throwFiredXEH.sqf
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Author: CBA Team
|
||||
* Throws Fired XEH.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: unit - Object the event handler is assigned to <OBJECT>
|
||||
* 1: weapon - Fired weapon <STRING>
|
||||
* 2: muzzle - Muzzle that was used <STRING>
|
||||
* 3: mode - Current mode of the fired weapon <STRING>
|
||||
* 4: ammo - Ammo used <STRING>
|
||||
* 5: magazine - magazine name which was used <STRING>
|
||||
* 6: projectile - Object of the projectile that was shot <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [unit, "weapon", "muzle", "mode", "ammo", "magazine", projectile] call ace_advanced_throwing_fnc_throwFiredXEH
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
TRACE_1("Fired",_this);
|
||||
|
||||
{
|
||||
_this call _x;
|
||||
} forEach ((_this select 0) getVariable "cba_xeh_fired");
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Author: Jonpas
|
||||
* Updates controls hints based on current state.
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* call ace_advanced_throwing_fnc_updateControlsHint
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if (!GVAR(showMouseControls)) exitWith {};
|
||||
|
||||
private _primed = ACE_player getVariable [QGVAR(primed), false];
|
||||
|
||||
private _mmb = [localize LSTRING(ChangeMode), localize LSTRING(Extend)] select (ACE_player getVariable [QGVAR(dropMode), false]);
|
||||
|
||||
if (!_primed) then {
|
||||
_mmb = [_mmb, localize LSTRING(Cook)] joinString " / ";
|
||||
};
|
||||
|
||||
[
|
||||
localize LSTRING(Throw),
|
||||
[localize ELSTRING(common,Cancel), ""] select _primed,
|
||||
_mmb
|
||||
] call EFUNC(interaction,showMouseHint);
|
1
addons/advanced_throwing/functions/script_component.hpp
Normal file
1
addons/advanced_throwing/functions/script_component.hpp
Normal file
@ -0,0 +1 @@
|
||||
#include "\z\ace\addons\advanced_throwing\script_component.hpp"
|
Reference in New Issue
Block a user