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

Attach to vehicles #1669

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
50 changes: 48 additions & 2 deletions AGM_Attach/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class CfgFunctions {
class canDetach;
class detach;
class openAttachUI;
class Place_Approve;
class Place_Cancel;
class vehicleCanAttach;
class vehicleCanDetach;
};
};
};
Expand All @@ -30,6 +34,29 @@ class CfgFunctions {
count = COUNT; \
};

#define MACRO_ATTACHTOVEHICLE \
class AGM_Actions { \
class AGM_AttachVehicle { \
displayName = "$STR_AGM_Attach_AttachDetach"; \
condition = "[_player, AGM_Interaction_Target] call AGM_Attach_fnc_vehicleCanAttach"; \
statement = "[_player, AGM_Interaction_Target] call AGM_Attach_fnc_openAttachUI;"; \
exceptions[] = {"AGM_Drag_isNotDragging"}; \
showDisabled = 0; \
priority = 0; \
icon = "\AGM_Attach\UI\attach_ca.paa"; \
hotkey = "T"; \
}; \
class AGM_Attach_DetachVehicle { \
displayName = "$STR_AGM_Attach_Detach"; \
condition = "[_player, AGM_Interaction_Target] call AGM_Attach_fnc_vehicleCanDetach"; \
statement = "[_player, AGM_Interaction_Target] call AGM_Attach_fnc_detach"; \
exceptions[] = {"AGM_Drag_isNotDragging"}; \
showDisabled = 0; \
priority = 0; \
icon = "\AGM_Attach\UI\detach_ca.paa"; \
}; \
};

class CfgVehicles {
class Man;
class CAManBase: Man {
Expand All @@ -38,7 +65,7 @@ class CfgVehicles {
class AGM_Attach {
displayName = "$STR_AGM_Attach_AttachDetach";
condition = "[_player, ''] call AGM_Attach_fnc_canAttach";
statement = "[_player] call AGM_Attach_fnc_openAttachUI;";
statement = "[_player, _player] call AGM_Attach_fnc_openAttachUI;";
exceptions[] = {"AGM_Drag_isNotDragging"};
showDisabled = 0;
priority = 5;
Expand All @@ -48,7 +75,7 @@ class CfgVehicles {
class AGM_Attach_Detach {
displayName = "$STR_AGM_Attach_Detach";
condition = "[_player] call AGM_Attach_fnc_canDetach";
statement = "[_player] call AGM_Attach_fnc_detach";
statement = "[_player, _player] call AGM_Attach_fnc_detach";
exceptions[] = {"AGM_Drag_isNotDragging"};
showDisabled = 0;
priority = 5;
Expand All @@ -59,6 +86,25 @@ class CfgVehicles {
};
};

class LandVehicle;
class Car: LandVehicle {
MACRO_ATTACHTOVEHICLE
};
class Tank: LandVehicle {
MACRO_ATTACHTOVEHICLE
};
class Air;
class Helicopter: Air {
MACRO_ATTACHTOVEHICLE
};
class Plane: Air {
MACRO_ATTACHTOVEHICLE
};
class Ship;
class Ship_F: Ship {
MACRO_ATTACHTOVEHICLE
};

class All;
class AGM_IR_Strobe_Effect: All {
scope = 1;
Expand Down
90 changes: 90 additions & 0 deletions AGM_Attach/functions/fn_Place_Approve.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
Name: AGM_Attach_fnc_Place_Approve

Author(s):
Pabst Mirror (based on Explosive attach by Garth de Wet (LH))

Description:
Approves placement of the lightObject, releases the placement object for it to settle in a location

Parameters:
Nothing

Returns:
Nothing

Example:
call AGM_Attach_fnc_Place_Approve;
*/
private ["_setupObject", "_setupClassname", "_itemClassname", "_placementText", "_attachToVehicle", "_player", "_position0", "_closeInRatio", "_offset", "_keepGoingCloser", "_pos0temp", "_position1", "_attachedObject", "_currentObjects", "_currentItemNames"];

if (AGM_Attach_pfeh_running) then {
["AGM_Attach_Placement","OnEachFrame"] call BIS_fnc_removeStackedEventHandler;
AGM_Attach_pfeh_running = false;
};

_setupObject = AGM_Attach_SetupObject;
_setupClassname = typeOf _setupObject;
_itemClassname = AGM_Attach_SetupPlacmentItem;
_placementText = AGM_Attach_SetupPlacmentText;
_attachToVehicle = AGM_Attach_SetupAttachVehicle;

AGM_Attach_SetupPlacmentItem = "";
AGM_Attach_SetupPlacmentText = "";
AGM_Attach_SetupObject = objNull;
AGM_Attach_SetupAttachVehicle = objNull;
AGM_Attach_placer forceWalk false;
AGM_Attach_placer = objNull;

_player = AGM_player;
[_player, "DefaultAction", _player getVariable ["AGM_Attach_Place", -1]] call AGM_Core_fnc_removeActionEventHandler;
[_player, "MenuBack", _player getVariable ["AGM_Attach_Cancel", -1]] call AGM_Core_fnc_removeActionEventHandler;
call AGM_Interaction_fnc_hideMouseHint;

//A player can release the attachObject with it floating in mid-air.
//This will use lineIntersectsWith to scan towards the center of the vehicle to find a collision
//ArmA's collision detection is of couse terrible and often misses collisions (difference between what we see and collision LOD)
//So it does multiple scans at slighly different angles
//This is VERY computationaly intensive, but doesn't happen that often.

_position0 = getPosAtl _setupObject;
_closeInRatio = 1;
_offset = _attachToVehicle worldToModel _position0;
_keepGoingCloser = true;
while {_keepGoingCloser} do {
_closeInRatio = _closeInRatio - 0.004;
if (_closeInRatio <= 0) exitWith {};
{
_pos0temp = _position0 vectorAdd _x;
{
_position1 = [(_offset select 0) * _closeInRatio, (_offset select 1) * _closeInRatio, (_offset select 2)];
_position1 = _attachToVehicle modelToWorld _position1;
_position1 = _position1 vectorAdd _x;
//Uncomment to see the lazor show, and see how the scanning works:
// drawLine3D [_pos0temp, _position1, [1,0,0,1]];
if (_attachToVehicle in lineIntersectsWith [(ATLToASL _pos0temp), (ATLToASL _position1), player, _setupObject]) exitWith {_keepGoingCloser = false};
} forEach [[0,0,0], [0,0,0.075], [0,0,-0.075], [0,0.075,0], [0,-0.075,0], [0.075,0,0], [-.075,0,0]];
} forEach [[0,0,0], [0,0,0.075], [0,0,-0.075]];
};
//Move it out slightly, for visability sake (better to look a little funny than be embedded//sunk in the hull)
_closeInRatio = (_closeInRatio + 0.006) min 1;

//Delete Local Placement Object
deleteVehicle _setupObject;

//Create New 'real' Object
_attachedObject = _setupClassname createVehicle (getPos _player);
_attachedObject attachTo [_attachToVehicle, [(_offset select 0) * _closeInRatio, (_offset select 1) * _closeInRatio, (_offset select 2)]];

//Remove Item from inventory
_player removeItem _itemClassname;

//Add Object to AGM_AttachedObjects and AGM_AttachedItemNames
_currentObjects = _attachToVehicle getVariable ["AGM_AttachedObjects", []];
_currentObjects pushBack _attachedObject;
_attachToVehicle setVariable ["AGM_AttachedObjects", _currentObjects, true];
_currentItemNames = _attachToVehicle getVariable ["AGM_AttachedItemNames", []];
_currentItemNames pushBack _itemClassname;
_attachToVehicle setVariable ["AGM_AttachedItemNames", _currentItemNames, true];

[_placementText] call AGM_Core_fnc_displayTextStructured;
37 changes: 37 additions & 0 deletions AGM_Attach/functions/fn_Place_Cancel.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Name: AGM_Attach_fnc_Place_Cancel

Author(s):
Pabst Mirror (based on Explosive attach by Garth de Wet (LH))

Description:
Cancels placement of the lightObject

Parameters:
Nothing

Returns:
Nothing

Example:
call AGM_Attach_fnc_Place_Cancel;
*/
if (AGM_Attach_pfeh_running) then {
["AGM_Attach_Placement","OnEachFrame"] call BIS_fnc_removeStackedEventHandler;
AGM_Attach_pfeh_running = false;
};
if (!isNull (AGM_Attach_SetupObject)) then {
deleteVehicle AGM_Attach_SetupObject;
};
AGM_Attach_SetupPlacmentItem = "";
AGM_Attach_SetupPlacmentText = "";
AGM_Attach_SetupObject = objNull;
AGM_Attach_SetupAttachVehicle = objNull;
if (isNil {AGM_Attach_placer}) then {
AGM_Attach_placer = objNull;
};
AGM_Attach_placer forceWalk false;
AGM_Attach_placer = objNull;
call AGM_Interaction_fnc_hideMouseHint;
[AGM_player, "DefaultAction", AGM_player getVariable ["AGM_Attach_Place", -1]] call AGM_Core_fnc_removeActionEventHandler;
[AGM_player, "MenuBack", AGM_player getVariable ["AGM_Attach_Cancel", -1]] call AGM_Core_fnc_removeActionEventHandler;
101 changes: 68 additions & 33 deletions AGM_Attach/functions/fn_attach.sqf
Original file line number Diff line number Diff line change
@@ -1,60 +1,95 @@
/*
Name: AGM_Attach_fnc_attach

Author: eRazeri and CAA-Picard

Attach an item to the unit
Attach an item to the unit. For vehicles, it starts the custom placement)

Arguments:
0: unit
1: Item name
0: OBJECT - unit doing the attaching (player)
1: OBJECT - vehicle that it will be attached to (player or vehicle)
2: STRING - classname of attached item (from CfgMagazines or CfgWeapons)

Return Value:
none
*/

private ["_unit", "_itemName", "_attachedItem"];
private ["_unit", "_attachToVehicle", "_itemName", "_selfAttachPosition", "_itemVehClass", "_onAtachText", "_attachedItem", "_player"];

_unit = _this select 0;
_itemName = _this select 1;
_attachToVehicle = _this select 1;
_itemName = _this select 2;

// Check if unit has an attached item
if (_unit getVariable ["AGM_AttachedItemName", ""] != "") exitWith {};
// For Self Placement - Check if unit has an attached item
if (_unit == _attachToVehicle) then {
if ((count (_attachToVehicle getVariable ["AGM_AttachedObjects", []])) > 0) exitWith {};
};

// Check if the unit still has the item
if !((_itemName in items _unit) or (_itemName in magazines _unit)) exitWith {};

// Attach item
_selfAttachPosition = [_unit, [-0.05,0,0.12], "rightshoulder"];
_itemVehClass = "";
_onAtachText = "";

switch true do {
case (_itemName == "AGM_IR_Strobe_Item") : {
_attachedItem = "AGM_IR_Strobe_Effect" createVehicle [0,0,0];
_attachedItem attachTo [_unit,[0,-0.11,0.16],"pilot"];//makes it attach to the head a bit better, shoulder is not good for visibility - eRazeri
[localize "STR_AGM_Attach_IrStrobe_Attached"] call AGM_Core_fnc_displayTextStructured;
case (_itemName == "AGM_IR_Strobe_Item"): {
_itemVehClass = "AGM_IR_Strobe_Effect";
_onAtachText = localize "STR_AGM_Attach_IrStrobe_Attached";
_selfAttachPosition = [_unit,[0,-0.11,0.16],"pilot"]; //makes it attach to the head a bit better, shoulder is not good for visibility - eRazeri
};
case (_itemName == "B_IR_Grenade") : {
_attachedItem = "B_IRStrobe" createVehicle [0,0,0];
_attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"];
[localize "STR_AGM_Attach_IrGrenade_Attached"] call AGM_Core_fnc_displayTextStructured;
case (_itemName == "B_IR_Grenade"): {
_itemVehClass = "B_IRStrobe";
_onAtachText = localize "STR_AGM_Attach_IrGrenade_Attached";
};
case (_itemName == "O_IR_Grenade") : {
_attachedItem = "O_IRStrobe" createVehicle [0,0,0];
_attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"];
[localize "STR_AGM_Attach_IrGrenade_Attached"] call AGM_Core_fnc_displayTextStructured;
case (_itemName == "O_IR_Grenade"): {
_itemVehClass = "O_IRStrobe";
_onAtachText = localize "STR_AGM_Attach_IrGrenade_Attached";
};
case (_itemName == "I_IR_Grenade") : {
_attachedItem = "I_IRStrobe" createVehicle [0,0,0];
_attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"];
[localize "STR_AGM_Attach_IrGrenade_Attached"] call AGM_Core_fnc_displayTextStructured;
case (_itemName == "I_IR_Grenade"): {
_itemVehClass = "I_IRStrobe";
_onAtachText = localize "STR_AGM_Attach_IrGrenade_Attached";
};
case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}) : {
_attachedItem = _itemName createVehicle [0,0,0];
_attachedItem attachTo [_unit,[-0.05,0,0.12],"rightshoulder"];
[localize "STR_AGM_Attach_Chemlight_Attached"] call AGM_Core_fnc_displayTextStructured;
case (_itemName == "Chemlight_blue" or {_itemName == "Chemlight_green"} or {_itemName == "Chemlight_red"} or {_itemName == "Chemlight_yellow"}): {
_itemVehClass = _itemName;
_onAtachText = localize "STR_AGM_Attach_Chemlight_Attached";
};
default {
if (true) exitWith {};
};
};

// Remove item
_unit removeItem _itemName;
_unit setVariable ["AGM_AttachedItemName", _itemName, true];
_unit setVariable ["AGM_AttachedItem", _attachedItem, true];
if (_itemVehClass == "") exitWith {["AGM_Attach_fnc_attach - no _itemVehClass for Item [%1]", _itemName] call bis_fnc_error;};

if (_unit == _attachToVehicle) then { //Self Attachment
_unit removeItem _itemName; // Remove item
_attachedItem = _itemVehClass createVehicle [0,0,0];
_attachedItem attachTo _selfAttachPosition;
[_onAtachText] call AGM_Core_fnc_displayTextStructured;
_attachToVehicle setVariable ["AGM_AttachedObjects", [_attachedItem], true];
_attachToVehicle setVariable ["AGM_AttachedItemNames", [_itemName], true];
} else {
AGM_Attach_SetupObject = _itemVehClass createVehicleLocal [0,0,-10000];
AGM_Attach_SetupObject enableSimulationGlobal false;
AGM_Attach_SetupPlacmentText = _onAtachText;
AGM_Attach_SetupPlacmentItem = _itemName;
AGM_Attach_SetupAttachVehicle = _attachToVehicle;
AGM_Attach_placer = _unit;
_unit forceWalk true;

["AGM_Attach_Placement","OnEachFrame", {
private "_player";
_player = AGM_player;
//Stop if player switch or player gets to far from vehicle
if ((AGM_Attach_placer != _player) || ((_player distance AGM_Attach_SetupAttachVehicle) > 9)) exitWith {
call AGM_Attach_fnc_Place_Cancel;
};
AGM_Attach_pfeh_running = true;
_pos = (ASLtoATL eyePos _player) vectorAdd (positionCameraToWorld [0,0,1] vectorDiff positionCameraToWorld [0,0,0]);
AGM_Attach_SetupObject setPosATL _pos;
}] call BIS_fnc_addStackedEventHandler;

//had to spawn the mouseHint, not sure why
[localize "STR_AGM_Attach_PlaceAction", localize "STR_AGM_Attach_CancelAction"] spawn AGM_Interaction_fnc_showMouseHint;
_unit setVariable ["AGM_Attach_Place", [_unit, "DefaultAction", {AGM_Attach_pfeh_running AND !isNull (AGM_Attach_SetupObject)}, {call AGM_Attach_fnc_Place_Approve;}] call AGM_Core_fnc_AddActionEventHandler];
_unit setVariable ["AGM_Attach_Cancel", [_unit, "MenuBack", {AGM_Attach_pfeh_running AND !isNull (AGM_Attach_SetupObject)}, {call AGM_Attach_fnc_Place_Cancel;}] call AGM_Core_fnc_AddActionEventHandler];
};
4 changes: 2 additions & 2 deletions AGM_Attach/functions/fn_canAttach.sqf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Author: commy2
*
* Check if a unit can attach a specific item.
* Check if a unit can attach a specific item to themselves.
*
* Argument:
* 0: Unit that wants to attach the object (Object)
Expand All @@ -16,4 +16,4 @@ private ["_unit", "_item"];
_unit = _this select 0;
_item = _this select 1;

canStand _unit && {_unit getVariable ["AGM_AttachedItemName", ""] == ""} && {_item in (magazines _unit + items _unit + [""])}
canStand _unit && {(count (_unit getVariable ["AGM_AttachedObjects", []])) == 0} && {_item in (magazines _unit + items _unit + [""])}
5 changes: 3 additions & 2 deletions AGM_Attach/functions/fn_canDetach.sqf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
/* AGM_Attach_fnc_canDetach
*
* Author: commy2
*
* Check if a unit has an item attached and if it can remove that item.
Expand All @@ -14,4 +15,4 @@ private "_unit";

_unit = _this select 0;

canStand _unit && {_unit getVariable ["AGM_AttachedItemName", ""] != ""}
canStand _unit && {(count (_unit getVariable ["AGM_AttachedObjects", []])) != 0}
Loading