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:
jonpas
2016-09-03 01:39:34 +02:00
committed by GitHub
parent 12de3265b8
commit 0e1f2828a9
34 changed files with 48 additions and 47 deletions

View 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

View 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

View 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

View 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);

View 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;
};

View 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 [])

View 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));

View 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

View 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);
};

View 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));
};

View 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);

View 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);
};
}];

View 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);
};

View File

@ -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;

View 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);

View 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");

View File

@ -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);

View File

@ -0,0 +1 @@
#include "\z\ace\addons\advanced_throwing\script_component.hpp"