Cargo - Improve various aspects (#9617)

* Update CfgVehicles.hpp

* Cargo cleanup

* Update menu.hpp

* Updated status effect key

* Update fnc_onMenuOpen.sqf

* Update fnc_onMenuOpen.sqf

* fix comment from merge

* nil interaction GVARs on menu close

* fix carry bug

* Fix floating objects in MP

* Updated ace_cargoAdded doc

* Fix progress bar prematurely stopping

* Finer cursor object selection

---------

Co-authored-by: LinkIsGrim <salluci.lovi@gmail.com>
This commit is contained in:
johnb432 2023-11-18 00:07:28 +01:00 committed by GitHub
parent 8f3129a02e
commit d1f0dc5e83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 821 additions and 639 deletions

View File

@ -9,7 +9,7 @@ class Cfg3DEN {
property = QGVAR(customName); property = QGVAR(customName);
control = "Edit"; control = "Edit";
expression = QUOTE(_this setVariable [ARR_3(QQGVAR(customName),_value,true)];); expression = QUOTE(_this setVariable [ARR_3(QQGVAR(customName),_value,true)]);
defaultValue = "''"; defaultValue = "''";
condition = "objectHasInventoryCargo - objectVehicle"; condition = "objectHasInventoryCargo - objectVehicle";

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers { class Extended_PreStart_EventHandlers {
class ADDON { class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));

View File

@ -173,7 +173,7 @@ class CfgVehicles {
}; };
// misc. vehicles // Misc. vehicles
class Quadbike_01_base_F: Car_F { class Quadbike_01_base_F: Car_F {
GVAR(space) = 0; GVAR(space) = 0;
GVAR(hasCargo) = 0; GVAR(hasCargo) = 0;
@ -184,7 +184,7 @@ class CfgVehicles {
GVAR(hasCargo) = 0; GVAR(hasCargo) = 0;
}; };
// helicopters // Helicopters
class Air; class Air;
class Helicopter: Air { class Helicopter: Air {
GVAR(space) = 8; GVAR(space) = 8;
@ -224,7 +224,7 @@ class CfgVehicles {
}; };
class Heli_Transport_04_base_F: Helicopter_Base_H { class Heli_Transport_04_base_F: Helicopter_Base_H {
// note the double brackets are because loadmasterTurrets is an array of arrays / turret paths // Note the double brackets are because loadmasterTurrets is an array of arrays / turret paths
GVAR(loadmasterTurrets)[] = {{1}}; GVAR(loadmasterTurrets)[] = {{1}};
GVAR(space) = 0; GVAR(space) = 0;
GVAR(hasCargo) = 0; GVAR(hasCargo) = 0;
@ -363,8 +363,9 @@ class CfgVehicles {
GVAR(size) = 6; GVAR(size) = 6;
}; };
// Slingload pallets
class Slingload_base_F: ReammoBox_F {}; class Slingload_base_F: ReammoBox_F {};
class CargoNet_01_base_F: Slingload_base_F { //Slingload pallets class CargoNet_01_base_F: Slingload_base_F {
GVAR(size) = 6; GVAR(size) = 6;
}; };

View File

@ -5,7 +5,6 @@ PREP(canUnloadItem);
PREP(getCargoSpaceLeft); PREP(getCargoSpaceLeft);
PREP(getNameItem); PREP(getNameItem);
PREP(getSizeItem); PREP(getSizeItem);
PREP(handleDeleted);
PREP(handleDestroyed); PREP(handleDestroyed);
PREP(initObject); PREP(initObject);
PREP(initVehicle); PREP(initVehicle);
@ -21,4 +20,3 @@ PREP(startLoadIn);
PREP(startUnload); PREP(startUnload);
PREP(unloadCarryItem); PREP(unloadCarryItem);
PREP(unloadItem); PREP(unloadItem);
PREP(validateCargoSpace);

View File

@ -1,49 +1,33 @@
#include "script_component.hpp" #include "script_component.hpp"
["ace_addCargo", {_this call FUNC(addCargoItem)}] call CBA_fnc_addEventHandler; ["ace_addCargo", LINKFUNC(addCargoItem)] call CBA_fnc_addEventHandler;
[QGVAR(paradropItem), {
params ["_item", "_vehicle", ["_showHint", true]];
private _unloaded = [_item, _vehicle, _showHint] call FUNC(paradropItem);
if (_unloaded && {GVAR(openAfterUnload) in [2, 3]}) then {
GVAR(interactionVehicle) = _vehicle;
GVAR(interactionParadrop) = true;
createDialog QGVAR(menu);
};
}] call CBA_fnc_addEventHandler;
["ace_loadCargo", { ["ace_loadCargo", {
params ["_item", "_vehicle"]; params ["_item", "_vehicle"];
TRACE_2("LoadCargo EH",_item,_vehicle); TRACE_2("LoadCargo EH",_item,_vehicle);
private _loaded = [_item, _vehicle] call FUNC(loadItem); private _loaded = [_item, _vehicle] call FUNC(loadItem); // returns true if successful
// Show hint as feedback // Show hint as feedback
private _hint = [LSTRING(LoadingFailed), LSTRING(LoadedItem)] select _loaded; private _hint = [LSTRING(loadingFailed), LSTRING(loadedItem)] select _loaded;
private _itemName = [_item, true] call FUNC(getNameItem); private _itemName = [_item, true] call FUNC(getNameItem);
private _vehicleName = getText (configOf _vehicle >> "displayName"); private _vehicleName = getText (configOf _vehicle >> "displayName");
[[_hint, _itemName, _vehicleName], 3.0] call EFUNC(common,displayTextStructured); [[_hint, _itemName, _vehicleName], 3] call EFUNC(common,displayTextStructured);
if (_loaded) then {
// Invoke listenable event
["ace_cargoLoaded", [_item, _vehicle]] call CBA_fnc_globalEvent;
};
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
["ace_unloadCargo", { ["ace_unloadCargo", {
params ["_item", "_vehicle", ["_unloader", objNull]]; params ["_item", "_vehicle", ["_unloader", objNull]];
TRACE_3("UnloadCargo EH",_item,_vehicle,_unloader); TRACE_3("UnloadCargo EH",_item,_vehicle,_unloader);
private _unloaded = [_item, _vehicle, _unloader] call FUNC(unloadItem); //returns true if sucessful private _unloaded = [_item, _vehicle, _unloader] call FUNC(unloadItem); // returns true if successful
// Show hint as feedback // Show hint as feedback
private _hint = [LSTRING(UnloadingFailed), LSTRING(UnloadedItem)] select _unloaded; private _hint = [LSTRING(unloadingFailed), LSTRING(unloadedItem)] select _unloaded;
private _itemName = [_item, true] call FUNC(getNameItem); private _itemName = [_item, true] call FUNC(getNameItem);
private _vehicleName = getText (configOf _vehicle >> "displayName"); private _vehicleName = getText (configOf _vehicle >> "displayName");
[[_hint, _itemName, _vehicleName], 3.0] call EFUNC(common,displayTextStructured); [[_hint, _itemName, _vehicleName], 3] call EFUNC(common,displayTextStructured);
if (_unloaded && {GVAR(openAfterUnload) in [1, 3]}) then { if (_unloaded && {GVAR(openAfterUnload) in [1, 3]}) then {
GVAR(interactionVehicle) = _vehicle; GVAR(interactionVehicle) = _vehicle;
@ -58,16 +42,27 @@
_item hideObjectGlobal false; _item hideObjectGlobal false;
_item setPosASL (AGLtoASL _emptyPosAGL); _item setPosASL (AGLtoASL _emptyPosAGL);
[_item, "blockDamage", "ACE_cargo", false] call EFUNC(common,statusEffect_set); [_item, "blockDamage", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
}] call CBA_fnc_addEventHandler;
[QGVAR(paradropItem), {
params ["_item", "_vehicle", ["_showHint", true]];
private _unloaded = [_item, _vehicle, _showHint] call FUNC(paradropItem);
if (_unloaded && {GVAR(openAfterUnload) in [2, 3]}) then {
GVAR(interactionVehicle) = _vehicle;
GVAR(interactionParadrop) = true;
createDialog QGVAR(menu);
};
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
// Private events to handle adding actions globally via public functions // Private events to handle adding actions globally via public functions
[QGVAR(initObject), DFUNC(initObject)] call CBA_fnc_addEventHandler; [QGVAR(initObject), LINKFUNC(initObject)] call CBA_fnc_addEventHandler;
[QGVAR(initVehicle), DFUNC(initVehicle)] call CBA_fnc_addEventHandler; [QGVAR(initVehicle), LINKFUNC(initVehicle)] call CBA_fnc_addEventHandler;
GVAR(vehicleAction) = [ GVAR(vehicleAction) = [
QGVAR(openMenu), localize LSTRING(openMenu), "", QGVAR(openMenu), LLSTRING(openMenu), "",
{ {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(interactionVehicle) = _target; GVAR(interactionVehicle) = _target;
@ -77,17 +72,17 @@ GVAR(vehicleAction) = [
{ {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(enable) && GVAR(enable) &&
{(_target getVariable [QGVAR(hasCargo), getNumber (configOf _target >> QGVAR(hasCargo)) == 1])} &&
{locked _target < 2} &&
{([_player, _target] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE} &&
{alive _target} && {alive _target} &&
{locked _target < 2} &&
{(_target getVariable [QGVAR(hasCargo), getNumber (configOf _target >> QGVAR(hasCargo)) == 1])} &&
{[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} && {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} &&
{[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)} {[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)} &&
{([_player, _target] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}
} }
] call EFUNC(interact_menu,createAction); ] call EFUNC(interact_menu,createAction);
GVAR(objectActions) = [ GVAR(objectActions) = [
[QGVAR(renameObject), LELSTRING(common,rename), "", //TODO: add icon, maybe a pencil couldn't find it before. [QGVAR(renameObject), LELSTRING(common,rename), "\a3\Modules_F_Curator\Data\iconMissionName_ca.paa",
{ {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(interactionVehicle) = _target; GVAR(interactionVehicle) = _target;
@ -97,59 +92,67 @@ GVAR(objectActions) = [
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(enable) && GVAR(enable) &&
{GVAR(enableRename)} && {GVAR(enableRename)} &&
{(_target getVariable [QGVAR(canLoad), getNumber (configOf _target >> QGVAR(canLoad))]) in [true, 1]} &&
{alive _target} && {alive _target} &&
{_target getVariable [QGVAR(canLoad), getNumber (configOf _target >> QGVAR(canLoad)) == 1]} &&
{!(_target getVariable [QGVAR(noRename), getNumber (configOf _target >> QGVAR(noRename)) == 1])} &&
{[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} && {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} &&
{[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)} && {[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)}
{(_target getVariable [QGVAR(noRename), getNumber (configOf _target >> QGVAR(noRename))]) in [false, 0]}
} }
] call EFUNC(interact_menu,createAction), ] call EFUNC(interact_menu,createAction),
[QGVAR(load), localize LSTRING(loadObject), "a3\ui_f\data\IGUI\Cfg\Actions\loadVehicle_ca.paa", [QGVAR(load), LLSTRING(loadObject), "a3\ui_f\data\IGUI\Cfg\Actions\loadVehicle_ca.paa",
{ {
params ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
[_player, _target] call FUNC(startLoadIn); [_player, _target] call FUNC(startLoadIn);
}, },
{ {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(enable) && GVAR(enable) &&
{(_target getVariable [QGVAR(canLoad), getNumber (configOf _target >> QGVAR(canLoad))]) in [true, 1]} &&
{locked _target < 2} &&
{alive _target} && {alive _target} &&
{locked _target < 2} &&
{_target getVariable [QGVAR(canLoad), getNumber (configOf _target >> QGVAR(canLoad)) == 1]} &&
{[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} && {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)} &&
{[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)} && {[_player, _target] call EFUNC(interaction,canInteractWithVehicleCrew)} &&
{((nearestObjects [_target, GVAR(cargoHolderTypes), (MAX_LOAD_DISTANCE + 10)]) findIf { {((nearestObjects [_target, GVAR(cargoHolderTypes), MAX_LOAD_DISTANCE + 10]) findIf {
private _hasCargoConfig = 1 == getNumber (configOf _x >> QGVAR(hasCargo)); _x != _target &&
private _hasCargoPublic = _x getVariable [QGVAR(hasCargo), false]; {alive _x} &&
(_hasCargoConfig || {_hasCargoPublic}) && {_x != _target} && {alive _x} && {locked _x < 2} && {locked _x < 2} &&
{_x getVariable [QGVAR(hasCargo), getNumber (configOf _x >> QGVAR(hasCargo)) == 1]} &&
{([_target, _x] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE} {([_target, _x] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}
}) > -1} }) != -1}
}, },
LINKFUNC(addCargoVehiclesActions) LINKFUNC(addCargoVehiclesActions)
] call EFUNC(interact_menu,createAction) ] call EFUNC(interact_menu,createAction)
]; ];
// find all remaining configured classes and init them, see XEH_preStart.sqf // Find all remaining configured classes and init them, see XEH_preStart.sqf
private _vehicleClassesAddAction = call (uiNamespace getVariable [QGVAR(initializedVehicleClasses), {[]}]); private _vehicleClassesAddAction = call (uiNamespace getVariable [QGVAR(initializedVehicleClasses), {[]}]);
{ {
[_x, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToClass); [_x, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToClass);
} forEach _vehicleClassesAddAction; } forEach _vehicleClassesAddAction;
GVAR(initializedVehicleClasses) append _vehicleClassesAddAction; GVAR(initializedVehicleClasses) append _vehicleClassesAddAction;
private _objectClassesAddAction = call (uiNamespace getVariable [QGVAR(initializedItemClasses), {[]}]); private _objectClassesAddAction = call (uiNamespace getVariable [QGVAR(initializedItemClasses), {[]}]);
{ {
private _objectClass = _x; private _objectClass = _x;
{ {
[_objectClass, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToClass); [_objectClass, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToClass);
} forEach GVAR(objectActions); } forEach GVAR(objectActions);
} forEach _objectClassesAddAction; } forEach _objectClassesAddAction;
GVAR(initializedItemClasses) append _objectClassesAddAction; GVAR(initializedItemClasses) append _objectClassesAddAction;
private _vehicleClassesAddClassEH = call (uiNamespace getVariable [QGVAR(vehicleClasses_classEH), {[]}]); private _vehicleClassesAddClassEH = call (uiNamespace getVariable [QGVAR(vehicleClasses_classEH), {[]}]);
{ {
[_x, "initPost", DFUNC(initVehicle), nil, nil, true] call CBA_fnc_addClassEventHandler; [_x, "initPost", DFUNC(initVehicle), nil, nil, true] call CBA_fnc_addClassEventHandler;
} forEach _vehicleClassesAddClassEH; } forEach _vehicleClassesAddClassEH;
private _objectClassesAddClassEH = call (uiNamespace getVariable [QGVAR(objectClasses_classEH), {[]}]); private _objectClassesAddClassEH = call (uiNamespace getVariable [QGVAR(objectClasses_classEH), {[]}]);
{ {
[_x, "initPost", DFUNC(initObject), nil, nil, true] call CBA_fnc_addClassEventHandler; [_x, "initPost", DFUNC(initObject), nil, nil, true] call CBA_fnc_addClassEventHandler;
} forEach _objectClassesAddClassEH; } forEach _objectClassesAddClassEH;
@ -157,7 +160,9 @@ private _objectClassesAddClassEH = call (uiNamespace getVariable [QGVAR(objectCl
if (isServer) then { if (isServer) then {
["ace_placedInBodyBag", { ["ace_placedInBodyBag", {
params ["_target", "_bodyBag", "_isGrave"]; params ["_target", "_bodyBag", "_isGrave"];
if (_isGrave) exitWith {}; // assume graves aren't cargo if (_isGrave) exitWith {}; // assume graves aren't cargo
_bodyBag setVariable [QGVAR(customName), [_target, false, true] call EFUNC(common,getName), true]; _bodyBag setVariable [QGVAR(customName), [_target, false, true] call EFUNC(common,getName), true];
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
}; };

View File

@ -10,11 +10,11 @@ PREP_RECOMPILE_END;
GVAR(initializedItemClasses) = []; GVAR(initializedItemClasses) = [];
GVAR(initializedVehicleClasses) = []; GVAR(initializedVehicleClasses) = [];
GVAR(cargoHolderTypes) = ["Car", "Air", "Tank", "Ship", "Cargo_base_F", "Land_PaperBox_closed_F"]; GVAR(cargoHolderTypes) = ["Car", "Air", "Tank", "Ship", "Cargo_base_F", "Land_PaperBox_closed_F"] apply {_x call EFUNC(common,getConfigName)}; // make sure they are config case
GVAR(disableParadropEffectsClasstypes) = ["Car_F"]; GVAR(disableParadropEffectsClasstypes) = ["Car_F"] apply {_x call EFUNC(common,getConfigName)};
if (isServer) then { if (isServer) then {
["All", "Deleted", LINKFUNC(handleDeleted)] call CBA_fnc_addClassEventHandler; ["All", "Deleted", LINKFUNC(handleDestroyed)] call CBA_fnc_addClassEventHandler;
}; };
["All", "Killed", LINKFUNC(handleDestroyed)] call CBA_fnc_addClassEventHandler; ["All", "Killed", LINKFUNC(handleDestroyed)] call CBA_fnc_addClassEventHandler;

View File

@ -2,36 +2,38 @@
#include "XEH_PREP.hpp" #include "XEH_PREP.hpp"
// See XEH_postInit.sqf // See XEH_postInit.sqf
private _vehicleClasses_addClassEH = ["ThingX", "LandVehicle", "Air", "Ship_F"]; private _vehicleClasses_addClassEH = ["ThingX", "LandVehicle", "Air", "Ship_F"];
private _objectClasses_addClassEH = ["ThingX", "StaticWeapon"]; private _objectClasses_addClassEH = ["ThingX", "StaticWeapon"];
private _vehicleClasses_addAction = []; private _vehicleClasses_addAction = [];
private _itemClasses_addAction = []; private _itemClasses_addAction = [];
private _class = "";
// find all remaining configured classes and init them // Find all remaining configured classes and init them
{ {
private _class = configName _x; _class = configName _x;
// init vehicle
// Init vehicle
if ( if (
1 == getNumber (_x >> QGVAR(hasCargo)) getNumber (_x >> QGVAR(hasCargo)) == 1 &&
&& {-1 == _vehicleClasses_addClassEH findIf {_class isKindOf _x}} {_vehicleClasses_addClassEH findIf {_class isKindOf _x} == -1}
) then { ) then {
if (_class isKindOf "Static") then { if (_class isKindOf "Static") then {
if (2 == getNumber (_x >> "scope")) then { if (getNumber (_x >> "scope") == 2) then {
_vehicleClasses_addAction pushBackUnique _class; _vehicleClasses_addAction pushBackUnique _class;
}; };
} else { } else {
_vehicleClasses_addClassEH pushBackUnique _class; _vehicleClasses_addClassEH pushBackUnique _class;
}; };
}; };
// init object
// Init object
if ( if (
1 == getNumber (_x >> QGVAR(canLoad)) getNumber (_x >> QGVAR(canLoad)) == 1 &&
&& {-1 == _objectClasses_addClassEH findIf {_class isKindOf _x}} {_objectClasses_addClassEH findIf {_class isKindOf _x} == -1}
) then { ) then {
if (_class isKindOf "Static") then { if (_class isKindOf "Static") then {
if (2 == getNumber (_x >> "scope")) then { if (getNumber (_x >> "scope") == 2) then {
_itemClasses_addAction pushBackUnique _class; _itemClasses_addAction pushBackUnique _class;
}; };
} else { } else {
@ -40,7 +42,6 @@ private _itemClasses_addAction = [];
}; };
} forEach ("true" configClasses (configFile >> "CfgVehicles")); } forEach ("true" configClasses (configFile >> "CfgVehicles"));
uiNamespace setVariable [QGVAR(vehicleClasses_classEH), compileFinal str _vehicleClasses_addClassEH]; uiNamespace setVariable [QGVAR(vehicleClasses_classEH), compileFinal str _vehicleClasses_addClassEH];
uiNamespace setVariable [QGVAR(objectClasses_classEH), compileFinal str _objectClasses_addClassEH]; uiNamespace setVariable [QGVAR(objectClasses_classEH), compileFinal str _objectClasses_addClassEH];
uiNamespace setVariable [QGVAR(initializedVehicleClasses), compileFinal str _vehicleClasses_addAction]; uiNamespace setVariable [QGVAR(initializedVehicleClasses), compileFinal str _vehicleClasses_addAction];

View File

@ -4,26 +4,34 @@
* Adds a cargo item to the vehicle. * Adds a cargo item to the vehicle.
* *
* Arguments: * Arguments:
* 0: Item Classname <STRING> * 0: Item to be loaded <STRING> or <OBJECT>
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Amount <NUMBER> (default: 1) * 2: Amount <NUMBER> (default: 1)
* 3: Show Hint <BOOL> (default: false)
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* ["item", vehicle] call ace_cargo_fnc_addCargoItem * ["ACE_Wheel", cursorObject] call ace_cargo_fnc_addCargoItem
* *
* Public: No * Public: No
*/ */
params ["_itemClass", "_vehicle", ["_amount", 1], ["_showHint", false, [false]]]; params ["_item", "_vehicle", ["_amount", 1]];
TRACE_3("params",_itemClass,_vehicle,_amount); TRACE_3("params",_item,_vehicle,_amount);
// Get config sensitive case name
if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
for "_i" from 1 to _amount do { for "_i" from 1 to _amount do {
[_itemClass, _vehicle] call FUNC(loadItem); [_item, _vehicle] call FUNC(loadItem);
};
} else {
[_item, _vehicle] call FUNC(loadItem);
_item = typeOf _item;
}; };
// Invoke listenable event // Invoke listenable event
["ace_cargoAdded", [_itemClass, _vehicle, _amount]] call CBA_fnc_globalEvent; ["ace_cargoAdded", [_item, _vehicle, _amount]] call CBA_fnc_globalEvent;

View File

@ -1,32 +1,34 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Dystopian * Author: Dystopian
* Create actions for nearest vehicles with cargo. * Creates actions for nearest vehicles with cargo.
* *
* Arguments: * Arguments:
* 0: Target <OBJECT> * 0: Holder object (vehicle) <OBJECT>
* *
* Return Value: * Return Value:
* Child actions <ARRAY> * Child actions <ARRAY>
* *
* Example: * Example:
* [cursorObject] call ace_cargo_fnc_addCargoVehiclesActions * cursorObject call ace_cargo_fnc_addCargoVehiclesActions
* *
* Public: No * Public: No
*/ */
params ["_target"]; params ["_vehicle"];
private _statement = { private _statement = {
params ["_target", "_player", "_vehicle"]; params ["_item", "_loader", "_vehicle"];
[_player, _target, _vehicle] call FUNC(startLoadIn);
[_loader, _item, _vehicle] call FUNC(startLoadIn);
}; };
private _vehicles = (nearestObjects [_target, GVAR(cargoHolderTypes), (MAX_LOAD_DISTANCE + 10)]) select { private _vehicles = (nearestObjects [_vehicle, GVAR(cargoHolderTypes), MAX_LOAD_DISTANCE + 10]) select {
private _hasCargoConfig = 1 == getNumber (configOf _x >> QGVAR(hasCargo)); _x != _vehicle &&
private _hasCargoPublic = _x getVariable [QGVAR(hasCargo), false]; {alive _x} &&
(_hasCargoConfig || {_hasCargoPublic}) && {_x != _target} && {alive _x} && {locked _x < 2} && {locked _x < 2} &&
{([_target, _x] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE} {_x getVariable [QGVAR(hasCargo), getNumber (configOf _x >> QGVAR(hasCargo)) == 1]} &&
{([_vehicle, _x] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}
}; };
[_vehicles, _statement, _target] call EFUNC(interact_menu,createVehiclesActions) [_vehicles, _statement, _vehicle] call EFUNC(interact_menu,createVehiclesActions)

View File

@ -1,48 +1,57 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Check if item can be loaded into other Object. * Checks if the item can be loaded into another object.
* *
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item to be loaded <STRING> or <OBJECT>
* 1: Holder Object (Vehicle) <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Ignore interaction distance and stability checks <BOOL> * 2: Ignore interaction distance and stability checks <BOOL> (default: false)
* *
* Return Value: * Return Value:
* Can load in <BOOL> * Can be loaded <BOOL>
* *
* Example: * Example:
* [item, holder] call ace_cargo_fnc_canLoadItemIn * ["ACE_Wheel", cursorObject] call ace_cargo_fnc_canLoadItemIn
* *
* Public: No * Public: No
*/ */
params [["_item", "", [objNull,""]], "_vehicle", ["_ignoreInteraction", false]]; params ["_item", "_vehicle", ["_ignoreInteraction", false]];
if ((!_ignoreInteraction) && {speed _vehicle > 1 || {((getPos _vehicle) select 2) > 3}}) exitWith {TRACE_1("vehicle not stable",_vehicle); false}; // Check if vehicle is stable
if (!_ignoreInteraction && {speed _vehicle > 1 || {((getPos _vehicle) select 2) > 3}}) exitWith {
TRACE_1("vehicle not stable",_vehicle);
if (_item isEqualType objNull && {{alive _x && {getText (configOf _x >> "simulation") != "UAVPilot"}} count crew _item > 0}) exitWith { false // return
TRACE_1("item is occupied",_item);
false
}; };
private _itemSize = [_item] call FUNC(getSizeItem); // If there is crew that isn't UAV crew, exit
private _validItem = false; if (_item isEqualType objNull && {(crew _item) findIf {alive _x && {!unitIsUAV _x}} != -1}) exitWith {
if (_item isEqualType "") then { TRACE_1("item is occupied",_item);
_validItem =
isClass (configFile >> "CfgVehicles" >> _item) && false // return
{getNumber (configFile >> "CfgVehicles" >> _item >> QGVAR(canLoad)) == 1}; };
private _itemSize = _item call FUNC(getSizeItem);
private _validItem = if (_item isEqualType "") then {
private _config = configFile >> "CfgVehicles" >> _item;
isClass _config &&
{getNumber (_config >> QGVAR(canLoad)) == 1}
} else { } else {
_validItem = alive _item &&
(alive _item) && {_item getVariable [QGVAR(canLoad), getNumber (configOf _item >> QGVAR(canLoad)) == 1]} &&
{_ignoreInteraction || {([_item, _vehicle] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}} && {_ignoreInteraction || {([_item, _vehicle] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}} &&
{!(_item getVariable [QEGVAR(cookoff,isCookingOff), false])} && {!(_item getVariable [QEGVAR(cookoff,isCookingOff), false])} && // do not load items that are cooking off
{isNull(_item getVariable [QEGVAR(refuel,nozzle), objNull])} && // Objects which have a refueling nozzle connected to them cannot be loaded {isNull (_item getVariable [QEGVAR(refuel,nozzle), objNull])} && // objects which have a refueling nozzle connected to them cannot be loaded
{isNull(_item getVariable [QEGVAR(refuel,ownedNozzle), objNull])}; // Fuel sources which have their nozzle out cannot be loaded {isNull (_item getVariable [QEGVAR(refuel,ownedNozzle), objNull])} // fuel sources which have their nozzle out cannot be loaded
}; };
_validItem && _validItem &&
{_itemSize > 0} &&
{alive _vehicle} && {alive _vehicle} &&
{_itemSize <= ([_vehicle] call FUNC(getCargoSpaceLeft))} && {locked _vehicle < 2} &&
{locked _vehicle < 2} {_vehicle getVariable [QGVAR(hasCargo), getNumber (configOf _vehicle >> QGVAR(hasCargo)) == 1]} &&
{_itemSize >= 0} &&
{_itemSize <= (_vehicle call FUNC(getCargoSpaceLeft)) max 0}

View File

@ -1,30 +1,44 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal, ViperMaul * Author: Glowbal, ViperMaul
* Check if item can be unloaded. * Checks if the item can be unloaded from another object.
* *
* Arguments: * Arguments:
* 0: loaded Object <OBJECT> * 0: Item to be unloaded <STRING> or <OBJECT>
* 1: Object <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Unloader (player) <OBJECT> (default: objNull) * 2: Unit doing the unloading <OBJECT> (default: objNull)
* 3: Ignore interaction distance and stability checks <BOOL> (default: false)
* 4: Ignore finding a suitable position <BOOL> (default: false)
* *
* Return Value: * Return Value:
* Can be unloaded <BOOL> * Can be unloaded <BOOL>
* *
* Example: * Example:
* [item, holder] call ace_cargo_fnc_canUnloadItem * ["ACE_Wheel", cursorObject] call ace_cargo_fnc_canUnloadItem
* *
* Public: No * Public: No
*/ */
params ["_item", "_vehicle", ["_unloader", objNull]]; params ["_item", "_vehicle", ["_unloader", objNull], ["_ignoreInteraction", false], ["_ignoreFindPosition", false]];
TRACE_2("params",_item,_vehicle); TRACE_2("params",_item,_vehicle);
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; // Get config sensitive case name
if !(_item in _loaded) exitWith {false}; if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
};
private _itemClass = if (_item isEqualType "") then {_item} else {typeOf _item}; if !(_item in (_vehicle getVariable [QGVAR(loaded), []])) exitWith {false};
private _emptyPos = [_vehicle, _itemClass, _unloader] call EFUNC(common,findUnloadPosition); private _validItem = if (_item isEqualType objNull) then {
alive _item
} else {
true
};
(count _emptyPos) == 3 _validItem &&
{alive _vehicle} &&
{locked _vehicle < 2} &&
{_vehicle getVariable [QGVAR(hasCargo), getNumber (configOf _vehicle >> QGVAR(hasCargo)) == 1]} &&
{_item call FUNC(getSizeItem) >= 0} &&
{_ignoreInteraction || {([_unloader, _vehicle] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}} &&
{_ignoreFindPosition || {([_vehicle, _item, _unloader, MAX_LOAD_DISTANCE, !_ignoreInteraction] call EFUNC(common,findUnloadPosition)) isNotEqualTo []}}

View File

@ -1,21 +1,20 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Get the cargo space left on object. * Gets the object's remaining cargo space.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Holder object (vehicle) <OBJECT>
* *
* Return Value: * Return Value:
* Cargo space left <NUMBER> * Cargo space left <NUMBER>
* *
* Example: * Example:
* [object] call ace_cargo_fnc_getCargoSpaceLeft * cursorObject call ace_cargo_fnc_getCargoSpaceLeft
* *
* Public: No * Public: No
*/ */
params ["_object"]; params ["_vehicle"];
// TRACE_1("params",_object);
(_object getVariable [QGVAR(space), getNumber (configOf _object >> QGVAR(space))]) max 0 _vehicle getVariable [QGVAR(space), getNumber (configOf _vehicle >> QGVAR(space))]

View File

@ -4,31 +4,31 @@
* Gets the name of the item, and alternatively the custom name if requested and available. * Gets the name of the item, and alternatively the custom name if requested and available.
* *
* Arguments: * Arguments:
* 0: Target <OBJECT> * 0: Item <STRING> or <OBJECT> (default: "")
* 1: Add custom name part <BOOL> (default: false) * 1: Add custom name <BOOL> (default: false)
* *
* Return Value: * Return Value:
* Item Name <STRING> * Item name <STRING>
* *
* Example: * Example:
* [crate_7] call ace_cargo_fnc_getNameItem * cursorObject call ace_cargo_fnc_getNameItem
* *
* Public: Yes * Public: Yes
*/ */
params ["_object", ["_addCustomPart", false]]; params [["_item", "", [objNull, ""]], ["_addCustomName", false, [false]]];
private _displayName = if (_object isEqualType "") then { private _displayName = if (_item isEqualType "") then {
getText (configFile >> "CfgVehicles" >> _object >> "displayName") getText (configFile >> "CfgVehicles" >> _item >> "displayName")
} else { } else {
getText ((configOf _object) >> "displayName") getText (configOf _item >> "displayName")
}; };
if (_addCustomPart && {!(_object isEqualType "")}) then { if (_addCustomName && {_item isEqualType objNull}) then {
private _customPart = _object getVariable [QGVAR(customName), ""]; private _customName = _item getVariable [QGVAR(customName), ""];
if (_customPart isNotEqualTo "") then { if (_customName isNotEqualTo "") then {
_displayName = _displayName + " [" + _customPart + "]"; _displayName = _displayName + " [" + _customName + "]";
}; };
}; };

View File

@ -1,29 +1,25 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal, kymckay * Author: Glowbal, kymckay
* Get the cargo size of an object. * Gets the cargo size of an object.
* *
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item <STRING> or <OBJECT>
* *
* Return Value: * Return Value:
* Cargo size <NUMBER> (default: -1) * Cargo size <NUMBER> (default: -1)
* *
* Example: * Example:
* [object] call ace_cargo_fnc_getSizeItem * cursorObject call ace_cargo_fnc_getSizeItem
* *
* Public: No * Public: No
*/ */
params ["_item"]; params ["_item"];
// Virtual items are much easier to deal with // Default cargo size is -1 as 0 is a valid size
if (_item isEqualType "") then { if (_item isEqualType "") then {
CARGO_SIZE(_item) GET_NUMBER(configFile >> "CfgVehicles" >> _item >> QGVAR(size),-1)
} else { } else {
if (isNil {_item getVariable QGVAR(size)}) then { _item getVariable [QGVAR(size), GET_NUMBER(configOf _item >> QGVAR(size),-1)]
CARGO_SIZE(typeOf _item)
} else {
_item getVariable QGVAR(size)
};
}; };

View File

@ -1,25 +0,0 @@
#include "..\script_component.hpp"
/*
* Author: mharis001
* Handles an object being deleted by deleting all loaded cargo.
*
* Arguments:
* 0: Object <OBJECT>
*
* Return Value:
* None
*
* Example:
* [_object] call ace_cargo_fnc_handleDeleted
*
* Public: No
*/
params ["_object"];
{
if (_x isEqualType objNull) then {
detach _x;
deleteVehicle _x;
};
} forEach (_object getVariable [QGVAR(loaded), []]);

View File

@ -1,7 +1,9 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: mharis001, Glowbal
* Handle object being destroyed. * Handles an object being destroyed/deleted.
* If object contained loaded cargo, the cargo is deleted.
* If object was loaded cargo, it's removed from loaded cargo list.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Object <OBJECT>
@ -10,23 +12,34 @@
* None * None
* *
* Example: * Example:
* [_object] call ace_cargo_fnc_handleDestroyed * cursorObject call ace_cargo_fnc_handleDestroyed
* *
* Public: No * Public: No
*/ */
params ["_vehicle"]; params ["_object"];
TRACE_1("params",_vehicle);
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; private _loaded = _object getVariable [QGVAR(loaded), []];
if (_loaded isEqualTo []) exitWith {};
if (_loaded isNotEqualTo []) then {
// Delete all cargo
{ {
// TODO Do we want to be able to recover destroyed equipment?
if (_x isEqualType objNull) then { if (_x isEqualType objNull) then {
detach _x; detach _x;
deleteVehicle _x; deleteVehicle _x;
}; };
} forEach _loaded; } forEach _loaded;
[_vehicle] call FUNC(validateCargoSpace); // In case vehicle is killed, but not deleted, reset loaded list
_object setVariable [QGVAR(loaded), [], true];
};
// Update remaining cargo space, if loaded as cargo in a vehicle
private _vehicle = attachedTo _object;
if (!isNull _vehicle && {_object in (_vehicle getVariable [QGVAR(loaded), []])}) then {
private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
private _itemSize = (_object call FUNC(getSizeItem)) max 0; // don't let negative size items increase space
_vehicle setVariable [QGVAR(space), _cargoSpace + _itemSize, true];
};

View File

@ -4,51 +4,57 @@
* Initializes variables for loadable objects. Called from init EH. * Initializes variables for loadable objects. Called from init EH.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Item <OBJECT>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [object] call ace_cargo_fnc_initObject * cursorObject call ace_cargo_fnc_initObject
* *
* Public: No * Public: No
*/ */
params ["_object"]; // Dedicated servers and HCs do not require action menus
private _type = typeOf _object; if (!hasInterface) exitWith {};
private _config = configOf _object;
TRACE_2("params",_object,_type);
// If object had size given to it via eden/public then override config canLoad setting params ["_item"];
private _canLoadPublic = _object getVariable [QGVAR(canLoad), false]; private _type = typeOf _item;
if (!(_canLoadPublic isEqualType false)) then { TRACE_2("params",_item,_type);
WARNING_4("%1[%2] - Variable %3 is %4 - Should be bool",_object,_type,QGVAR(canLoad),_canLoadPublic);
// If object had size given to it via eden/public, then override config canLoad setting
private _canLoadPublic = _item getVariable QGVAR(canLoad);
private _canLoadPublicDefined = !isNil "_canLoadPublic";
if (_canLoadPublicDefined && {!(_canLoadPublic isEqualType false)}) then {
WARNING_4("%1[%2] - Variable %3 is %4 - Should be bool",_item,_type,QGVAR(canLoad),_canLoadPublic);
}; };
private _canLoadConfig = getNumber (_config >> QGVAR(canLoad)) == 1;
private _canLoadConfig = getNumber (configOf _item >> QGVAR(canLoad)) == 1;
// Nothing to do here if object can't be loaded // Nothing to do here if object can't be loaded
if !(_canLoadConfig || {_canLoadPublic in [true, 1]}) exitWith {}; if !((_canLoadPublicDefined && {_canLoadPublic in [true, 1]}) || {!_canLoadPublicDefined && {_canLoadConfig}}) exitWith {};
// Servers and HCs do not require action menus (beyond this point)
if !(hasInterface) exitWith {};
// Unnecessary to add actions to an object class that's already got them // Unnecessary to add actions to an object class that's already got them
if (_type in GVAR(initializedItemClasses)) exitWith {}; if (_type in GVAR(initializedItemClasses)) exitWith {};
if (_object getVariable [QGVAR(initObject),false]) exitWith {}; if (_item getVariable [QGVAR(initObject),false]) exitWith {};
// Objects given size via eden have their actions added to the object // Objects given size via eden have their actions added to the object
// So this function may run for multiple of the same class in that case // So this function may run for multiple of the same class in that case
if (_canLoadConfig) then { if (_canLoadConfig) then {
GVAR(initializedItemClasses) pushBack _type; GVAR(initializedItemClasses) pushBack _type;
TRACE_1("Adding load cargo action to class", _type); TRACE_1("Adding load cargo action to class", _type);
{ {
[_type, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToClass); [_type, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToClass);
} forEach GVAR(objectActions); } forEach GVAR(objectActions);
} else { } else {
_object setVariable [QGVAR(initObject),true]; _item setVariable [QGVAR(initObject), true];
TRACE_1("Adding load cargo action to object", _object);
TRACE_1("Adding load cargo action to object", _item);
{ {
[_object, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToObject); [_item, 0, ["ACE_MainActions"], _x] call EFUNC(interact_menu,addActionToObject);
} forEach GVAR(objectActions); } forEach GVAR(objectActions);
}; };

View File

@ -10,7 +10,7 @@
* None * None
* *
* Example: * Example:
* [vehicle] call ace_cargo_fnc_initVehicle * cursorObject call ace_cargo_fnc_initVehicle
* *
* Public: No * Public: No
*/ */
@ -21,7 +21,7 @@ TRACE_1("params", _vehicle);
private _type = typeOf _vehicle; private _type = typeOf _vehicle;
private _config = configOf _vehicle; private _config = configOf _vehicle;
// If vehicle had space given to it via eden/public then override config hasCargo setting // If vehicle had space given to it via eden/public, then override config hasCargo setting
private _hasCargoPublic = _vehicle getVariable [QGVAR(hasCargo), false]; private _hasCargoPublic = _vehicle getVariable [QGVAR(hasCargo), false];
private _hasCargoConfig = getNumber (_config >> QGVAR(hasCargo)) == 1; private _hasCargoConfig = getNumber (_config >> QGVAR(hasCargo)) == 1;
@ -29,41 +29,53 @@ private _hasCargoConfig = getNumber (_config >> QGVAR(hasCargo)) == 1;
if !(_hasCargoConfig || _hasCargoPublic) exitWith {}; if !(_hasCargoConfig || _hasCargoPublic) exitWith {};
// Check if cargo is in cargo holder types (checked when trying to search for loadable objects) // Check if cargo is in cargo holder types (checked when trying to search for loadable objects)
private _addCargoType = true; private _addCargoType = GVAR(cargoHolderTypes) findIf {_type isKindOf _x} == -1;
{
if (_type isKindOf _x) exitWith {_addCargoType = false};
} forEach GVAR(cargoHolderTypes);
TRACE_2("",_addCargoType,_type); TRACE_2("",_addCargoType,_type);
if (_addCargoType) then { if (_addCargoType) then {
GVAR(cargoHolderTypes) pushBack _type; GVAR(cargoHolderTypes) pushBack _type;
}; };
// Vehicle can have default ace cargo in its config // If already initialised (both actions and cargo), then skip
if (_vehicle getVariable [QGVAR(initVehicle), false]) exitWith {};
// Vehicles can have default ace cargo in their config
if (isServer) then { if (isServer) then {
_vehicle setVariable [QGVAR(initVehicle), true];
private _cargoClassname = "";
private _cargoCount = 0;
{ {
private _cargoClassname = getText (_x >> "type"); _cargoClassname = getText (_x >> "type");
private _cargoCount = getNumber (_x >> "amount"); _cargoCount = getNumber (_x >> "amount");
TRACE_3("adding ACE_Cargo", (configName _x), _cargoClassname, _cargoCount);
TRACE_3("adding ACE_Cargo",configName _x,_cargoClassname,_cargoCount);
["ace_addCargo", [_cargoClassname, _vehicle, _cargoCount]] call CBA_fnc_localEvent; ["ace_addCargo", [_cargoClassname, _vehicle, _cargoCount]] call CBA_fnc_localEvent;
} forEach ("true" configClasses (_config >> QUOTE(ADDON) >> "Cargo")); } forEach ("true" configClasses (_config >> QUOTE(ADDON) >> "cargo"));
}; };
// Servers and HCs do not require action menus (beyond this point) // Servers and HCs do not require action menus (beyond this point)
if !(hasInterface) exitWith {}; if (!hasInterface) exitWith {};
// Unnecessary to add actions to a vehicle class that's already got them // Unnecessary to add actions to a vehicle class that's already got them
if (_type in GVAR(initializedVehicleClasses)) exitWith {}; if (_type in GVAR(initializedVehicleClasses)) exitWith {};
if (_vehicle getVariable [QGVAR(initVehicle),false]) exitWith {};
// Vehicles given cargo via eden have their actions added to the object // Vehicles given cargo via eden have their actions added to the object
// So this function may run for multiple of the same class in that case // So this function may run for multiple of the same class in that case
if (_hasCargoConfig) then { if (_hasCargoConfig) then {
GVAR(initializedVehicleClasses) pushBack _type; GVAR(initializedVehicleClasses) pushBack _type;
TRACE_1("Adding unload cargo action to class", _type); TRACE_1("Adding unload cargo action to class", _type);
[_type, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToClass); [_type, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToClass);
} else { } else {
_vehicle setVariable [QGVAR(initVehicle), true]; _vehicle setVariable [QGVAR(initVehicle), true];
TRACE_1("Adding unload cargo action to object", _vehicle); TRACE_1("Adding unload cargo action to object", _vehicle);
[_vehicle, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToObject); [_vehicle, 0, ["ACE_MainActions"], GVAR(vehicleAction)] call EFUNC(interact_menu,addActionToObject);
}; };
@ -71,24 +83,31 @@ if (_hasCargoConfig) then {
if (_vehicle isKindOf "Air") then { if (_vehicle isKindOf "Air") then {
private _condition = { private _condition = {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(enable) && {[_player, _target, []] call EFUNC(common,canInteractWith)} && { GVAR(enable) &&
private _turretPath = _player call CBA_fnc_turretPath; {[_player, _target, []] call EFUNC(common,canInteractWith)} && {
(_player == (driver _target)) || // pilot private _turretPath = _target unitTurret _player;
{(getNumber (([_target, _turretPath] call CBA_fnc_getTurret) >> "isCopilot")) == 1} || // coPilot
{_turretPath in (getArray (configOf _target >> QGVAR(loadmasterTurrets)))}} // loadMaster turret from config (_player == currentPilot _target) || // Pilot/Co-pilot
{(getNumber ([_target, _turretPath] call CBA_fnc_getTurret >> "isCopilot")) == 1} || // Co-pilot
{_turretPath in (getArray (configOf _target >> QGVAR(loadmasterTurrets)))}
}
}; };
private _statement = { private _statement = {
//IGNORE_PRIVATE_WARNING ["_target", "_player"]; //IGNORE_PRIVATE_WARNING ["_target", "_player"];
GVAR(interactionVehicle) = _target; GVAR(interactionVehicle) = _target;
GVAR(interactionParadrop) = true; GVAR(interactionParadrop) = true;
createDialog QGVAR(menu); createDialog QGVAR(menu);
}; };
private _text = localize LSTRING(openMenu);
private _text = LLSTRING(openMenu);
private _icon = ""; private _icon = "";
private _action = [QGVAR(openMenu), _text, _icon, _statement, _condition] call EFUNC(interact_menu,createAction); private _action = [QGVAR(openMenu), _text, _icon, _statement, _condition] call EFUNC(interact_menu,createAction);
// Self action on the vehicle
if (_hasCargoConfig) then { if (_hasCargoConfig) then {
[_type, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToClass); // self action on the vehicle [_type, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToClass);
} else { } else {
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject); [_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
}; };

View File

@ -1,27 +1,36 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Load object into vehicle. * Loads an object into a vehicle.
* Objects loaded via classname remain virtual until unloaded. * Objects loaded via classname remain virtual until unloaded.
* *
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item to be loaded <STRING> or <OBJECT> (default: "")
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT> (default: objNull)
* 2: Ignore interaction distance and stability checks <BOOL> * 2: Ignore interaction distance and stability checks <BOOL> (default: false)
* *
* Return Value: * Return Value:
* Object loaded <BOOL> * Object loaded <BOOL>
* *
* Example: * Example:
* [object, vehicle] call ace_cargo_fnc_loadItem * ["ACE_Wheel", cursorObject] call ace_cargo_fnc_loadItem
* *
* Public: Yes * Public: Yes
*/ */
params [["_item","",[objNull,""]], ["_vehicle",objNull,[objNull]], ["_ignoreInteraction", false]]; params [["_item", "", [objNull, ""]], ["_vehicle", objNull, [objNull]], ["_ignoreInteraction", false, [false]]];
TRACE_2("params",_item,_vehicle); TRACE_3("params",_item,_vehicle,_ignoreInteraction);
if !([_item, _vehicle, _ignoreInteraction] call FUNC(canLoadItemIn)) exitWith {TRACE_2("cannot load",_item,_vehicle); false}; // Get config sensitive case name
if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
};
if !([_item, _vehicle, _ignoreInteraction] call FUNC(canLoadItemIn)) exitWith {
TRACE_3("cannot load",_item,_vehicle,_ignoreInteraction);
false // return
};
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; private _loaded = _vehicle getVariable [QGVAR(loaded), []];
_loaded pushBack _item; _loaded pushBack _item;
@ -29,10 +38,12 @@ _vehicle setVariable [QGVAR(loaded), _loaded, true];
TRACE_1("added to loaded array",_loaded); TRACE_1("added to loaded array",_loaded);
private _space = [_vehicle] call FUNC(getCargoSpaceLeft); // Update cargo space remaining
private _itemSize = [_item] call FUNC(getSizeItem); private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
_vehicle setVariable [QGVAR(space), _space - _itemSize, true]; private _itemSize = (_item call FUNC(getSizeItem)) max 0; // don't let negative size items increase space
_vehicle setVariable [QGVAR(space), _cargoSpace - _itemSize, true];
// Attach object 100m below vehicle
if (_item isEqualType objNull) then { if (_item isEqualType objNull) then {
detach _item; detach _item;
_item attachTo [_vehicle, [0, 0, -100]]; _item attachTo [_vehicle, [0, 0, -100]];
@ -49,8 +60,11 @@ if (_item isEqualType objNull) then {
[QEGVAR(zeus,removeObjects), [[_item], _objectCurators]] call CBA_fnc_serverEvent; [QEGVAR(zeus,removeObjects), [[_item], _objectCurators]] call CBA_fnc_serverEvent;
}; };
// Some objects below water will take damage over time and eventualy become "water logged" and unfixable (because of negative z attach) // Some objects below water will take damage over time, eventually becoming "water logged" and unfixable (because of negative z attach)
[_item, "blockDamage", "ACE_cargo", true] call EFUNC(common,statusEffect_set); [_item, "blockDamage", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
}; };
true // Invoke listenable event
["ace_cargoLoaded", [_item, _vehicle]] call CBA_fnc_globalEvent;
true // return

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Handle the UI data display. * Handles the UI data display.
* *
* Arguments: * Arguments:
* 0: Display <DISPLAY> * 0: Display <DISPLAY>
@ -10,7 +10,7 @@
* None * None
* *
* Example: * Example:
* [display] call ace_cargo_fnc_onMenuOpen * display call ace_cargo_fnc_onMenuOpen
* *
* Public: No * Public: No
*/ */
@ -22,37 +22,70 @@ params ["_display"];
uiNamespace setVariable [QGVAR(menuDisplay), _display]; uiNamespace setVariable [QGVAR(menuDisplay), _display];
if (GVAR(interactionParadrop)) then { if (GVAR(interactionParadrop)) then {
(_display displayCtrl 12) ctrlSetText (localize LSTRING(paradropButton)); (_display displayCtrl 12) ctrlSetText LLSTRING(paradropButton);
}; };
[{ [{
params ["_vehicle", "_pfhID"];
disableSerialization; disableSerialization;
private _display = uiNamespace getVariable QGVAR(menuDisplay); private _display = uiNamespace getVariable QGVAR(menuDisplay);
if (isnil "_display") exitWith {
[_this select 1] call CBA_fnc_removePerFrameHandler; if (isNil "_display") exitWith {
GVAR(interactionVehicle) = nil;
GVAR(interactionParadrop) = nil;
_pfhID call CBA_fnc_removePerFrameHandler;
}; };
if (isNull GVAR(interactionVehicle) || {(([ACE_player, GVAR(interactionVehicle)] call EFUNC(interaction,getInteractionDistance)) >= MAX_LOAD_DISTANCE) && {(vehicle ACE_player) != GVAR(interactionVehicle)}}) exitWith { // Close menu if in invalid state
if (
!alive _vehicle ||
{locked _vehicle >= 2} ||
{!(_vehicle getVariable [QGVAR(hasCargo), true])} || // if the cargo menu could be opened, the vehicle has QGVAR(hasCargo) in its config or the variable is set using FUNC(setSpace)
{(([ACE_player, _vehicle] call EFUNC(interaction,getInteractionDistance)) >= MAX_LOAD_DISTANCE) && {(vehicle ACE_player) != _vehicle}}
) exitWith {
closeDialog 0; closeDialog 0;
[_this select 1] call CBA_fnc_removePerFrameHandler;
GVAR(interactionVehicle) = nil;
GVAR(interactionParadrop) = nil;
_pfhID call CBA_fnc_removePerFrameHandler;
}; };
private _loaded = GVAR(interactionVehicle) getVariable [QGVAR(loaded), []];
private _ctrl = _display displayCtrl 100; private _ctrl = _display displayCtrl 100;
private _label = _display displayCtrl 2; private _label = _display displayCtrl 2;
// Remove previous entries
lbClear _ctrl; lbClear _ctrl;
// Display item names
private _displayName = "";
private _itemSize = 0;
private _index = -1;
{ {
private _class = if (_x isEqualType "") then {_x} else {typeOf _x}; _displayName = [_x, true] call FUNC(getNameItem);
private _displayName = [_x, true] call FUNC(getNameItem); _itemSize = _x call FUNC(getSizeItem);
if (GVAR(interactionParadrop)) then {
_ctrl lbAdd format ["%1 (%2s)", _displayName, GVAR(paradropTimeCoefficent) * ([_class] call FUNC(getSizeItem))]; if (_itemSize >= 0) then {
_index = if (GVAR(interactionParadrop)) then {
_ctrl lbAdd format ["%1 (%2s)", _displayName, GVAR(paradropTimeCoefficent) * _itemSize]
} else { } else {
_ctrl lbAdd _displayName; _ctrl lbAdd _displayName
}; };
true _ctrl lbSetTooltip [_index, format [LLSTRING(sizeMenu), _itemSize]];
} count _loaded; } else {
// If item has a size < 0, it means it's not loadable
_index = _ctrl lbAdd _displayName;
_label ctrlSetText format[localize LSTRING(labelSpace), [GVAR(interactionVehicle)] call DFUNC(getCargoSpaceLeft)]; _ctrl lbSetTooltip [_index, LLSTRING(unloadingImpossible)];
}, 0, []] call CBA_fnc_addPerFrameHandler; _ctrl lbSetColor [_index, [1, 0, 0, 1]]; // set text to red
_ctrl lbSetSelectColor [_index, [1, 0, 0, 1]];
};
} forEach (_vehicle getVariable [QGVAR(loaded), []]);
_label ctrlSetText format [LLSTRING(labelSpace), (_vehicle call FUNC(getCargoSpaceLeft)) max 0];
}, 0, GVAR(interactionVehicle)] call CBA_fnc_addPerFrameHandler;

View File

@ -1,18 +1,18 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: marc_book, commy2, CAA-Picard * Author: marc_book, commy2, CAA-Picard
* Unload and paradrop object from plane or helicopter. * Unloads and paradrops an object from a plane or helicopter.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Item <STRING> or <OBJECT>
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Show Hint <BOOL> (default: true) * 2: Show Hint <BOOL> (default: true)
* *
* Return Value: * Return Value:
* Object unloaded <BOOL> * Object unloaded <BOOL>
* *
* Example: * Example:
* [object, vehicle] call ace_cargo_fnc_paradropItem * ["ACE_Wheel", vehicle player] call ace_cargo_fnc_paradropItem
* *
* Public: No * Public: No
*/ */
@ -20,38 +20,55 @@
params ["_item", "_vehicle", ["_showHint", true]]; params ["_item", "_vehicle", ["_showHint", true]];
TRACE_2("params",_item,_vehicle); TRACE_2("params",_item,_vehicle);
// Get config sensitive case name
if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
};
// Check if item is actually part of cargo
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; private _loaded = _vehicle getVariable [QGVAR(loaded), []];
if !(_item in _loaded) exitWith {false}; if !(_item in _loaded) exitWith {
false // return
};
// unload item from cargo // Check if item can be unloaded
private _itemSize = _item call FUNC(getSizeItem);
if (_itemSize < 0) exitWith {
false // return
};
// Unload item from cargo
_loaded deleteAt (_loaded find _item); _loaded deleteAt (_loaded find _item);
_vehicle setVariable [QGVAR(loaded), _loaded, true]; _vehicle setVariable [QGVAR(loaded), _loaded, true];
private _cargoSpace = [_vehicle] call FUNC(getCargoSpaceLeft); // Update cargo space remaining
private _itemSize = [_item] call FUNC(getSizeItem); private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
_vehicle setVariable [QGVAR(space), (_cargoSpace + _itemSize), true]; _vehicle setVariable [QGVAR(space), _cargoSpace + _itemSize, true];
(boundingBoxReal _vehicle) params ["_bb1", "_bb2"]; (boundingBoxReal _vehicle) params ["_bb1", "_bb2"];
private _distBehind = ((_bb1 select 1) min (_bb2 select 1)) - 4; // 4 meters behind max bounding box private _distBehind = ((_bb1 select 1) min (_bb2 select 1)) - 4; // 4 meters behind max bounding box
TRACE_1("",_distBehind);
private _posBehindVehicleAGL = _vehicle modelToWorld [0, _distBehind, -2]; private _posBehindVehicleAGL = _vehicle modelToWorld [0, _distBehind, -2];
TRACE_1("",_distBehind);
private _object = _item; private _object = _item;
if (_item isEqualType objNull) then { if (_item isEqualType objNull) then {
detach _object; detach _object;
// hideObjectGlobal must be executed before setPos to ensure light objects are rendered correctly // hideObjectGlobal must be executed before setPos to ensure light objects are rendered correctly
// do both on server to ensure they are executed in the correct order // Do both on server to ensure they are executed in the correct order
[QGVAR(serverUnload), [_object, _posBehindVehicleAGL]] call CBA_fnc_serverEvent; [QGVAR(serverUnload), [_object, _posBehindVehicleAGL]] call CBA_fnc_serverEvent;
} else { } else {
_object = createVehicle [_item, _posBehindVehicleAGL, [], 0, "NONE"]; _object = createVehicle [_item, _posBehindVehicleAGL, [], 0, "NONE"];
_object setPosASL (AGLtoASL _posBehindVehicleAGL); _object setPosASL (AGLtoASL _posBehindVehicleAGL);
}; };
[QEGVAR(common,setVelocity), [_object, ((velocity _vehicle) vectorAdd ((vectorNormalized (vectorDir _vehicle)) vectorMultiply -5))], _object] call CBA_fnc_targetEvent; [QEGVAR(common,setVelocity), [_object, (velocity _vehicle) vectorAdd ((vectorNormalized (vectorDir _vehicle)) vectorMultiply -5)], _object] call CBA_fnc_targetEvent;
// open parachute and ir light effect // Open parachute and IR light effect
[{ [{
params ["_object"]; params ["_object"];
@ -63,7 +80,7 @@ if (_item isEqualType objNull) then {
[QEGVAR(common,fixCollision), _parachute] call CBA_fnc_localEvent; [QEGVAR(common,fixCollision), _parachute] call CBA_fnc_localEvent;
[QEGVAR(common,fixCollision), _object, _object] call CBA_fnc_targetEvent; [QEGVAR(common,fixCollision), _object, _object] call CBA_fnc_targetEvent;
// cannot use setPos on parachutes without them closing down // Cannot use setPos on parachutes without them closing down
_parachute attachTo [_object, [0, 0, 0]]; _parachute attachTo [_object, [0, 0, 0]];
detach _parachute; detach _parachute;
@ -79,10 +96,9 @@ if (_item isEqualType objNull) then {
private _light = "Chemlight_yellow" createVehicle [0, 0, 0]; private _light = "Chemlight_yellow" createVehicle [0, 0, 0];
_light attachTo [_object, [0, 0, 0]]; _light attachTo [_object, [0, 0, 0]];
}; };
}, _object, 0.7] call CBA_fnc_waitAndExecute;
}, [_object], 0.7] call CBA_fnc_waitAndExecute; // Create smoke effect when crate landed
// smoke effect when crate landed
[{ [{
(_this select 0) params ["_object"]; (_this select 0) params ["_object"];
@ -90,21 +106,20 @@ if (_item isEqualType objNull) then {
[_this select 1] call CBA_fnc_removePerFrameHandler; [_this select 1] call CBA_fnc_removePerFrameHandler;
}; };
if (getPos _object select 2 < 1) then { if (getPos _object select 2 < 1) exitWith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
if ((GVAR(disableParadropEffectsClasstypes) findIf {_object isKindOf _x}) == -1) then { if ((GVAR(disableParadropEffectsClasstypes) findIf {_object isKindOf _x}) == -1) then {
private _smoke = "SmokeshellYellow" createVehicle [0, 0, 0]; private _smoke = "SmokeshellYellow" createVehicle [0, 0, 0];
_smoke attachTo [_object, [0, 0, 0]]; _smoke attachTo [_object, [0, 0, 0]];
}; };
[_this select 1] call CBA_fnc_removePerFrameHandler;
}; };
}, 1, _object] call CBA_fnc_addPerFrameHandler;
}, 1, [_object]] call CBA_fnc_addPerFrameHandler;
if (_showHint) then { if (_showHint) then {
[ [
[ [
LSTRING(UnloadedItem), LSTRING(unloadedItem),
[_object, true] call FUNC(getNameItem), [_object, true] call FUNC(getNameItem),
getText (configOf _vehicle >> "displayName") getText (configOf _vehicle >> "displayName")
], ],
@ -115,4 +130,4 @@ if (_showHint) then {
// Invoke listenable event // Invoke listenable event
["ace_cargoUnloaded", [_object, _vehicle, "paradrop"]] call CBA_fnc_globalEvent; ["ace_cargoUnloaded", [_object, _vehicle, "paradrop"]] call CBA_fnc_globalEvent;
true true // return

View File

@ -4,23 +4,28 @@
* Removes a cargo item from the vehicle. * Removes a cargo item from the vehicle.
* *
* Arguments: * Arguments:
* 0: Item <STRING> or <OBJECT> * 0: Item to be removed <STRING> or <OBJECT> (default: "")
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT> (default: objNull)
* 2: Amount <NUMBER> (default: 1) * 2: Amount <NUMBER> (default: 1)
* *
* Return Value: * Return Value:
* Number of items removed <NUMBER> * Number of items removed <NUMBER>
* *
* Example: * Example:
* ["ACE_Wheel", vehicle, 2] call ace_cargo_fnc_removeCargoItem * ["ACE_Wheel", cursorObject, 2] call ace_cargo_fnc_removeCargoItem
* [crate_7, truck] call ace_cargo_fnc_removeCargoItem * [crate_7, truck] call ace_cargo_fnc_removeCargoItem
* *
* Public: Yes * Public: Yes
*/ */
params ["_item", "_vehicle", ["_amount", 1]]; params [["_item", "", [objNull, ""]], ["_vehicle", objNull, [objNull]], ["_amount", 1, [0]]];
TRACE_3("params",_item,_vehicle,_amount); TRACE_3("params",_item,_vehicle,_amount);
// Get config sensitive case name
if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
};
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; private _loaded = _vehicle getVariable [QGVAR(loaded), []];
private _addedSpace = 0; private _addedSpace = 0;
@ -29,31 +34,40 @@ private _itemsRemoved = 0;
private _continue = if (_item isEqualType objNull) then { private _continue = if (_item isEqualType objNull) then {
if !(_item in _loaded) exitWith {false}; if !(_item in _loaded) exitWith {false};
_addedSpace = [_item] call FUNC(getSizeItem);
_addedSpace = (_item call FUNC(getSizeItem)) max 0; // don't let negative size items increase space
_loaded deleteAt (_loaded find _item); _loaded deleteAt (_loaded find _item);
_itemClass = typeOf _item; _itemClass = typeOf _item;
// Delete item
deleteVehicle _item; deleteVehicle _item;
_itemsRemoved = 1; _itemsRemoved = 1;
true true
} else { } else {
{ {
if (_itemsRemoved == _amount) exitWith {}; if (_itemsRemoved == _amount) exitWith {};
if ( if (
(_x isEqualType "" && {_x == _item}) || // Check for classname, case-insensitive (_x isEqualType "" && {_x == _item}) ||
{_x isEqualType objNull && {typeOf _x isEqualTo _item}} {_x isEqualType objNull && {typeOf _x == _item}}
) then { ) then {
INC(_itemsRemoved); INC(_itemsRemoved);
ADD(_addedSpace,[_x] call FUNC(getSizeItem)); _addedSpace = _addedSpace + ((_x call FUNC(getSizeItem)) max 0); // don't let negative size items increase space
// Delete item
if (_x isEqualType objNull) then { if (_x isEqualType objNull) then {
deleteVehicle _x; deleteVehicle _x;
}; };
_loaded set [_forEachIndex, nil]; _loaded set [_forEachIndex, nil];
}; };
} forEach _loaded; } forEach _loaded;
FILTER(_loaded,!isNil "_x"); FILTER(_loaded,!isNil "_x");
true true
}; };
@ -61,8 +75,9 @@ if (!_continue) exitWith {0};
_vehicle setVariable [QGVAR(loaded), _loaded, true]; _vehicle setVariable [QGVAR(loaded), _loaded, true];
private _space = [_vehicle] call FUNC(getCargoSpaceLeft); // Update remaining cargo space
_vehicle setVariable [QGVAR(space), _space + _addedSpace, true]; private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
_vehicle setVariable [QGVAR(space), _cargoSpace + _addedSpace, true];
// Invoke listenable event // Invoke listenable event
["ace_cargoRemoved", [_itemClass, _vehicle, _amount, _itemsRemoved]] call CBA_fnc_globalEvent; ["ace_cargoRemoved", [_itemClass, _vehicle, _amount, _itemsRemoved]] call CBA_fnc_globalEvent;

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: JasperRab * Author: JasperRab
* Renames object. * Renames an object.
* *
* Arguments: * Arguments:
* None * None
@ -10,19 +10,23 @@
* None * None
* *
* Example: * Example:
* [] call ace_cargo_fnc_renameObject * call ace_cargo_fnc_renameObject
* *
* Public: Yes * Public: No
*/ */
private _display = uiNamespace getVariable QGVAR(menuDisplay); private _display = uiNamespace getVariable QGVAR(menuDisplay);
if (isNil "_display") exitWith {}; if (isNil "_display") exitWith {};
private _ctrlEditText = ctrlText 100; private _ctrlEditText = ctrlText 100;
_ctrlEditText = _ctrlEditText select [0, 32]; _ctrlEditText = _ctrlEditText select [0, 32];
if (_ctrlEditText isEqualTo "") then { // custom name has been removed
// Check if custom name has been removed
if (_ctrlEditText isEqualTo "") then {
[LSTRING(clearedCustomName), 3] call EFUNC(common,displayTextStructured); [LSTRING(clearedCustomName), 3] call EFUNC(common,displayTextStructured);
} else { } else {
[[LSTRING(renamedObject), _ctrlEditText], 3] call EFUNC(common,displayTextStructured); [[LSTRING(renamedObject), _ctrlEditText], 3] call EFUNC(common,displayTextStructured);
}; };
GVAR(interactionVehicle) setVariable [QGVAR(customName), _ctrlEditText, true]; GVAR(interactionVehicle) setVariable [QGVAR(customName), _ctrlEditText, true];

View File

@ -1,57 +1,55 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: kymckay * Author: kymckay
* Set the cargo size of any object. Has global effect. * Sets the cargo size of any object. Has global effect.
* Adds the load action menu if necessary. * Adds the load action menu if necessary.
* Negative size makes unloadable. * A negative size disables the object's cargo interactions.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Object <OBJECT> (default: objNull)
* 1: Cargo size <NUMBER> * 1: Cargo size <NUMBER> (default: nil)
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [cursorTarget, 3] call ace_cargo_fnc_setSize * [cursorObject, 3] call ace_cargo_fnc_setSize
* *
* Public: Yes * Public: Yes
*/ */
// Only run this after the settings are initialized
if !(EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(setSize), _this];
};
params [ params [
["_object", objNull, [objNull]], ["_object", objNull, [objNull]],
["_size",nil,[0]] // Default can't be a number since all are valid ["_size", nil, [0]] // default can't be a number since all are valid
]; ];
TRACE_2("setSize",_object,_size); TRACE_2("setSize",_object,_size);
private _oldSize = _object call FUNC(getSizeItem);
// Nothing to do here // Nothing to do here
if ( if (isNil "_size" || {isNull _object} || {_size == _oldSize}) exitWith {};
(isNil "_size") ||
{isNull _object} ||
{_size == _object getVariable [QGVAR(size), CARGO_SIZE(typeOf _object)]}
) exitWith {};
// Apply new size globally // Apply new size globally
// Necessary to update value, even if unloadable, as API could be used again // Necessary to update value, even if disabled, as API could be used again
_object setVariable [QGVAR(canLoad), _size >= 0, true]; _object setVariable [QGVAR(canLoad), _size >= 0, true];
_object setVariable [QGVAR(size), _size, true]; _object setVariable [QGVAR(size), _size, true];
// If no size no need for load action // Update remaining cargo space, if loaded as cargo in a vehicle
if (_size < 0) exitWith {}; private _vehicle = attachedTo _object;
// If an existing ID is present, load action has already been added globally if (!isNull _vehicle && {_object in (_vehicle getVariable [QGVAR(loaded), []])}) then {
private _jipID = _object getVariable QGVAR(setSize_jipID); private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
// Actions should be added to all future JIP players too _vehicle setVariable [QGVAR(space), _cargoSpace + (_oldSize max 0) - (_size max 0), true]; // don't let negative size items increase space
if (isNil "_jipID") then { };
_jipID = [QGVAR(initObject), [_object]] call CBA_fnc_globalEventJIP;
// Actions should be added for all future JIP players too, regardless of size
private _jipID = format [QGVAR(sizeJipID_%1), hashValue _object];
[QGVAR(initObject), _object, _jipID] call CBA_fnc_globalEventJIP;
// Remove from JIP queue if object is deleted
if !(_object getVariable [QGVAR(setSizeRemoveJip), false]) then {
[_jipID, _object] call CBA_fnc_removeGlobalEventJIP; [_jipID, _object] call CBA_fnc_removeGlobalEventJIP;
// Store the ID for any future calls to this function _object setVariable [QGVAR(setSizeRemoveJip), true, true];
_object setVariable [QGVAR(setSize_jipID), _jipID, true];
}; };

View File

@ -1,12 +1,12 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: kymckay * Author: kymckay
* Set the cargo space of any object. Has global effect. * Sets the cargo space of any object. Has global effect.
* Adds the cargo action menu if necessary. * Adds the cargo action menu if necessary.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Vehicle <OBJECT> (default: objNull)
* 1: Cargo space <NUMBER> * 1: Cargo space <NUMBER> (default: nil)
* *
* Return Value: * Return Value:
* None * None
@ -17,49 +17,38 @@
* Public: Yes * Public: Yes
*/ */
// Only run this after the settings are initialized
if !(EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(setSpace), _this];
};
params [ params [
["_vehicle", objNull, [objNull]], ["_vehicle", objNull, [objNull]],
["_space",nil,[0]] // Default can't be a number since all are valid ["_space", nil, [0]] // default can't be a number since all are valid
]; ];
TRACE_2("setSpace",_vehicle,_size); TRACE_2("setSpace",_vehicle,_space);
// Nothing to do here // Nothing to do here
if ( if (isNil "_space" || {isNull _vehicle}) exitWith {};
(isNil "_space") ||
{isNull _vehicle}
) exitWith {};
// Account for cargo already in the vehicle // Account for cargo already in the vehicle
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; private _loaded = _vehicle getVariable [QGVAR(loaded), []];
private _newSpace = _space; private _cargoSpace = _space;
{ {
_newSpace = _newSpace - ([_x] call FUNC(getSizeItem)); _cargoSpace = _cargoSpace - ((_x call FUNC(getSizeItem)) max 0);
} forEach _loaded; } forEach _loaded;
// If the new value is the same as the old, do nothing // If the new value is the same as the old, do nothing
if (_newSpace == (_vehicle getVariable [QGVAR(space), CARGO_SPACE(typeOf _vehicle)])) exitwith {}; if (_cargoSpace == (_vehicle call FUNC(getCargoSpaceLeft))) exitwith {};
// Apply new space globally // Apply new space globally
_vehicle setVariable [QGVAR(space), _newSpace, true];
// Necessary to update value, even if no space, as API could be used again // Necessary to update value, even if no space, as API could be used again
_vehicle setVariable [QGVAR(hasCargo), _space > 0, true]; _vehicle setVariable [QGVAR(hasCargo), _space > 0, true];
_vehicle setVariable [QGVAR(space), _cargoSpace, true];
// If no cargo space no need for cargo menu // Space should be added for all future JIP players too, regardless of space
if (_space <= 0) exitWith {}; private _jipID = format [QGVAR(spaceJipID_%1), hashValue _vehicle];
[QGVAR(initVehicle), _vehicle, _jipID] call CBA_fnc_globalEventJIP;
// If an existing ID is present, cargo menu has already been added globally // Remove from JIP queue if vehicle is deleted
private _jipID = _vehicle getVariable QGVAR(setSpace_jipID); if !(_vehicle getVariable [QGVAR(setSpaceRemoveJip), false]) then {
// Cargo menu should be added to all future JIP players too
if (isNil "_jipID") then {
_jipID = [QGVAR(initVehicle), [_vehicle]] call CBA_fnc_globalEventJIP;
[_jipID, _vehicle] call CBA_fnc_removeGlobalEventJIP; [_jipID, _vehicle] call CBA_fnc_removeGlobalEventJIP;
// Store the ID for any future calls to this function _vehicle setVariable [QGVAR(setSpaceRemoveJip), true, true];
_vehicle setVariable [QGVAR(setSpace_jipID), _jipID, true];
}; };

View File

@ -1,67 +1,103 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Start load item. * Starts loading item.
* *
* Arguments: * Arguments:
* 0: Player <OBJECT> * 0: Unit doing the loading <OBJECT>
* 1: Object <OBJECT> * 1: Item to be loaded <OBJECT>
* 2: Vehicle <OBJECT> (Optional) * 2: Holder object (vehicle) <OBJECT> (default: objNull)
* *
* Return Value: * Return Value:
* Load ProgressBar Started <BOOL> * Load ProgressBar Started <BOOL>
* *
* Example: * Example:
* [player, cursorTarget] call ace_cargo_fnc_startLoadIn * [player, cursorObject] call ace_cargo_fnc_startLoadIn
* *
* Public: No * Public: No
*/ */
params ["_player", "_object", ["_cargoVehicle", objNull]]; params ["_loader", "_item", ["_vehicle", objNull]];
TRACE_3("params",_player,_object,_cargoVehicle); TRACE_3("params",_loader,_item,_vehicle);
private _vehicle = _cargoVehicle;
if (isNull _vehicle) then { if (isNull _vehicle) then {
{ {
if ([_object, _x] call FUNC(canLoadItemIn)) exitWith {_vehicle = _x}; if ([_item, _x] call FUNC(canLoadItemIn)) exitWith {
} forEach (nearestObjects [_player, GVAR(cargoHolderTypes), (MAX_LOAD_DISTANCE + 10)]); _vehicle = _x;
};
} forEach (nearestObjects [_loader, GVAR(cargoHolderTypes), MAX_LOAD_DISTANCE + 10]);
}; };
if (isNull _vehicle) exitWith { if (isNull _vehicle) exitWith {
TRACE_3("Could not find vehicle",_player,_object,_vehicle); TRACE_3("Could not find vehicle",_loader,_item,_vehicle);
false
false // return
}; };
private _return = false;
// Start progress bar // Start progress bar
if ([_object, _vehicle] call FUNC(canLoadItemIn)) then { if ([_item, _vehicle] call FUNC(canLoadItemIn)) then {
[_player, _object, true] call EFUNC(common,claim); private _duration = GVAR(loadTimeCoefficient) * (_item call FUNC(getSizeItem));
private _size = [_object] call FUNC(getSizeItem);
// If load time is 0, don't show a progress bar
if (_duration <= 0) exitWith {
["ace_loadCargo", [_item, _vehicle]] call CBA_fnc_localEvent;
true // return
};
// Claim so nobody else can interact with it
[_loader, _item, true] call EFUNC(common,claim);
[ [
GVAR(loadTimeCoefficient) * _size, _duration,
[_object, _vehicle], [_item, _vehicle],
{ {
TRACE_1("load finish",_this); TRACE_1("load finish",_this);
[objNull, _this select 0 select 0, true] call EFUNC(common,claim); [objNull, _this select 0 select 0, true] call EFUNC(common,claim);
["ace_loadCargo", _this select 0] call CBA_fnc_localEvent; ["ace_loadCargo", _this select 0] call CBA_fnc_localEvent;
}, },
{ {
TRACE_1("load fail",_this); TRACE_1("load fail",_this);
[objNull, _this select 0 select 0, true] call EFUNC(common,claim); (_this select 0) params ["_item", "_vehicle"];
[objNull, _item, true] call EFUNC(common,claim);
// Fix cancelling loading a carried item
if (!isNull attachedTo _item) then {
detach _item;
// Prevent coliisions between item and vehicle
[QEGVAR(common,fixCollision), _vehicle, _vehicle] call CBA_fnc_targetEvent;
[QEGVAR(common,fixCollision), _item, _item] call CBA_fnc_targetEvent;
[QEGVAR(common,fixPosition), _item, _item] call CBA_fnc_targetEvent;
[QEGVAR(common,fixFloating), _item, _item] call CBA_fnc_targetEvent;
};
}, },
localize LSTRING(LoadingItem), LLSTRING(loadingItem),
{ {
(_this select 0) params ["_item", "_target"]; (_this select 0) call FUNC(canLoadItemIn)
(alive _target) && {locked _target < 2} && {alive _item}
&& {([_item, _target] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}
}, },
["isNotSwimming"] ["isNotSwimming"]
] call EFUNC(common,progressBar); ] call EFUNC(common,progressBar);
_return = true;
true // return
} else { } else {
private _displayName = [_object, true] call FUNC(getNameItem); [[LSTRING(loadingFailed), [_item, true] call FUNC(getNameItem)], 3] call EFUNC(common,displayTextStructured);
[[LSTRING(LoadingFailed), _displayName], 3] call EFUNC(common,displayTextStructured);
// Fix cancelling loading a carried item
if (!isNull attachedTo _item) then {
detach _item;
// Prevent coliisions between item and vehicle
[QEGVAR(common,fixCollision), _vehicle, _vehicle] call CBA_fnc_targetEvent;
[QEGVAR(common,fixCollision), _item, _item] call CBA_fnc_targetEvent;
[QEGVAR(common,fixPosition), _item, _item] call CBA_fnc_targetEvent;
[QEGVAR(common,fixFloating), _item, _item] call CBA_fnc_targetEvent;
}; };
_return false // return
};

View File

@ -1,16 +1,16 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * Author: Glowbal
* Start unload action. * Starts unloading item selected in the cargo menu.
* *
* Arguments: * Arguments:
* None * 0: Unit doing the unloading <OBJECT>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [] call ace_cargo_fnc_startUnload * player call ace_cargo_fnc_startUnload
* *
* Public: No * Public: No
*/ */
@ -18,76 +18,92 @@
disableSerialization; disableSerialization;
private _display = uiNamespace getVariable QGVAR(menuDisplay); private _display = uiNamespace getVariable QGVAR(menuDisplay);
if (isNil "_display") exitWith {}; if (isNil "_display") exitWith {};
private _loaded = GVAR(interactionVehicle) getVariable [QGVAR(loaded), []]; private _loaded = GVAR(interactionVehicle) getVariable [QGVAR(loaded), []];
if (_loaded isEqualTo []) exitWith {}; if (_loaded isEqualTo []) exitWith {};
private _ctrl = _display displayCtrl 100; // This can be an object or a classname string
private _item = _loaded param [lbCurSel (_display displayCtrl 100), nil];
private _selected = (lbCurSel _ctrl) max 0; if (isNil "_item") exitWith {};
if (count _loaded <= _selected) exitWith {}; params ["_unit"];
private _item = _loaded select _selected; // This can be an object or a classname string
if (GVAR(interactionParadrop)) exitWith { if (GVAR(interactionParadrop)) exitWith {
// If drop time is 0 don't show a progress bar // Close the cargo menu
if (GVAR(paradropTimeCoefficent) == 0) exitWith { closeDialog 0;
private _duration = GVAR(paradropTimeCoefficent) * (_item call FUNC(getSizeItem));
// If drop time is 0, don't show a progress bar
if (_duration <= 0) exitWith {
[QGVAR(paradropItem), [_item, GVAR(interactionVehicle)]] call CBA_fnc_localEvent; [QGVAR(paradropItem), [_item, GVAR(interactionVehicle)]] call CBA_fnc_localEvent;
}; };
// Start progress bar - paradrop // Start progress bar - paradrop
private _size = [_item] call FUNC(getSizeItem); // Delay execution by a frame, to avoid progress bar stopping prematurely because of the cargo menu still being open
[ [EFUNC(common,progressBar), [
GVAR(paradropTimeCoefficent) * _size, _duration,
[_item, GVAR(interactionVehicle), ACE_player], [_item, GVAR(interactionVehicle)],
{ {
(_this select 0) params ["_item", "_target", "_player"]; [QGVAR(paradropItem), _this select 0] call CBA_fnc_localEvent;
[QGVAR(paradropItem), [_item, _target]] call CBA_fnc_localEvent;
}, },
{ {
params ["_args", "", "", "_errorCode"]; // show warning if we failed because of flight conditions params ["", "", "", "_errorCode"];
if (_errorCode == 3) then {
_args params ["_item", "_target", "_player"]; if (_errorCode == 3) then { // show warning if we failed because of flight conditions
[localize LSTRING(unlevelFlightWarning)] call EFUNC(common,displayTextStructured); [LSTRING(unlevelFlightWarning)] call EFUNC(common,displayTextStructured);
}; };
}, },
localize LSTRING(UnloadingItem), LLSTRING(unloadingItem),
{ {
(_this select 0) params ["_item", "_target", "_player"]; (_this select 0) params ["", "_target"];
if ((acos ((vectorUp _target) select 2)) > 30) exitWith {false}; // check flight level if ((acos ((vectorUp _target) select 2)) > 30) exitWith {false}; // check flight level
if (((getPos _target) select 2) < 25) exitWith {false}; // check height if (((getPos _target) select 2) < 25) exitWith {false}; // check height
if ((speed _target) < -5) exitWith {false}; // check reverse if ((speed _target) < -5) exitWith {false}; // check reverse
true true
}, },
["isNotSwimming", "isNotInside"], ["isNotSwimming", "isNotInside"],
false false
] call EFUNC(common,progressBar); ]] call CBA_fnc_execNextFrame;
}; };
// Start progress bar - normal ground unload // Start progress bar - normal ground unload
if ([_item, GVAR(interactionVehicle), ACE_player] call FUNC(canUnloadItem)) then { if ([_item, GVAR(interactionVehicle), _unit] call FUNC(canUnloadItem)) then {
private _size = [_item] call FUNC(getSizeItem); // Close the cargo menu
closeDialog 0;
private _duration = GVAR(loadTimeCoefficient) * (_item call FUNC(getSizeItem));
// If unload time is 0, don't show a progress bar
if (_duration <= 0) exitWith {
["ace_unloadCargo", [_item, GVAR(interactionVehicle), _unit]] call CBA_fnc_localEvent;
};
[ [
GVAR(loadTimeCoefficient) * _size, _duration,
[_item, GVAR(interactionVehicle), ACE_player], [_item, GVAR(interactionVehicle), _unit],
{TRACE_1("unload finish",_this); ["ace_unloadCargo", _this select 0] call CBA_fnc_localEvent},
{TRACE_1("unload fail",_this);},
localize LSTRING(UnloadingItem),
{ {
(_this select 0) params ["_item", "_target", "_player"]; TRACE_1("unload finish",_this);
(alive _target) ["ace_unloadCargo", _this select 0] call CBA_fnc_localEvent;
&& {locked _target < 2} },
&& {([_player, _target] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE} {
&& {_item in (_target getVariable [QGVAR(loaded), []])} TRACE_1("unload fail",_this);
},
LLSTRING(unloadingItem),
{
(_this select 0) params ["_item", "_vehicle", "_unit"];
[_item, _vehicle, _unit, false, true] call FUNC(canUnloadItem) // don't check for a suitable unloading position every frame
}, },
["isNotSwimming"] ["isNotSwimming"]
] call EFUNC(common,progressBar); ] call EFUNC(common,progressBar);
} else { } else {
private _displayName = [_item, true] call FUNC(getNameItem); [[LSTRING(unloadingFailed), [_item, true] call FUNC(getNameItem)], 3] call EFUNC(common,displayTextStructured);
[[LSTRING(UnloadingFailed), _displayName], 3] call EFUNC(common,displayTextStructured);
}; };

View File

@ -4,17 +4,18 @@
* Dragging integration. Unloader starts carrying unloaded object. * Dragging integration. Unloader starts carrying unloaded object.
* *
* Arguments: * Arguments:
* 0: Unloader <OBJECT> * 0: Unit doing the unloading <OBJECT>
* 1: Item <OBJECT> * 1: Unloaded item <OBJECT>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [player, object] call ace_cargo_fnc_unloadCarryItem * [player, cursorObject] call ace_cargo_fnc_unloadCarryItem
* *
* Public: No * Public: No
*/ */
params ["_unloader", "_object"]; params ["_unloader", "_object"];
TRACE_2("unloadCarryItem-start",_unloader,_object); TRACE_2("unloadCarryItem-start",_unloader,_object);
@ -24,17 +25,21 @@ if (!GVAR(carryAfterUnload) || {getNumber (configOf _object >> QGVAR(blockUnload
// When unloading attached objects, this code will run before server has finished moving object to the safe position // When unloading attached objects, this code will run before server has finished moving object to the safe position
[{ [{
params ["_unloader", "_object"]; params ["_unloader", "_object"];
(_unloader distance _object) < 10 (_unloader distance _object) < 10
}, { }, {
params ["_unloader", "_object"]; params ["_unloader", "_object"];
TRACE_2("unloadCarryItem-unloaded",_unloader,_object); TRACE_2("unloadCarryItem-unloaded",_unloader,_object);
if ([_unloader, _object] call EFUNC(dragging,canCarry)) exitWith { if ([_unloader, _object] call EFUNC(dragging,canCarry)) exitWith {
[_unloader, _object] call EFUNC(dragging,startCarry); [_unloader, _object] call EFUNC(dragging,startCarry);
}; };
if ([_unloader, _object] call EFUNC(dragging,canDrag)) exitWith { if ([_unloader, _object] call EFUNC(dragging,canDrag)) exitWith {
[_unloader, _object] call EFUNC(dragging,startDrag); [_unloader, _object] call EFUNC(dragging,startDrag);
}; };
}, _this, 1.0, { // delay is based on how long it will take server event to trigger and take effect }, _this, 1, { // Delay is based on how long it will take server event to trigger and take effect
// not a hard error if this fails, could have just unloaded to other side of vehicle because of findSafePos // Not a hard error if this fails, could have just unloaded to other side of vehicle because of findSafePos
TRACE_1("unloadCarryItem-failed to unload nearby player",_this); TRACE_1("unloadCarryItem-failed to unload nearby player",_this);
}] call CBA_fnc_waitUntilAndExecute; }] call CBA_fnc_waitUntilAndExecute;

View File

@ -1,57 +1,74 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal, ViperMaul * Author: Glowbal, ViperMaul
* Unload object from vehicle. * Unloads an object from a vehicle.
* *
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item to be unloaded <STRING> or <OBJECT> (default: "")
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT> (default: objNull)
* 2: Unloader <OBJECT> (default: objNull) * 2: Unloader <OBJECT> (default: objNull)
* *
* Return Value: * Return Value:
* Object was unloaded <BOOL> * Object unloaded <BOOL>
* *
* Example: * Example:
* [object, vehicle] call ace_cargo_fnc_unloadItem * ["ACE_Wheel", cursorObject] call ace_cargo_fnc_unloadItem
* *
* Public: Yes * Public: Yes
*/ */
params ["_item", "_vehicle", ["_unloader", objNull]]; params [["_item", "", [objNull, ""]], ["_vehicle", objNull, [objNull]], ["_unloader", objNull, [objNull]]];
TRACE_3("params",_item,_vehicle,_unloader); TRACE_3("params",_item,_vehicle,_unloader);
// Get config sensitive case name
if (_item isEqualType "") then {
_item = _item call EFUNC(common,getConfigName);
};
// Check if item is actually part of cargo
private _loaded = _vehicle getVariable [QGVAR(loaded), []];
if !(_item in _loaded) exitWith {
ERROR_3("Tried to unload item [%1] not in vehicle[%2] cargo[%3]",_item,_vehicle,_loaded);
false // return
};
// Check if item can be unloaded
private _itemSize = _item call FUNC(getSizeItem);
if (_itemSize < 0) exitWith {
false // return
};
// This covers testing vehicle stability and finding a safe position // This covers testing vehicle stability and finding a safe position
private _emptyPosAGL = [_vehicle, _item, _unloader] call EFUNC(common,findUnloadPosition); private _emptyPosAGL = [_vehicle, _item, _unloader] call EFUNC(common,findUnloadPosition);
TRACE_1("findUnloadPosition",_emptyPosAGL); TRACE_1("findUnloadPosition",_emptyPosAGL);
if ((count _emptyPosAGL) != 3) exitWith { if (_emptyPosAGL isEqualTo []) exitWith {
TRACE_4("Could not find unload pos",_vehicle,getPosASL _vehicle,isTouchingGround _vehicle,speed _vehicle); // Display text saying there are no safe places to exit the vehicle
if ((!isNull _unloader) && {_unloader == ACE_player}) then { if (!isNull _unloader && {_unloader == ACE_player}) then {
//display text saying there are no safe places to exit the vehicle [ELSTRING(common,NoRoomToUnload)] call EFUNC(common,displayTextStructured);
[localize ELSTRING(common,NoRoomToUnload)] call EFUNC(common,displayTextStructured);
};
false
}; };
private _loaded = _vehicle getVariable [QGVAR(loaded), []]; false // return
if !(_item in _loaded) exitWith {
ERROR_3("Tried to unload item [%1] not in vehicle[%2] cargo[%3]", _item, _vehicle, _loaded);
false
}; };
// Unload item from cargo
_loaded deleteAt (_loaded find _item); _loaded deleteAt (_loaded find _item);
_vehicle setVariable [QGVAR(loaded), _loaded, true]; _vehicle setVariable [QGVAR(loaded), _loaded, true];
private _space = [_vehicle] call FUNC(getCargoSpaceLeft); // Update cargo space remaining
private _itemSize = [_item] call FUNC(getSizeItem); private _cargoSpace = _vehicle call FUNC(getCargoSpaceLeft);
_vehicle setVariable [QGVAR(space), (_space + _itemSize), true]; _vehicle setVariable [QGVAR(space), _cargoSpace + _itemSize, true];
private _object = _item; private _object = _item;
if (_object isEqualType objNull) then { if (_object isEqualType objNull) then {
detach _object; detach _object;
// hideObjectGlobal must be executed before setPos to ensure light objects are rendered correctly // hideObjectGlobal must be executed before setPos to ensure light objects are rendered correctly
// do both on server to ensure they are executed in the correct order // Do both on server to ensure they are executed in the correct order
[QGVAR(serverUnload), [_object, _emptyPosAGL]] call CBA_fnc_serverEvent; [QGVAR(serverUnload), [_object, _emptyPosAGL]] call CBA_fnc_serverEvent;
if (["ace_zeus"] call EFUNC(common,isModLoaded)) then { if (["ace_zeus"] call EFUNC(common,isModLoaded)) then {
@ -75,4 +92,5 @@ if (_object isEqualType objNull) then {
// Invoke listenable event // Invoke listenable event
["ace_cargoUnloaded", [_object, _vehicle, "unload"]] call CBA_fnc_globalEvent; ["ace_cargoUnloaded", [_object, _vehicle, "unload"]] call CBA_fnc_globalEvent;
true
true // return

View File

@ -1,37 +0,0 @@
#include "..\script_component.hpp"
/*
* Author: Glowbal
* Validate the vehicle cargo space.
*
* Arguments:
* 0: Object <OBJECT>
*
* Return Value:
* None
*
* Example:
* [object] call ace_cargo_fnc_validateCargoSpace
*
* Public: No
*/
params ["_vehicle"];
TRACE_1("params",_vehicle);
private _loaded = _vehicle getVariable [QGVAR(loaded), []];
private _newLoaded = [];
private _totalSpaceOccupied = 0;
{
if ((_x isEqualType "") || {!isNull _x}) then {
_newLoaded pushback _x;
_totalSpaceOccupied = _totalSpaceOccupied + ([_x] call FUNC(getSizeItem));
};
true
} count _loaded;
if (count _loaded != count _newLoaded) then {
_vehicle setVariable [QGVAR(loaded), _newLoaded, true];
};
_vehicle setVariable [QGVAR(space), getNumber (configOf _vehicle >> QGVAR(space)) - _totalSpaceOccupied, true];

View File

@ -1,52 +1,58 @@
[ [
QGVAR(enable), "CHECKBOX", QGVAR(enable),
"CHECKBOX",
[LSTRING(ModuleSettings_enable), LSTRING(ModuleSettings_enable_Description)], [LSTRING(ModuleSettings_enable), LSTRING(ModuleSettings_enable_Description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
true, true,
true, true,
{[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(loadTimeCoefficient), "SLIDER", QGVAR(loadTimeCoefficient),
"SLIDER",
[LSTRING(loadTimeCoefficient), LSTRING(loadTimeCoefficient_description)], [LSTRING(loadTimeCoefficient), LSTRING(loadTimeCoefficient_description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
[0, 10, 5, 1], [0, 10, 5, 1],
true, true,
{[QGVAR(loadTimeCoefficient), _this, true] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(loadTimeCoefficient), _this, true] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(paradropTimeCoefficent), "SLIDER", QGVAR(paradropTimeCoefficent),
"SLIDER",
[LSTRING(paradropTimeCoefficent), LSTRING(paradropTimeCoefficent_description)], [LSTRING(paradropTimeCoefficent), LSTRING(paradropTimeCoefficent_description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
[0, 10, 2.5, 1], [0, 10, 2.5, 1],
true, true,
{[QGVAR(paradropTimeCoefficent), _this, true] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(paradropTimeCoefficent), _this, true] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(openAfterUnload), "LIST", QGVAR(openAfterUnload),
"LIST",
[LSTRING(openAfterUnload), LSTRING(openAfterUnload_description)], [LSTRING(openAfterUnload), LSTRING(openAfterUnload_description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
[[0, 1, 2, 3], [ELSTRING(common,never), LSTRING(unloadObject), LSTRING(paradropButton), ELSTRING(common,both)], 0], [[0, 1, 2, 3], [ELSTRING(common,never), LSTRING(unloadObject), LSTRING(paradropButton), ELSTRING(common,both)], 0],
false, false,
{[QGVAR(openAfterUnload), _this, true] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(openAfterUnload), _this, true] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(enableRename), "CHECKBOX", QGVAR(enableRename),
"CHECKBOX",
[LSTRING(ModuleSettings_enableRename), LSTRING(ModuleSettings_enableRename_Description)], [LSTRING(ModuleSettings_enableRename), LSTRING(ModuleSettings_enableRename_Description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
true, true,
false, false,
{[QGVAR(enableRename), _this, true] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(enableRename), _this, true] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(carryAfterUnload), "CHECKBOX", QGVAR(carryAfterUnload),
"CHECKBOX",
[LSTRING(carryAfterUnload), LSTRING(carryAfterUnload_description)], [LSTRING(carryAfterUnload), LSTRING(carryAfterUnload_description)],
[LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(openMenu)], [ELSTRING(OptionsMenu,CategoryLogistics), LSTRING(openMenu)],
true, true,
false, false,
{[QGVAR(carryAfterUnload), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(carryAfterUnload), _this] call EFUNC(common,cbaSettings_settingChanged)}

View File

@ -4,7 +4,7 @@ class GVAR(menu) {
idd = 314614; idd = 314614;
movingEnable = 1; movingEnable = 1;
onLoad = QUOTE([_this select 0] call FUNC(onMenuOpen)); onLoad = QUOTE([_this select 0] call FUNC(onMenuOpen));
onUnload = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(menuDisplay)),nil)];); onUnload = QUOTE(uiNamespace setVariable [ARR_2(QQGVAR(menuDisplay),nil)]);
class controlsBackground { class controlsBackground {
class HeaderBackground: ACE_gui_backgroundBase { class HeaderBackground: ACE_gui_backgroundBase {
idc = -1; idc = -1;
@ -46,7 +46,7 @@ class GVAR(menu) {
w = "13 * (((safezoneW / safezoneH) min 1.2) / 40)"; w = "13 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; h = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
style = ST_CENTER; style = ST_CENTER;
colorText[] = {1, 1, 1.0, 0.9}; colorText[] = {1, 1, 1, 0.9};
colorBackground[] = {0, 0, 0, 0}; colorBackground[] = {0, 0, 0, 0};
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1.2)"; SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1.2)";
text = ""; text = "";
@ -97,7 +97,7 @@ class GVAR(menu) {
text = CSTRING(unloadObject); text = CSTRING(unloadObject);
idc = 12; idc = 12;
x = "20.9 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; x = "20.9 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)";
action = QUOTE([] call FUNC(startUnload)); action = QUOTE(ACE_player call FUNC(startUnload));
}; };
}; };
}; };

View File

@ -3,8 +3,8 @@
class GVAR(renameMenu) { class GVAR(renameMenu) {
idd = 314615; idd = 314615;
movingEnable = 0; movingEnable = 0;
onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(menuDisplay)),_this select 0)];); onLoad = QUOTE(uiNamespace setVariable [ARR_2(QQGVAR(menuDisplay),_this select 0)]);
onUnload = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(menuDisplay)),nil)];); onUnload = QUOTE(uiNamespace setVariable [ARR_2(QQGVAR(menuDisplay),nil)]);
class controlsBackground { class controlsBackground {
class HeaderBackground: ACE_gui_backgroundBase { class HeaderBackground: ACE_gui_backgroundBase {
idc = -1; idc = -1;
@ -40,7 +40,7 @@ class GVAR(renameMenu) {
text = CSTRING(renameObjectUI); text = CSTRING(renameObjectUI);
}; };
class edit: ACE_gui_editBase { class edit: ACE_gui_editBase {
onLoad = QUOTE((_this select 0) ctrlSetText (GVAR(interactionVehicle) getVariable [ARR_2(QUOTE(QGVAR(customName)),'')])); onLoad = QUOTE((_this select 0) ctrlSetText (GVAR(interactionVehicle) getVariable [ARR_2(QQGVAR(customName),'')]));
idc = 100; idc = 100;
canModify = 1; canModify = 1;
x = "13.1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; x = "13.1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)";

View File

@ -19,7 +19,3 @@
#define MAX_LOAD_DISTANCE 5 #define MAX_LOAD_DISTANCE 5
#define GET_NUMBER(config,default) (if (isNumber (config)) then {getNumber (config)} else {default}) #define GET_NUMBER(config,default) (if (isNumber (config)) then {getNumber (config)} else {default})
// Default cargo size is -1 as 0 is a valid size
#define CARGO_SIZE(classname) GET_NUMBER(configFile >> "CfgVehicles" >> (classname) >> QGVAR(size),-1)
#define CARGO_SPACE(classname) GET_NUMBER(configFile >> "CfgVehicles" >> (classname) >> QGVAR(space),0)

View File

@ -38,7 +38,7 @@
<Japanese>名前を次に変更:&lt;br/&gt;%1</Japanese> <Japanese>名前を次に変更:&lt;br/&gt;%1</Japanese>
<French>Renommé en :&lt;br/&gt;%1</French> <French>Renommé en :&lt;br/&gt;%1</French>
<Russian>Переименовано в:&lt;br/&gt;%1</Russian> <Russian>Переименовано в:&lt;br/&gt;%1</Russian>
<German>Neu Bewaffnet: &lt;br/&gt;%1</German> <German>Neu umbenannt zu: &lt;br/&gt;%1</German>
<Polish>Nazwa zmieniona na:&lt;br/&gt;%1</Polish> <Polish>Nazwa zmieniona na:&lt;br/&gt;%1</Polish>
<Chinesesimp>重命名为:&lt;br/&gt;%1</Chinesesimp> <Chinesesimp>重命名为:&lt;br/&gt;%1</Chinesesimp>
<Korean>%1(으)로 명칭을 바꿈</Korean> <Korean>%1(으)로 명칭을 바꿈</Korean>
@ -294,6 +294,16 @@
<Chinesesimp>%1&lt;br/&gt;无法被卸载</Chinesesimp> <Chinesesimp>%1&lt;br/&gt;无法被卸载</Chinesesimp>
<Turkish>%1&lt;br/&gt; kargo boşaltılamadı</Turkish> <Turkish>%1&lt;br/&gt; kargo boşaltılamadı</Turkish>
</Key> </Key>
<Key ID="STR_ACE_Cargo_UnloadingImpossible">
<English>Can't be unloaded</English>
<German>Kann nicht entladen werden</German>
<French>Ne peut pas être déchargé</French>
</Key>
<Key ID="STR_ACE_Cargo_SizeMenu">
<English>Cargo Size: %1</English>
<German>Frachtgröße: %1</German>
<French>Encombrement fret: %1</French>
</Key>
<Key ID="STR_ACE_Cargo_customName_edenName"> <Key ID="STR_ACE_Cargo_customName_edenName">
<English>Custom Name</English> <English>Custom Name</English>
<Japanese>カスタム名</Japanese> <Japanese>カスタム名</Japanese>
@ -364,7 +374,7 @@
<Turkish>Kargo Boyutu</Turkish> <Turkish>Kargo Boyutu</Turkish>
</Key> </Key>
<Key ID="STR_ACE_Cargo_size_edenDesc"> <Key ID="STR_ACE_Cargo_size_edenDesc">
<English>The cargo space required to hold this object (-1 for unloadable)</English> <English>The cargo space required to hold this object (-1 for not loadable)</English>
<German>Frachtraumgröße, welche zum Einladen dieses Objektes benötigt wird (-1 nicht einladbar)</German> <German>Frachtraumgröße, welche zum Einladen dieses Objektes benötigt wird (-1 nicht einladbar)</German>
<Italian>Lo spazio del cargo necessita di mantenere questo oggetto (-1 per scaricabile)</Italian> <Italian>Lo spazio del cargo necessita di mantenere questo oggetto (-1 per scaricabile)</Italian>
<Japanese>オブジェクトを積載するのに必要なカーゴ スペース (-1 で積載不可)</Japanese> <Japanese>オブジェクトを積載するのに必要なカーゴ スペース (-1 で積載不可)</Japanese>

View File

@ -2,138 +2,150 @@
/* /*
* Author: PabstMirror, ViperMaul * Author: PabstMirror, ViperMaul
* Find a safe place near a vehicle to unload something. * Find a safe place near a vehicle to unload something.
* Handles Normal Terrain, In Water or On Buildings (Pier, StaticShip). * Handles normal terrain, water or on buildings (Pier, StaticShip).
* *
* Arguments: * Arguments:
* 0: Source Vehicle <OBJECT> * 0: Holder object (vehicle) <OBJECT>
* 1: Cargo <OBJECT> or <STRING> * 1: Item to be unloaded <STRING> or <OBJECT>
* 2: Unloader (player) <OBJECT> (default: objNull) * 2: Unit doing the unloading <OBJECT> (default: objNull)
* 3: Max Distance (meters) <NUMBER> (default: 10) * 3: Max distance (meters) <NUMBER> (default: 10)
* 4: Check Vehicle is Stable <BOOL> (default: true) * 4: Check if holder object is stable <BOOL> (default: true)
* *
* Return Value: * Return Value:
* Unload PositionAGL (can Be [] if no valid pos found) <ARRAY> * Unload PositionAGL ([] if no valid pos found) <ARRAY>
* *
* Example: * Example:
* [theCar, "CAManBase", player, 10, true] call ace_common_fnc_findUnloadPosition * [cursorObject, "CAManBase", player, 10, true] call ace_common_fnc_findUnloadPosition
* *
* Public: No * Public: No
*/ */
//Number of tests run (effects performance in worst case scenarior where nothing is found VERSUES reliably finding a pos): // Number of tests run (effects performance in worst case scenario where nothing is found VERSUS reliably finding a pos)
#define MAX_TESTS 75 #define MAX_TESTS 75
//Manual collision tests (count and radius): // Manual collision tests (count and radius)
#define COL_TEST_COUNT 12 #define COL_TEST_COUNT 12
params ["_vehicle", "_cargo", ["_theUnloader", objNull], ["_maxDistance", 10], ["_checkVehicleIsStable", true]]; params ["_vehicle", "_item", ["_unloader", objNull], ["_maxDistance", 10], ["_checkVehicleIsStable", true]];
TRACE_5("params",_vehicle,_cargo,_theUnloader,_maxDistance,_checkVehicleIsStable); TRACE_5("params",_vehicle,_item,_unloader,_maxDistance,_checkVehicleIsStable);
scopeName "main"; scopeName "main";
if (_checkVehicleIsStable) then { if (_checkVehicleIsStable) then {
if (((vectorMagnitude (velocity _vehicle)) > 1.5) || {(!(_vehicle isKindOf "Ship")) && {(!isTouchingGround _vehicle) && {((getPos _vehicle) select 2) > 1.5}}}) then { if (((vectorMagnitude (velocity _vehicle)) > 1.5) || {(!(_vehicle isKindOf "Ship")) && {(!isTouchingGround _vehicle) && {((getPos _vehicle) select 2) > 1.5}}}) then {
TRACE_4("bad vehicle state",_vehicle,velocity _vehicle,isTouchingGround _vehicle,getPos _vehicle); TRACE_4("bad vehicle state",_vehicle,velocity _vehicle,isTouchingGround _vehicle,getPos _vehicle);
[] breakOut "main";
[] breakOut "main"
}; };
}; };
private _radiusOfItem = 1; private _radiusOfItem = 1;
if (_cargo isKindOf "CAManBase") then {
if (_item isKindOf "CAManBase") then {
_radiusOfItem = 1.1; _radiusOfItem = 1.1;
} else { } else {
// `sizeOf` is unreliable, and does not work with object types that don't exist on map, so estimate size based on cargo size // `sizeOf` is unreliable, and does not work with object types that don't exist on map, so estimate size based on cargo size
private _configOfCargo = if (_cargo isEqualType objNull) then {
configOf _cargo
} else {
configFile >> "CfgVehicles" >> _cargo
};
private _itemSize = if (isNumber (_configOfCargo >> QEGVAR(cargo,size)) && {getNumber (_configOfCargo >> QEGVAR(cargo,size)) != -1}) then {
getNumber (_configOfCargo >> QEGVAR(cargo,size));
} else {
if (["ace_cargo"] call FUNC(isModLoaded)) then { if (["ace_cargo"] call FUNC(isModLoaded)) then {
[_cargo] call EFUNC(cargo,getSizeItem); private _itemSize = _item call EFUNC(cargo,getSizeItem);
} else {
_radiusOfItem; if (_itemSize > 0) then {
};
};
if (_itemSize != -1) then {
_radiusOfItem = (_itemSize ^ 0.35) max 0.75; _radiusOfItem = (_itemSize ^ 0.35) max 0.75;
}; };
}; };
};
if (isNull _theUnloader) then {_theUnloader = _vehicle;}; if (isNull _unloader) then {
_unloader = _vehicle;
};
// Ideal unload pos is halfway between unloader and vehicle (at the unloader's height) // Ideal unload pos is halfway between unloader and vehicle (at the unloader's height)
private _originASL = ((getPosASL _theUnloader) vectorAdd (getPosASL _vehicle)) vectorMultiply 0.5; private _originASL = ((getPosASL _unloader) vectorAdd (getPosASL _vehicle)) vectorMultiply 0.5;
_originASL set [2, (getPosASL _theUnloader) select 2]; _originASL set [2, (getPosASL _unloader) select 2];
private _originAGL = ASLtoAGL _originASL; private _originAGL = ASLtoAGL _originASL;
// Do a manual search for empty pos (handles underwater, buildings or piers) // Do a manual search for empty pos (handles underwater, buildings or piers)
TRACE_2("Checking for unload",_originAGL,_radiusOfItem); TRACE_2("Checking for unload",_originAGL,_radiusOfItem);
private _rangeToCheck = 0; private _rangeToCheck = 0;
while {_rangeToCheck < _maxDistance} do { while {_rangeToCheck < _maxDistance} do {
private _roundDistance = random _rangeToCheck; private _roundDistance = random _rangeToCheck;
private _roundAngle = random 360; private _roundAngle = random 360;
private _roundAGL = _originAGL vectorAdd [(cos _roundAngle) * _roundDistance, (sin _roundAngle) * _roundDistance, 0]; private _roundAGL = _originAGL vectorAdd [(cos _roundAngle) * _roundDistance, (sin _roundAngle) * _roundDistance, 0];
private _roundPointIsValid = false; private _roundPointIsValid = false;
if (((AGLtoASL _roundAGL) select 2) > 0) then { if (((AGLtoASL _roundAGL) select 2) > 0) then {
//Shoot a ray down, and make sure we hit something solid like a building or the ground: // Shoot a ray down, and make sure we hit something solid like a building or the ground
private _belowRoundArray = lineIntersectsSurfaces [(AGLtoASL _roundAGL) vectorAdd [0, 0, 0.5], (AGLtoASL _roundAGL) vectorAdd [0, 0, -1]]; private _belowRoundArray = lineIntersectsSurfaces [(AGLtoASL _roundAGL) vectorAdd [0, 0, 0.5], (AGLtoASL _roundAGL) vectorAdd [0, 0, -1]];
TRACE_4("Testing for solid",_roundDistance,_roundAngle,_roundAGL,_belowRoundArray); TRACE_4("Testing for solid",_roundDistance,_roundAngle,_roundAGL,_belowRoundArray);
if (_belowRoundArray isNotEqualTo []) then { if (_belowRoundArray isNotEqualTo []) then {
private _aboveBuilding = (_belowRoundArray select 0) select 2; private _aboveBuilding = (_belowRoundArray select 0) select 2;
// Point is above something: Terrain (null) or Building // Point is above something: Terrain (null) or Building
if ((isNull _aboveBuilding) || {_aboveBuilding isKindOf "Building"}) then { if ((isNull _aboveBuilding) || {_aboveBuilding isKindOf "Building"}) then {
//Get the real intersection point: // Get the real intersection point
_roundAGL = ASLtoAGL ((_belowRoundArray select 0) select 0); _roundAGL = ASLtoAGL ((_belowRoundArray select 0) select 0);
_roundPointIsValid = true; _roundPointIsValid = true;
}; };
}; };
} else { } else {
// Underwater, just unload anywhere // Underwater, just unload anywhere
TRACE_3("Under the sea",_roundDistance,_roundAngle,_roundAGL); TRACE_3("Under the sea",_roundDistance,_roundAngle,_roundAGL);
_roundPointIsValid = true; _roundPointIsValid = true;
}; };
//Make sure point is valid and do a fast check for people in the way (which sometimes aren't caught by line scaning) // Make sure point is valid and do a fast check for people in the way (which sometimes aren't caught by line scanning)
if (_roundPointIsValid && {(_roundAGL nearEntities ["Man", _radiusOfItem]) isEqualTo []}) then { if (_roundPointIsValid && {(_roundAGL nearEntities ["Man", _radiusOfItem]) isEqualTo []}) then {
for "_index" from 0 to (COL_TEST_COUNT -1) do { for "_index" from 0 to (COL_TEST_COUNT -1) do {
//Scan for colisions with objects with lineIntersectsSurfaces // Scan for collisions with objects with lineIntersectsSurfaces
private _angle = _index * (360 / COL_TEST_COUNT); private _angle = _index * (360 / COL_TEST_COUNT);
private _point1ASL = (AGLtoASL _roundAGL) vectorAdd [_radiusOfItem * cos _angle, _radiusOfItem * sin _angle, 0.1]; private _point1ASL = (AGLtoASL _roundAGL) vectorAdd [_radiusOfItem * cos _angle, _radiusOfItem * sin _angle, 0.1];
private _point2ASL = (AGLtoASL _roundAGL) vectorAdd [-_radiusOfItem * cos _angle, -_radiusOfItem * sin _angle, (_radiusOfItem + 0.5)]; private _point2ASL = (AGLtoASL _roundAGL) vectorAdd [-_radiusOfItem * cos _angle, -_radiusOfItem * sin _angle, _radiusOfItem + 0.5];
private _testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL]; private _testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL];
if (((count _testIntersections) == 1) && {isNull ((_testIntersections select 0) select 2)}) then { if (((count _testIntersections) == 1) && {isNull ((_testIntersections select 0) select 2)}) then {
private _hitGroundASL = (_testIntersections select 0) select 0; private _hitGroundASL = (_testIntersections select 0) select 0;
private _hitHeightOffset = ((AGLtoASL _roundAGL) select 2) - (_hitGroundASL select 2); private _hitHeightOffset = ((AGLtoASL _roundAGL) select 2) - (_hitGroundASL select 2);
private _hit2dOffset = _roundAGL distance2D _hitGroundASL; private _hit2dOffset = _roundAGL distance2D _hitGroundASL;
private _slope = _hitHeightOffset atan2 _hit2dOffset; private _slope = _hitHeightOffset atan2 _hit2dOffset;
if (_slope < 25) then { //Ignore ground hit if slope is reasonable
// Ignore ground hit if slope is reasonable
if (_slope < 25) then {
_testIntersections = []; _testIntersections = [];
}; };
}; };
if (_testIntersections isNotEqualTo []) exitWith { if (_testIntersections isNotEqualTo []) exitWith {
TRACE_2("collision low/high",_roundAGL,_testIntersections); TRACE_2("collision low/high",_roundAGL,_testIntersections);
_roundPointIsValid = false; _roundPointIsValid = false;
}; };
_point1ASL = (AGLtoASL _roundAGL) vectorAdd [_radiusOfItem * cos _angle, _radiusOfItem * sin _angle, 0.5]; _point1ASL = (AGLtoASL _roundAGL) vectorAdd [_radiusOfItem * cos _angle, _radiusOfItem * sin _angle, 0.5];
_point2ASL = (AGLtoASL _roundAGL) vectorAdd [-_radiusOfItem * cos _angle, -_radiusOfItem * sin _angle, 1]; _point2ASL = (AGLtoASL _roundAGL) vectorAdd [-_radiusOfItem * cos _angle, -_radiusOfItem * sin _angle, 1];
_testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL]; _testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL];
if (_testIntersections isNotEqualTo []) exitWith { if (_testIntersections isNotEqualTo []) exitWith {
TRACE_2("collision mid",_roundAGL,_testIntersections); TRACE_2("collision mid",_roundAGL,_testIntersections);
_roundPointIsValid = false; _roundPointIsValid = false;
}; };
}; };
if (_roundPointIsValid) then { if (_roundPointIsValid) then {
TRACE_3("Valid point found", _rangeToCheck,_roundAGL, (_originAGL distance _roundAGL)); TRACE_3("Valid point found",_rangeToCheck,_roundAGL,_originAGL distance _roundAGL);
//Raise it slightly so we don't sink through the floor:
(_roundAGL vectorAdd [0,0,0.05]) breakOut "main"; // Raise it slightly so we don't sink through the floor
(_roundAGL vectorAdd [0, 0, 0.05]) breakOut "main"; // return
}; };
}; };
_rangeToCheck = _rangeToCheck + (_maxDistance / MAX_TESTS); _rangeToCheck = _rangeToCheck + (_maxDistance / MAX_TESTS);
}; };
TRACE_1("no valid spots found",_rangeToCheck); TRACE_1("no valid spots found",_rangeToCheck);
[] //return empty array
[] // return

View File

@ -72,13 +72,13 @@ if (_previousHint isEqualType "") exitWith {};
// Mouse hint // Mouse hint
private _hintLMB = LLSTRING(Drop); private _hintLMB = LLSTRING(Drop);
getCursorObjectParams params ["_cursorObject", "", "_distance"]; private _cursorObject = cursorObject;
if ( if (
!isNull _cursorObject && {[_unit, _cursorObject, ["isNotCarrying"]] call EFUNC(common,canInteractWith)} && !isNull _cursorObject && {[_unit, _cursorObject, ["isNotCarrying"]] call EFUNC(common,canInteractWith)} &&
{ {
if (_target isKindOf "CAManBase") then { if (_target isKindOf "CAManBase") then {
(_distance <= MAX_LOAD_DISTANCE_MAN) && {[_cursorObject, 0, true] call EFUNC(common,nearestVehiclesFreeSeat) isNotEqualTo []} (_unit distance _cursorObject <= MAX_LOAD_DISTANCE_MAN) && {[_cursorObject, 0, true] call EFUNC(common,nearestVehiclesFreeSeat) isNotEqualTo []}
} else { } else {
["ace_cargo"] call EFUNC(common,isModLoaded) && ["ace_cargo"] call EFUNC(common,isModLoaded) &&
{EGVAR(cargo,enable)} && {EGVAR(cargo,enable)} &&

View File

@ -30,8 +30,17 @@ private _inBuilding = _unit call FUNC(isObjectOnObject);
[QEGVAR(common,fixCollision), _unit] call CBA_fnc_localEvent; [QEGVAR(common,fixCollision), _unit] call CBA_fnc_localEvent;
[QEGVAR(common,fixCollision), _target, _target] call CBA_fnc_targetEvent; [QEGVAR(common,fixCollision), _target, _target] call CBA_fnc_targetEvent;
private _cursorObject = cursorObject;
_tryLoad = _tryLoad && {!isNull _cursorObject} && {[_unit, _cursorObject, ["isNotCarrying"]] call EFUNC(common,canInteractWith)};
private _loadCargo = false;
// Don't release object if loading into vehicle (object might be released into vehicle)
if (_tryLoad && {!(_target isKindOf "CAManBase")} && {["ace_cargo"] call EFUNC(common,isModLoaded)} && {[_target, _cursorObject] call EFUNC(cargo,canLoadItemIn)}) then {
_loadCargo = true;
} else {
// Release object // Release object
detach _target; detach _target;
};
// Fix anim when aborting carrying persons // Fix anim when aborting carrying persons
if (_target isKindOf "CAManBase" || {animationState _unit in CARRY_ANIMATIONS}) then { if (_target isKindOf "CAManBase" || {animationState _unit in CARRY_ANIMATIONS}) then {
@ -97,13 +106,11 @@ if (_mass != 0) then {
// Reset temp direction // Reset temp direction
_target setVariable [QGVAR(carryDirection_temp), nil]; _target setVariable [QGVAR(carryDirection_temp), nil];
getCursorObjectParams params ["_cursorObject", "", "_distance"]; // (Try) loading into vehicle
if (_loadCargo) then {
// Try loading into vehicle [_unit, _target, _cursorObject] call EFUNC(cargo,startLoadIn);
if (_tryLoad && {!isNull _cursorObject} && {[_unit, _cursorObject, ["isNotCarrying"]] call EFUNC(common,canInteractWith)}) then { } else {
if (_target isKindOf "CAManBase") then { if (_tryLoad && {_unit distance _cursorObject <= MAX_LOAD_DISTANCE_MAN} && {_target isKindOf "CAManBase"}) then {
if (_distance > MAX_LOAD_DISTANCE_MAN) exitWith {};
private _vehicles = [_cursorObject, 0, true] call EFUNC(common,nearestVehiclesFreeSeat); private _vehicles = [_cursorObject, 0, true] call EFUNC(common,nearestVehiclesFreeSeat);
if ([_cursorObject] isEqualTo _vehicles) then { if ([_cursorObject] isEqualTo _vehicles) then {
@ -113,13 +120,5 @@ if (_tryLoad && {!isNull _cursorObject} && {[_unit, _cursorObject, ["isNotCarryi
[_unit, _target, _cursorObject] call EFUNC(common,loadPerson); [_unit, _target, _cursorObject] call EFUNC(common,loadPerson);
}; };
}; };
} else {
if (
["ace_cargo"] call EFUNC(common,isModLoaded) &&
{EGVAR(cargo,enable)} &&
{[_target, _cursorObject] call EFUNC(cargo,canLoadItemIn)}
) then {
[_unit, _target, _cursorObject] call EFUNC(cargo,startLoadIn);
};
}; };
}; };

View File

@ -1,4 +1,4 @@
private _category = [LELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(DisplayName)]; private _category = [ELSTRING(OptionsMenu,CategoryLogistics), LLSTRING(DisplayName)];
[ [
QGVAR(enabled), "CHECKBOX", QGVAR(enabled), "CHECKBOX",

View File

@ -1,7 +1,9 @@
private _category = [ELSTRING(OptionsMenu,CategoryLogistics), "str_state_refuel"];
[ [
QGVAR(rate), "SLIDER", QGVAR(rate), "SLIDER",
[LSTRING(RefuelSettings_speed_DisplayName), LSTRING(RefuelSettings_speed_Description)], [LSTRING(RefuelSettings_speed_DisplayName), LSTRING(RefuelSettings_speed_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_refuel"], _category,
[0,25,1,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] [0,25,1,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal true, // isGlobal
{[QGVAR(rate), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(rate), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -10,7 +12,7 @@
[ [
QGVAR(cargoRate), "SLIDER", QGVAR(cargoRate), "SLIDER",
[LSTRING(RefuelSettings_speedCargo_DisplayName), LSTRING(RefuelSettings_speedCargo_Description)], [LSTRING(RefuelSettings_speedCargo_DisplayName), LSTRING(RefuelSettings_speedCargo_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_refuel"], _category,
[0,250,10,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] [0,250,10,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal true, // isGlobal
{[QGVAR(cargoRate), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(cargoRate), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -19,7 +21,7 @@
[ [
QGVAR(hoseLength), "SLIDER", QGVAR(hoseLength), "SLIDER",
[LSTRING(RefuelSettings_hoseLength_DisplayName)], [LSTRING(RefuelSettings_hoseLength_DisplayName)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_refuel"], _category,
[0,50,12,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] [0,50,12,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal true, // isGlobal
{[QGVAR(hoseLength), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(hoseLength), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -28,7 +30,7 @@
[ [
QGVAR(progressDuration), "TIME", QGVAR(progressDuration), "TIME",
[LSTRING(RefuelSettings_progressDuration_DisplayName), LSTRING(RefuelSettings_progressDuration_Description)], [LSTRING(RefuelSettings_progressDuration_DisplayName), LSTRING(RefuelSettings_progressDuration_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_refuel"], _category,
[0, 10, 2], // [min, max, default value] [0, 10, 2], // [min, max, default value]
true, // isGlobal true, // isGlobal
{[QGVAR(progressDuration), _this] call EFUNC(common,cbaSettings_settingChanged)} {[QGVAR(progressDuration), _this] call EFUNC(common,cbaSettings_settingChanged)}

View File

@ -1,7 +1,7 @@
[ [
QGVAR(addRopeToVehicleInventory), "CHECKBOX", QGVAR(addRopeToVehicleInventory), "CHECKBOX",
LSTRING(Setting_addRopeToVehicleInventory_DisplayName), LSTRING(Setting_addRopeToVehicleInventory_DisplayName),
LELSTRING(OptionsMenu,CategoryLogistics), ELSTRING(OptionsMenu,CategoryLogistics),
true, true,
true, true,
{ {

View File

@ -32,10 +32,10 @@ if !(["ace_cargo"] call EFUNC(common,isModLoaded) && ["ace_repair"] call EFUNC(c
if !(alive _mouseOverUnit) then { if !(alive _mouseOverUnit) then {
[LSTRING(OnlyAlive)] call FUNC(showMessage); [LSTRING(OnlyAlive)] call FUNC(showMessage);
} else { } else {
if (getNumber (configFile >> "CfgVehicles" >> "ACE_Track" >> QEGVAR(cargo,size)) > [_mouseOverUnit] call EFUNC(cargo,getCargoSpaceLeft)) then { if ("ACE_Track" call EFUNC(cargo,getSizeItem) > _mouseOverUnit call EFUNC(cargo,getCargoSpaceLeft)) then {
[LSTRING(OnlyEnoughCargoSpace)] call FUNC(showMessage); [LSTRING(OnlyEnoughCargoSpace)] call FUNC(showMessage);
} else { } else {
["ace_addCargo", ["ACE_Track", _mouseOverUnit, 1, true]] call CBA_fnc_localEvent; ["ace_addCargo", ["ACE_Track", _mouseOverUnit, 1]] call CBA_fnc_localEvent;
}; };
}; };
}; };

View File

@ -32,10 +32,10 @@ if !(["ace_cargo"] call EFUNC(common,isModLoaded) && ["ace_repair"] call EFUNC(c
if !(alive _mouseOverUnit) then { if !(alive _mouseOverUnit) then {
[LSTRING(OnlyAlive)] call FUNC(showMessage); [LSTRING(OnlyAlive)] call FUNC(showMessage);
} else { } else {
if (getNumber (configFile >> "CfgVehicles" >> "ACE_Wheel" >> QEGVAR(cargo,size)) > [_mouseOverUnit] call EFUNC(cargo,getCargoSpaceLeft)) then { if ("ACE_Wheel" call EFUNC(cargo,getSizeItem) > _mouseOverUnit call EFUNC(cargo,getCargoSpaceLeft)) then {
[LSTRING(OnlyEnoughCargoSpace)] call FUNC(showMessage); [LSTRING(OnlyEnoughCargoSpace)] call FUNC(showMessage);
} else { } else {
["ace_addCargo", ["ACE_Wheel", _mouseOverUnit, 1, true]] call CBA_fnc_localEvent; ["ace_addCargo", ["ACE_Wheel", _mouseOverUnit, 1]] call CBA_fnc_localEvent;
}; };
}; };
}; };

View File

@ -21,6 +21,8 @@ class CfgVehicles {
class yourVehicleBaseClass { class yourVehicleBaseClass {
ace_cargo_space = 4; // Cargo space your vehicle has ace_cargo_space = 4; // Cargo space your vehicle has
ace_cargo_hasCargo = 1; // Enables cargo to be loaded inside the vehicle (1-yes, 0-no) ace_cargo_hasCargo = 1; // Enables cargo to be loaded inside the vehicle (1-yes, 0-no)
ace_cargo_loadmasterTurrets = {{1}}; // If vehicle inherits from "Air", you can set this attribute.
// When sitting in the turret paths you define here, you can paradrop cargo items. By default, pilots and co-pilots can paradrop cargo items.
}; };
}; };
``` ```
@ -50,8 +52,9 @@ class CfgVehicles {
Event Name | Passed Parameter(s) | Locality | Description Event Name | Passed Parameter(s) | Locality | Description
---------- | ----------- | ------------------- | -------- ---------- | ----------- | ------------------- | --------
`ace_cargoLoaded` | [_item, _vehicle] | Global | Cargo has been Loaded into vehicle `ace_cargoAdded` | [_itemClass, _vehicle, _amount] | Global | Cargo has been added to vehicle
`ace_cargoUnloaded` | [_item, _vehicle, _unloadType] | Global | Cargo has been Unloaded from vehicle `ace_cargoLoaded` | [_item, _vehicle] | Global | Cargo has been loaded into vehicle
`ace_cargoUnloaded` | [_item, _vehicle, _unloadType] | Global | Cargo has been unloaded from vehicle
`ace_cargoRemoved` | [_itemClass, _vehicle, _amountRequested, _amountRemoved] | Global | Cargo has been removed (deleted) from vehicle `ace_cargoRemoved` | [_itemClass, _vehicle, _amountRequested, _amountRemoved] | Global | Cargo has been removed (deleted) from vehicle
## 3. Editor Attributes ## 3. Editor Attributes
@ -73,12 +76,12 @@ To disable cargo for a mission object use:
### 4.2 Adjusting cargo size of an object ### 4.2 Adjusting cargo size of an object
`ace_cargo_fnc_setSize` `ace_cargo_fnc_setSize`
Note that this function can be used to make objects loadable/unloadable (set to `-1` for unloadable). Note that this function can be used to make objects loadable/unloadable (set to `-1` to disable cargo interactions).
```sqf ```sqf
* Set the cargo size of any object. Has global effect. * Sets the cargo size of any object. Has global effect.
* Adds the load action menu if necessary. * Adds the load action menu if necessary.
* Negative size makes unloadable. * A negative size disables the object's cargo interactions.
* *
* Arguments: * Arguments:
* 0: Object <OBJECT> * 0: Object <OBJECT>
@ -97,7 +100,7 @@ Note that this function can be used to make objects loadable/unloadable (set to
Note that this function can be used to enable/disable a vehicle's cargo space (set to `0` to disable). Note that this function can be used to enable/disable a vehicle's cargo space (set to `0` to disable).
```sqf ```sqf
* Set the cargo space of any object. Has global effect. * Sets the cargo space of any object. Has global effect.
* Adds the cargo action menu if necessary. * Adds the cargo action menu if necessary.
* *
* Arguments: * Arguments:
@ -113,14 +116,17 @@ Note that this function can be used to enable/disable a vehicle's cargo space (s
### 4.4 Load cargo into vehicle ### 4.4 Load cargo into vehicle
`ace_cargo_fnc_loadItem` (Also callable from cba event `ace_loadCargo`) `ace_cargo_fnc_loadItem` (Also callable from CBA event `ace_loadCargo`)
Note first arg can be a in-game object or a classname of an object type. Note first argument can be a in-game object or a classname of an object type.
```sqf ```sqf
* Load an object into a vehicle.
* Objects loaded via classname remain virtual until unloaded.
*
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item to be loaded <STRING> or <OBJECT>
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Ignore interaction distance and stability checks <BOOL> * 2: Ignore interaction distance and stability checks <BOOL> (default: false)
* *
* Return Value: * Return Value:
* Object loaded <BOOL> * Object loaded <BOOL>
@ -131,16 +137,16 @@ Note first arg can be a in-game object or a classname of an object type.
### 4.5 Unload cargo from vehicle ### 4.5 Unload cargo from vehicle
`ace_cargo_fnc_unloadItem` (Also callable from cba event `ace_unloadCargo`) `ace_cargo_fnc_unloadItem` (Also callable from CBA event `ace_unloadCargo`)
```sqf ```sqf
* Arguments: * Arguments:
* 0: Item <OBJECT or STRING> * 0: Item to be unloaded <STRING> or <OBJECT>
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Unloader <OBJECT> (default: objNull) * 2: Unloader <OBJECT> (default: objNull)
* *
* Return Value: * Return Value:
* Object was unloaded <BOOL> * Object unloaded <BOOL>
* *
* Example: * Example:
* [object, vehicle] call ace_cargo_fnc_unloadItem * [object, vehicle] call ace_cargo_fnc_unloadItem
@ -152,8 +158,8 @@ Note first arg can be a in-game object or a classname of an object type.
```sqf ```sqf
* Arguments: * Arguments:
* 0: Item <STRING> or <OBJECT> * 0: Item to be removed <STRING> or <OBJECT>
* 1: Vehicle <OBJECT> * 1: Holder object (vehicle) <OBJECT>
* 2: Amount <NUMBER> (default: 1) * 2: Amount <NUMBER> (default: 1)
* *
* Return Value: * Return Value:
@ -167,5 +173,5 @@ Note first arg can be a in-game object or a classname of an object type.
### 4.7 Disable cargo renaming via script ### 4.7 Disable cargo renaming via script
```sqf ```sqf
cargoBox setVariable ["ace_cargo_noRename", true] cargoBox setVariable ["ace_cargo_noRename", true, _disableGlobally]
``` ```