ACE3/addons/explosives/functions/fnc_setupExplosive.sqf

216 lines
11 KiB
Plaintext
Raw Normal View History

#include "script_component.hpp"
/*
* Author: Garth 'L-H' de Wet
* Starts the setup process for the passed explosive. Player only.
*
* Arguments:
2015-07-14 05:24:55 +00:00
* 0: Vehicle <OBJECT>
* 1: Player Unit <OBJECT>
* 2: Classname of explosive to place. (CfgMagazine class) <STRING>
*
* Return Value:
* None
*
* Example:
* [player, "SatchelCharge_Remote_Mag"] call ACE_Explosives_fnc_SetupExplosive;
*
* Public: Yes
*/
2015-07-14 05:24:55 +00:00
2015-07-25 06:42:17 +00:00
#define PLACE_RANGE_MAX 1
#define PLACE_RANGE_MIN 0.025
2015-08-15 19:35:33 +00:00
params ["_vehicle", "_unit", "_magClassname"];
TRACE_3("params",_vehicle,_unit,_magClassname);
2015-07-14 05:24:55 +00:00
//Get setup object vehicle and model:
private _setupObjectClass = getText(ConfigFile >> "CfgMagazines" >> _magClassname >> QGVAR(SetupObject));
2015-07-14 05:24:55 +00:00
if (!isClass (configFile >> "CfgVehicles" >> _setupObjectClass)) exitWith {ERROR("Bad Vehicle");};
private _p3dModel = getText (configFile >> "CfgVehicles" >> _setupObjectClass >> "model");
2015-07-14 05:24:55 +00:00
if (_p3dModel == "") exitWith {ERROR("No Model");}; //"" - will crash game!
2016-01-24 17:39:59 +00:00
[_unit, "forceWalk", "ACE_Explosives", true] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Explosives", true] call EFUNC(common,statusEffect_set);
2015-07-18 05:36:47 +00:00
2015-07-15 07:54:38 +00:00
//Show mouse buttons:
2015-07-14 05:24:55 +00:00
[localize LSTRING(PlaceAction), localize LSTRING(CancelAction), localize LSTRING(ScrollAction)] call EFUNC(interaction,showMouseHint);
2015-07-15 07:54:38 +00:00
_unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {true}, {GVAR(placeAction) = PLACE_APPROVE;}] call EFUNC(common,AddActionEventHandler)];
_unit setVariable [QGVAR(cancelActionEH), [_unit, "zoomtemp", {true}, {GVAR(placeAction) = PLACE_CANCEL;}] call EFUNC(common,AddActionEventHandler)];
2015-07-14 05:24:55 +00:00
//Display to show virtual object:
(QGVAR(virtualAmmo) call BIS_fnc_rscLayer) cutRsc [QGVAR(virtualAmmo), "PLAIN", 0, false];
((uiNamespace getVariable [QGVAR(virtualAmmoDisplay), displayNull]) displayCtrl 800851) ctrlSetModel _p3dModel;
2015-07-17 04:59:31 +00:00
//Make sure it has a trigger that works when attached (eg, no tripwires that only do pressurePlate)
private _isAttachable = false;
private _supportedTriggers = getArray (configFile >> "CfgMagazines" >> _magClassname >> "ACE_Triggers" >> "SupportedTriggers");
2015-07-16 04:52:47 +00:00
{
if ((getNumber (configFile >> "ACE_Triggers" >> _x >> "isAttachable")) == 1) exitWith {_isAttachable = true;};
} forEach _supportedTriggers;
2015-07-14 05:24:55 +00:00
GVAR(pfeh_running) = true;
GVAR(placeAction) = PLACE_WAITING;
2015-07-15 07:54:38 +00:00
GVAR(TweakedAngle) = 0;
2015-07-14 05:24:55 +00:00
2015-07-18 05:36:47 +00:00
2015-07-14 05:24:55 +00:00
[{
2015-07-15 07:54:38 +00:00
BEGIN_COUNTER(pfeh);
2015-07-14 05:24:55 +00:00
2015-08-15 19:35:33 +00:00
params ["_args", "_pfID"];
_args params ["_unit", "_magClassname", "_setupObjectClass", "_isAttachable"];
2015-07-14 05:24:55 +00:00
private _lookDirVector = ((positionCameraToWorld [0,0,0]) call EFUNC(common,positionToASL)) vectorFromTo ((positionCameraToWorld [0,0,10]) call EFUNC(common,positionToASL));
private _basePosASL = (eyePos _unit);
2015-07-25 07:10:33 +00:00
if (cameraView == "EXTERNAL") then { //If external, show explosive over the right shoulder
2015-07-15 07:54:38 +00:00
_basePosASL = _basePosASL vectorAdd ((positionCameraToWorld [0.3,0,0]) vectorDiff (positionCameraToWorld [0,0,0]));
};
2015-07-25 07:10:33 +00:00
if ((stance _unit) == "PRONE") then {
//If prone, lower base and increase up angle of look - Makes it much easier to attach to underside of vehicles
_basePosASL set [2, ((_basePosASL select 2) - 0.3)];
_lookDirVector = ((positionCameraToWorld [0,0,0]) call EFUNC(common,positionToASL)) vectorFromTo ((positionCameraToWorld [0,3,10]) call EFUNC(common,positionToASL));
};
private _cameraAngle = (_lookDirVector select 0) atan2 (_lookDirVector select 1);
2015-07-15 07:54:38 +00:00
private _testPositionIsValid = {
private _testBase = _basePosASL vectorAdd (_lookDirVector vectorMultiply (_this select 0));
private _return = true;
2015-07-15 07:54:38 +00:00
{
private _testPos = _testBase vectorAdd [0.1 * (_x select 0) * (cos _cameraAngle), 0.1 * (_x select 0) * (sin _cameraAngle), 0.1 * (_x select 1)];
2015-07-25 07:10:33 +00:00
#ifdef DEBUG_MODE_FULL
2015-07-15 07:54:38 +00:00
drawLine3d [(eyePos _unit) call EFUNC(common,ASLToPosition), (_testPos) call EFUNC(common,ASLToPosition), [1,0,0,1]];
2015-07-25 07:10:33 +00:00
#endif
if !((lineIntersectsSurfaces [eyePos _unit, _testPos, _unit]) isEqualTo []) exitWith {_return = false;};
2015-07-15 07:54:38 +00:00
} forEach [[0,0], [-1,-1], [1,-1], [-1,1], [1,1]];
_return
};
private _distanceFromBase = PLACE_RANGE_MAX;
private _badPosition = !([_distanceFromBase] call _testPositionIsValid);
private _attachVehicle = objNull;
2015-07-15 07:54:38 +00:00
2015-07-17 04:59:31 +00:00
if (_isAttachable && _badPosition) then {
_attachVehicle = objNull;
private _testBase = _basePosASL vectorAdd _lookDirVector;
2015-07-17 04:59:31 +00:00
{
private _testPos = _testBase vectorAdd [0.1 * (_x select 0) * (cos _cameraAngle), 0.1 * (_x select 0) * (sin _cameraAngle), 0.1 * (_x select 1)];
private _intersectObject = ((lineIntersectsSurfaces [eyePos _unit, _testPos, _unit]) param [0, objNull]) param [3, objNull];
if !(_intersectObject isEqualTo objNull) exitWith {_attachVehicle = _intersectObject};
2015-07-17 04:59:31 +00:00
} forEach [[0,0], [-1,-1], [1,-1], [-1,1], [1,1]];
2015-07-25 06:42:17 +00:00
if ((!isNull _attachVehicle) && {[PLACE_RANGE_MIN] call _testPositionIsValid} &&
2015-07-17 04:59:31 +00:00
{(_attachVehicle isKindOf "Car") || {_attachVehicle isKindOf "Tank"} || {_attachVehicle isKindOf "Air"} || {_attachVehicle isKindOf "Ship"}}) then {
private _min = PLACE_RANGE_MIN;
private _max = PLACE_RANGE_MAX;
2015-07-17 04:59:31 +00:00
for "_index" from 0 to 6 do {
2015-07-15 07:54:38 +00:00
_distanceFromBase = (_min + _max) / 2;
if ([_distanceFromBase] call _testPositionIsValid) then {
_min = _distanceFromBase;
} else {
_max = _distanceFromBase;
};
};
_badPosition = false;
_distanceFromBase = ((_min + _max) / 2 + 0.075) min 1;
2015-07-17 04:59:31 +00:00
} else {
_attachVehicle = objNull;
2015-07-15 07:54:38 +00:00
};
};
private _virtualPosASL = _basePosASL vectorAdd (_lookDirVector vectorMultiply _distanceFromBase);
2015-07-25 06:42:17 +00:00
2018-11-01 17:46:46 +00:00
// Update mouse hint
private _ctrlTextLMB = (uiNamespace getVariable [QEGVAR(interaction,mouseHint), displayNull]) displayCtrl 2420;
2015-07-25 06:42:17 +00:00
if (_badPosition) then {
2018-11-01 17:46:46 +00:00
_ctrlTextLMB ctrlSetText localize LSTRING(BlockedAction);
2015-07-25 06:42:17 +00:00
} else {
if (isNull _attachVehicle) then {
2018-11-01 17:46:46 +00:00
_ctrlTextLMB ctrlSetText localize LSTRING(PlaceAction);
2015-07-25 06:42:17 +00:00
} else {
2018-11-01 17:46:46 +00:00
_ctrlTextLMB ctrlSetText localize LSTRING(AttachAction);
2015-07-25 06:42:17 +00:00
};
};
2015-07-17 04:59:31 +00:00
//Don't allow Placing bellow terrain
2015-07-15 07:54:38 +00:00
if ((getTerrainHeightASL _virtualPosASL) > (_virtualPosASL select 2)) then {
_virtualPosASL set [2, (getTerrainHeightASL _virtualPosASL)];
2015-07-14 05:24:55 +00:00
};
//Don't allow placing in a bad position:
if (_badPosition && {GVAR(placeAction) == PLACE_APPROVE}) then {GVAR(placeAction) = PLACE_WAITING;};
if (_unit != ACE_player ||
{!([_unit, objNull, ["isNotSwimming"]] call EFUNC(common,canInteractWith))} ||
{!(_magClassname in (magazines _unit))}
) then {
GVAR(placeAction) = PLACE_CANCEL;
};
2015-07-18 05:36:47 +00:00
if (GVAR(placeAction) != PLACE_WAITING) then {
2015-07-14 05:24:55 +00:00
[_pfID] call CBA_fnc_removePerFrameHandler;
GVAR(pfeh_running) = false;
2016-01-19 15:34:59 +00:00
[_unit, "forceWalk", "ACE_Explosives", false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Explosives", false] call EFUNC(common,statusEffect_set);
2015-07-14 05:24:55 +00:00
[] call EFUNC(interaction,hideMouseHint);
[_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler);
[_unit, "zoomtemp", (_unit getVariable [QGVAR(cancelActionEH), -1])] call EFUNC(common,removeActionEventHandler);
(QGVAR(virtualAmmo) call BIS_fnc_rscLayer) cutText ["", "PLAIN"];
if (GVAR(placeAction) == PLACE_APPROVE) then {
private _placeAngle = 0;
private _expSetupVehicle = _setupObjectClass createVehicle (_virtualPosASL call EFUNC(common,ASLToPosition));
2015-08-05 17:22:43 +00:00
TRACE_1("Planting Mass", (getMass _expSetupVehicle));
//If the object is too heavy, it can kill a player if it colides
if ((getMass _expSetupVehicle) > 5) then {_expSetupVehicle setMass 5;};
2015-07-15 07:54:38 +00:00
if (isNull _attachVehicle) then {
2015-07-17 04:59:31 +00:00
_placeAngle = _cameraAngle - GVAR(TweakedAngle) + 180;
2015-07-15 07:54:38 +00:00
_expSetupVehicle setPosAsl _virtualPosASL;
2015-07-15 08:18:19 +00:00
_expSetupVehicle setDir _placeAngle;
2015-07-17 04:59:31 +00:00
_placeAngle = _placeAngle + 180; //CfgAmmos seem to be 180 for some reason
2015-07-15 07:54:38 +00:00
} else {
private _modelOffset = _attachVehicle worldToModel (_virtualPosASL call EFUNC(common,ASLToPosition));
2015-07-15 07:54:38 +00:00
_placeAngle = _cameraAngle - (getDir _attachVehicle) + 180;
_expSetupVehicle attachTo [_attachVehicle, _modelOffset];
_expSetupVehicle setVectorDirAndUp [[0,0,-1],[(sin _placeAngle),(cos _placeAngle),0]];
};
2015-07-25 06:42:17 +00:00
TRACE_1("Place angel",_placeAngle);
2015-07-15 07:54:38 +00:00
_expSetupVehicle setVariable [QGVAR(class), _magClassname, true];
_expSetupVehicle setVariable [QGVAR(Direction), _placeAngle, true];
2015-07-14 05:24:55 +00:00
2015-07-15 07:54:38 +00:00
_unit removeMagazine _magClassname;
2016-07-12 14:16:01 +00:00
[_unit, "PutDown"] call EFUNC(common,doGesture);
2015-07-15 07:54:38 +00:00
_unit setVariable [QGVAR(PlantingExplosive), true];
[{_this setVariable [QGVAR(PlantingExplosive), false]}, _unit, 1.5] call CBA_fnc_waitAndExecute;
2015-07-14 05:24:55 +00:00
};
} else {
private _screenPos = worldToScreen (_virtualPosASL call EFUNC(common,ASLToPosition));
2015-07-15 07:54:38 +00:00
if (_badPosition || {_screenPos isEqualTo []}) then {
2015-07-14 05:24:55 +00:00
((uiNamespace getVariable [QGVAR(virtualAmmoDisplay), displayNull]) displayCtrl 800851) ctrlShow false;
} else {
2015-07-18 05:36:47 +00:00
//Show the model on the hud in aprox the same size/location as it will be placed:
2015-07-14 05:24:55 +00:00
((uiNamespace getVariable [QGVAR(virtualAmmoDisplay), displayNull]) displayCtrl 800851) ctrlShow true;
2015-07-15 07:54:38 +00:00
private _realDistance = ((_virtualPosASL call EFUNC(common,ASLToPosition)) distance (positionCameraToWorld [0,0,0])) / (([] call CBA_fnc_getFov) select 1);
2015-07-14 05:24:55 +00:00
_screenPos = [(_screenPos select 0), _realDistance, (_screenPos select 1)];
((uiNamespace getVariable [QGVAR(virtualAmmoDisplay), displayNull]) displayCtrl 800851) ctrlSetPosition _screenPos;
private _modelDir = [0,0,-1];
private _modelUp = [0,-1,0];
2015-07-15 07:54:38 +00:00
if (isNull _attachVehicle) then {
private _angle = acos (_lookDirVector select 2);
2015-07-15 07:54:38 +00:00
_modelUp = [0, (cos _angle), (sin _angle)];
_modelDir = [cos GVAR(TweakedAngle), sin GVAR(TweakedAngle), 0] vectorCrossProduct _modelUp;
};
2015-07-14 05:24:55 +00:00
((uiNamespace getVariable [QGVAR(virtualAmmoDisplay), displayNull]) displayCtrl 800851) ctrlSetModelDirAndUp [_modelDir, _modelUp];
};
};
2015-07-15 07:54:38 +00:00
END_COUNTER(pfeh);
2015-07-16 04:52:47 +00:00
}, 0, [_unit, _magClassname, _setupObjectClass, _isAttachable]] call CBA_fnc_addPerFrameHandler;