Add support for virtual cargo

Allows cargo objects to be added via classname and reduces simulation/synchronization overhead. Objects become physical upon unloading and cannot be re-made virtual, only scripts can add such virtual objects.

Also separates the player feedback from the loading/unloading code and adds a progress bar.
This commit is contained in:
SilentSpike 2015-09-27 17:19:40 +01:00
parent 6ee5c6d9f8
commit f65f6e9b72
13 changed files with 159 additions and 88 deletions

View File

@ -1,5 +1,45 @@
#include "script_component.hpp"
["LoadCargo", {_this call FUNC(loadItem)}] call EFUNC(common,addEventHandler);
["UnloadCargo", {_this call FUNC(unloadItem)}] call EFUNC(common,addEventHandler);
["AddCargoByClass", {_this call FUNC(addCargoItem)}] call EFUNC(common,addEventHandler);
["LoadCargo", {
(_this select 0) params ["_item","_vehicle"];
private ["_loaded", "_hint", "_itemName", "_vehicleName"];
_loaded = [_item, _vehicle] call FUNC(loadItem);
// Show hint as feedback
_hint = [LSTRING(LoadingFailed), LSTRING(LoadedItem)] select _loaded;
_itemName = getText (configFile >> "CfgVehicles" >> typeOf _item >> "displayName");
_vehicleName = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName");
["displayTextStructured", [[_hint, _itemName, _vehicleName], 3.0]] call EFUNC(common,localEvent);
if (_loaded) then {
// Invoke listenable event
["cargoLoaded", [_item, _vehicle]] call EFUNC(common,globalEvent);
};
}] call EFUNC(common,addEventHandler);
["UnloadCargo", {
(_this select 0) params ["_item","_vehicle"];
private ["_unloaded", "_itemClass", "_hint", "_itemName", "_vehicleName"];
_unloaded = [_item, _vehicle] call FUNC(unloadItem);
_itemClass = if (typeName _item == "STRING") then {_item} else {typeOf _item};
// Show hint as feedback
_hint = [LSTRING(UnloadingFailed), LSTRING(UnloadedItem)] select _unloaded;
_itemName = getText (configFile >> "CfgVehicles" >> _itemClass >> "displayName");
_vehicleName = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName");
["displayTextStructured", [[_hint, _itemName, _vehicleName], 3.0]] call EFUNC(common,localEvent);
if (_unloaded) then {
// Invoke listenable event
["cargoUnloaded", [_item, _vehicle]] call EFUNC(common,globalEvent);
};
// TOOO maybe drag/carry the unloaded item?
}] call EFUNC(common,addEventHandler);

View File

@ -21,18 +21,9 @@ private ["_position", "_item", "_i"];
params ["_itemClass", "_vehicle", ["_amount", 1]];
TRACE_3("params",_itemClass,_vehicle,_amount);
_position = getPos _vehicle;
_position set [1, (_position select 1) + 1];
_position set [2, (_position select 2) + 7.5];
for "_i" from 1 to _amount do {
_item = createVehicle [_itemClass, _position, [], 0, "CAN_COLLIDE"];
// Load item or delete it if no space left
if !([_item, _vehicle] call FUNC(loadItem)) exitWith {
deleteVehicle _item;
};
// Invoke listenable event
["cargoAddedByClass", [_itemClass, _vehicle, _amount]] call EFUNC(common,globalEvent);
[_item, _vehicle] call FUNC(loadItem);
};
// Invoke listenable event
["cargoAddedByClass", [_itemClass, _vehicle, _amount]] call EFUNC(common,globalEvent);

View File

@ -3,7 +3,7 @@
* Check if item can be loaded into other Object.
*
* Arguments:
* 0: Item Object <OBJECT>
* 0: Item <OBJECT or STRING>
* 1: Holder Object (Vehicle) <OBJECT>
*
* Return value:
@ -16,14 +16,24 @@
*/
#include "script_component.hpp"
params ["_item", "_vehicle"];
params [["_item", "", [objNull,""]], "_vehicle"];
if (speed _vehicle > 1 || (((getPos _vehicle) select 2) > 3)) exitWith {false};
private "_itemSize";
_itemSize = ([_item] call FUNC(getSizeItem));
private ["_itemSize", "_validItem"];
_itemSize = [_item] call FUNC(getSizeItem);
(_itemSize > 0) &&
{alive _item && alive _vehicle} &&
{(_item distance _vehicle <= MAX_LOAD_DISTANCE)} &&
if (typeName _item == "STRING") then {
_validItem =
isClass (configFile >> "CfgVehicles" >> _item) &&
{getNumber (configFile >> "CfgVehicles" >> _item >> QGVAR(canLoad)) == 1};
} else {
_validItem =
(alive _item) &&
{(_item distance _vehicle) <= MAX_LOAD_DISTANCE};
};
_validItem &&
{_itemSize > 0} &&
{alive _vehicle} &&
{_itemSize <= ([_vehicle] call FUNC(getCargoSpaceLeft))}

View File

@ -16,18 +16,19 @@
*/
#include "script_component.hpp"
private ["_loaded", "_validVehiclestate", "_emptyPos"];
params ["_item", "_vehicle"];
private ["_loaded", "_itemClass", "_validVehiclestate", "_emptyPos"];
_loaded = _vehicle getVariable [QGVAR(loaded), []];
if !(_item in _loaded) exitWith {false};
_itemClass = if (typeName _item == "STRING") then {_item} else {typeOf _item};
_validVehiclestate = true;
_emptyPos = [];
if (_vehicle isKindOf "Ship" ) then {
if !(speed _vehicle <1 && {(((getPosATL _vehicle) select 2) < 2)}) then {_validVehiclestate = false};
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, typeOf _item]); // TODO: if spot is underwater pick another spot.
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, _itemClass]); // TODO: if spot is underwater pick another spot.
} else {
if (_vehicle isKindOf "Air" ) then {
if !(speed _vehicle <1 && {isTouchingGround _vehicle}) then {_validVehiclestate = false};
@ -35,7 +36,7 @@ if (_vehicle isKindOf "Ship" ) then {
_emptyPos = [(_emptyPos select 0) + random(5), (_emptyPos select 1) + random(5), _emptyPos select 2 ];
} else {
if !(speed _vehicle <1 && {(((getPosATL _vehicle) select 2) < 2)}) then {_validVehiclestate = false};
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, typeOf _item]);
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, _itemClass]);
};
};

View File

@ -3,7 +3,7 @@
* Get the cargo size of an object.
*
* Arguments:
* 0: Object <OBJECT>
* 0: Item <OBJECT or STRING>
*
* Return value:
* Cargo size <NUMBER> (default: -1)
@ -15,14 +15,24 @@
*/
#include "script_component.hpp"
private "_config";
params ["_item"];
private ["_isVirtual","_itemClass","_config"];
scopeName "return";
_config = (configFile >> "CfgVehicles" >> typeOf _item >> QGVAR(size));
_isVirtual = (typeName _item == "STRING");
_itemClass = if (_isVirtual) then {_item} else {typeOf _item};
_config = (configFile >> "CfgVehicles" >> _itemClass >> QGVAR(size));
if (isNumber (_config)) exitWith {
_item getVariable [QGVAR(size), getNumber (_config)]
if (_isVirtual) then {
if (isNumber _config) then {
(getNumber _config) breakOut "return";
};
} else {
_config = (configFile >> "CfgVehicles" >> typeOf _item >> QGVAR(size));
if (isNumber _config) then {
(_item getVariable [QGVAR(size), getNumber _config]) breakOut "return";
};
};
-1

View File

@ -20,12 +20,13 @@ params ["_vehicle"];
private["_loaded"];
_loaded = _vehicle getVariable [QGVAR(loaded), []];
if (count _loaded == 0) exitWith {};
if (_loaded isEqualTo []) exitWith {};
{
// TODO deleteVehicle or just delete vehicle? Do we want to be able to recover destroyed equipment?
deleteVehicle _x;
//_x setDamage 1;
// TODO Do we want to be able to recover destroyed equipment?
if (typeName _x == "OBJECT") then {
deleteVehicle _x;
};
} count _loaded;
[_vehicle] call FUNC(validateCargoSpace);

View File

@ -1,9 +1,10 @@
/*
* Author: Glowbal
* Load object into vehicle.
* Objects loaded via classname remain virtual until unloaded.
*
* Arguments:
* 0: Object <OBJECT>
* 0: Item <OBJECT or STRING>
* 1: Vehicle <OBJECT>
*
* Return value:
@ -16,10 +17,9 @@
*/
#include "script_component.hpp"
params [["_item","",[objNull,""]], ["_vehicle",objNull,[objNull]]];
private ["_loaded", "_space", "_itemSize"];
params ["_item", "_vehicle"];
if !([_item, _vehicle] call FUNC(canLoadItemIn)) exitWith {false};
_loaded = _vehicle getVariable [QGVAR(loaded), []];
@ -30,19 +30,10 @@ _space = [_vehicle] call FUNC(getCargoSpaceLeft);
_itemSize = [_item] call FUNC(getSizeItem);
_vehicle setVariable [QGVAR(space), _space - _itemSize, true];
detach _item;
_item attachTo [_vehicle,[0,0,100]];
["hideObjectGlobal", [_item, true]] call EFUNC(common,serverEvent);
// show hint
private ["_itemName", "_vehicleName"];
_itemName = getText (configFile >> "CfgVehicles" >> typeOf _item >> "displayName");
_vehicleName = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName");
["displayTextStructured", [[localize LSTRING(LoadedItem), _itemName, _vehicleName], 3.0]] call EFUNC(common,localEvent);
// Invoke listenable event
["cargoLoaded", [_item, _vehicle]] call EFUNC(common,globalEvent);
if (typeName _item == "OBJECT") then {
detach _item;
_item attachTo [_vehicle,[0,0,-100]];
["hideObjectGlobal", [_item, true]] call EFUNC(common,serverEvent);
};
true

View File

@ -22,7 +22,7 @@ params ["_display"];
uiNamespace setVariable [QGVAR(menuDisplay), _display];
[{
private ["_display","_loaded", "_ctrl", "_label"];
private ["_display","_loaded", "_ctrl", "_class", "_label"];
disableSerialization;
_display = uiNamespace getVariable QGVAR(menuDisplay);
if (isnil "_display") exitWith {
@ -40,7 +40,8 @@ uiNamespace setVariable [QGVAR(menuDisplay), _display];
lbClear _ctrl;
{
_ctrl lbAdd (getText(configfile >> "CfgVehicles" >> typeOf _x >> "displayName"));
_class = if (typeName _x == "STRING") then {_x} else {typeOf _x};
_ctrl lbAdd (getText(configfile >> "CfgVehicles" >> _class >> "displayName"));
true
} count _loaded;

View File

@ -16,16 +16,25 @@
#include "script_component.hpp"
params ["_player", "_object"];
private ["_vehicle", "_size", "_displayName"];
private ["_nearestVehicle"];
_nearestVehicle = [_player] call FUNC(findNearestVehicle);
_vehicle = [_player] call FUNC(findNearestVehicle);
if (isNull _nearestVehicle || _nearestVehicle isKindOf "Cargo_Base_F") then {
if (isNull _vehicle || _vehicle isKindOf "Cargo_Base_F") then {
{
if ([_object, _x] call FUNC(canLoadItemIn)) exitWith {_nearestVehicle = _x};
if ([_object, _x] call FUNC(canLoadItemIn)) exitWith {_vehicle = _x};
} foreach (nearestObjects [_player, ["Cargo_base_F", "Land_PaperBox_closed_F"], MAX_LOAD_DISTANCE]);
};
if (isNull _nearestVehicle) exitWith {false};
if (isNull _vehicle) exitWith {false};
[_object, _nearestVehicle] call FUNC(loadItem)
// Start progress bar
if ([_object, _vehicle] call FUNC(canLoadItemIn)) then {
_size = [_object] call FUNC(getSizeItem);
[5 * _size, [_object,_vehicle], "LoadCargo", {}, localize LSTRING(LoadingItem)] call EFUNC(common,progressBar);
} else {
_displayName = getText (configFile >> "CfgVehicles" >> typeOf _object >> "displayName");
["displayTextStructured", [[LSTRING(LoadingFailed), _displayName], 3.0]] call EFUNC(common,localEvent);
};

View File

@ -20,7 +20,7 @@ private ["_display", "_loaded", "_ctrl", "_selected", "_item"];
disableSerialization;
_display = uiNamespace getVariable QGVAR(menuDisplay);
if (isnil "_display") exitWith {};
if (isNil "_display") exitWith {};
_loaded = GVAR(interactionVehicle) getVariable [QGVAR(loaded), []];
if (count _loaded == 0) exitWith {};
@ -32,4 +32,17 @@ _selected = (lbCurSel _ctrl) max 0;
if (count _loaded <= _selected) exitWith {};
_item = _loaded select _selected;
[_item, GVAR(interactionVehicle)] call FUNC(unloadItem);
// Start progress bar
private ["_size", "_itemClass", "_displayName"];
if ([_item, GVAR(interactionVehicle)] call FUNC(canUnloadItem)) then {
_size = [_item] call FUNC(getSizeItem);
[5 * _size, [_item, GVAR(interactionVehicle)], "UnloadCargo", {}, localize LSTRING(UnloadingItem)] call EFUNC(common,progressBar);
} else {
_itemClass = if (typeName _item == "STRING") then {_item} else {typeOf _item};
_displayName = getText (configFile >> "CfgVehicles" >> _itemClass >> "displayName");
["displayTextStructured", [[LSTRING(UnloadingFailed), _displayName], 3.0]] call EFUNC(common,localEvent);
};

View File

@ -3,7 +3,7 @@
* Unload object from vehicle.
*
* Arguments:
* 0: Object <OBJECT>
* 0: Item <OBJECT or STRING>
* 1: Vehicle <OBJECT>
*
* Return value:
@ -16,20 +16,21 @@
*/
#include "script_component.hpp"
private ["_loaded", "_space", "_itemSize", "_emptyPos", "_validVehiclestate"];
params ["_item", "_vehicle"];
private ["_loaded", "_space", "_itemSize", "_emptyPos", "_validVehiclestate"];
if !([_item, _vehicle] call FUNC(canUnloadItem)) exitWith {
false
};
_itemClass = if (typeName _item == "STRING") then {_item} else {typeOf _item};
_validVehiclestate = true;
_emptyPos = [];
if (_vehicle isKindOf "Ship" ) then {
if !(speed _vehicle <1 && {(((getPosATL _vehicle) select 2) < 2)}) then {_validVehiclestate = false};
TRACE_1("SHIP Ground Check", getPosATL _vehicle );
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, typeOf _item]); // TODO: if spot is underwater pick another spot.
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 15, _itemClass]); // TODO: if spot is underwater pick another spot.
} else {
if (_vehicle isKindOf "Air" ) then {
if !(speed _vehicle <1 && {isTouchingGround _vehicle}) then {_validVehiclestate = false};
@ -39,38 +40,29 @@ if (_vehicle isKindOf "Ship" ) then {
} else {
if !(speed _vehicle <1 && {(((getPosATL _vehicle) select 2) < 2)}) then {_validVehiclestate = false};
TRACE_1("Vehicle Ground Check", isTouchingGround _vehicle);
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 13, typeOf _item]);
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 13, _itemClass]);
};
};
TRACE_1("getPosASL Vehicle Check", getPosASL _vehicle);
if (!_validVehiclestate) exitWith {false};
if (count _emptyPos == 0) exitWith {false}; //consider displaying text saying there are no safe places to exit the vehicle
if (count _emptyPos == 0) exitWith {false};
_loaded = _vehicle getVariable [QGVAR(loaded), []];
_loaded = _loaded - [_item];
_loaded deleteAt (_loaded find _item);
_vehicle setVariable [QGVAR(loaded), _loaded, true];
_space = [_vehicle] call FUNC(getCargoSpaceLeft);
_itemSize = [_item] call FUNC(getSizeItem);
_vehicle setVariable [QGVAR(space), (_space + _itemSize), true];
detach _item;
_item setPosASL (_emptyPos call EFUNC(common,PositiontoASL));
["hideObjectGlobal", [_item, false]] call EFUNC(common,serverEvent);
// show hint
private ["_itemName", "_vehicleName"];
_itemName = getText (configFile >> "CfgVehicles" >> typeOf _item >> "displayName");
_vehicleName = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName");
["displayTextStructured", [[localize LSTRING(UnloadedItem), _itemName, _vehicleName], 3.0]] call EFUNC(common,localEvent);
// TOOO maybe drag/carry the unloaded item?
// Invoke listenable event
["cargoUnloaded", [_item, _vehicle]] call EFUNC(common,globalEvent);
if (typeName _item == "OBJECT") then {
detach _item;
_item setPosASL (_emptyPos call EFUNC(common,PositiontoASL));
["hideObjectGlobal", [_item, false]] call EFUNC(common,serverEvent);
} else {
createVehicle [_item, _emptyPos, [], 0, ""];
};
true

View File

@ -24,7 +24,7 @@ _loaded = _vehicle getVariable [QGVAR(loaded), []];
_newLoaded = [];
_totalSpaceOccupied = 0;
{
if !(isNull _x) then {
if ((typeName _x == "STRING") || {!isNull _x}) then {
_newLoaded pushback _x;
_totalSpaceOccupied = _totalSpaceOccupied + ([_x] call FUNC(getSizeItem));
};
@ -35,4 +35,4 @@ if (count _loaded != count _newLoaded) then {
_vehicle setVariable [QGVAR(loaded), _newLoaded, true];
};
_vehicle setVariable [QGVAR(space), getNumber (configFile >> "CfgVehicles" >> typeof _vehicle >> QGVAR(space)) - _totalSpaceOccupied, true];
_vehicle setVariable [QGVAR(space), getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> QGVAR(space)) - _totalSpaceOccupied, true];

View File

@ -95,5 +95,17 @@
<Hungarian>1%&lt;br/&gt;kirakodva ebből:&lt;br/&gt;%2</Hungarian>
<Russian>%1&lt;br/&gt;разгружен из&lt;br/&gt;%2</Russian>
</Key>
<Key ID="STR_ACE_Cargo_LoadingItem">
<English>Loading Cargo</English>
</Key>
<Key ID="STR_ACE_Cargo_UnloadingItem">
<English>Unloading Cargo</English>
</Key>
<Key ID="STR_ACE_Cargo_LoadingFailed">
<English>%1&lt;br/&gt;could not be loaded</English>
</Key>
<Key ID="STR_ACE_Cargo_UnloadingFailed">
<English>%1&lt;br/&gt;could not be unloaded</English>
</Key>
</Package>
</Project>