Add findUnloadPosition integration

This commit is contained in:
PabstMirror 2016-01-26 18:01:01 -06:00
parent 1a98726716
commit 17a882fe4d
11 changed files with 159 additions and 104 deletions

View File

@ -21,9 +21,9 @@
}] call EFUNC(common,addEventHandler);
["UnloadCargo", {
(_this select 0) params ["_item","_vehicle"];
(_this select 0) params ["_item","_vehicle", ["_unloader", objNull]];
private _unloaded = [_item, _vehicle] call FUNC(unloadItem);
private _unloaded = [_item, _vehicle, _player] call FUNC(unloadItem);
private _itemClass = if (_item isEqualType "") then {_item} else {typeOf _item};

View File

@ -5,6 +5,7 @@
* Arguments:
* 0: loaded Object <OBJECT>
* 1: Object <OBJECT>
* 2: Unloader (player) <OPTIONAL><OBJECT>
*
* Return value:
* Can be unloaded <BOOL>
@ -16,7 +17,7 @@
*/
#include "script_component.hpp"
params ["_item", "_vehicle"];
params ["_item", "_vehicle", ["_unloader", objNull]];
TRACE_2("params",_item,_vehicle);
private _loaded = _vehicle getVariable [QGVAR(loaded), []];
@ -24,22 +25,6 @@ if !(_item in _loaded) exitWith {false};
private _itemClass = if (_item isEqualType "") then {_item} else {typeOf _item};
private _validVehiclestate = true;
private _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, _itemClass]); // TODO: if spot is underwater pick another spot.
} else {
if (_vehicle isKindOf "Air" ) then {
if !(speed _vehicle <1 && {isTouchingGround _vehicle}) then {_validVehiclestate = false};
_emptyPos = (getPosASL _vehicle) call EFUNC(common,ASLtoPosition);
_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, _itemClass]);
};
};
private _emptyPos = [_vehicle, _itemClass, _unloader] call EFUNC(common,findUnloadPosition);
if (!_validVehiclestate) exitWith {false};
(count _emptyPos != 0)
(count _emptyPos) == 3

View File

@ -43,7 +43,7 @@ if (getNumber (configFile >> "CfgVehicles" >> _type >> QGVAR(hasCargo)) != 1) ex
TRACE_1("Adding unload cargo action to class", _type);
private _condition = {
GVAR(enable) && {locked _target < 2} && {alive _target} && {[_player, _target, []] call EFUNC(common,canInteractWith)}
GVAR(enable) && {locked _target < 2} && {alive _target} && {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)}
};
private _statement = {
GVAR(interactionVehicle) = _target;

View File

@ -31,10 +31,10 @@ if (count _loaded <= _selected) exitWith {};
private _item = _loaded select _selected; //This can be an object or a classname string
// Start progress bar
if ([_item, GVAR(interactionVehicle)] call FUNC(canUnloadItem)) then {
if ([_item, GVAR(interactionVehicle), ACE_player] call FUNC(canUnloadItem)) then {
private _size = [_item] call FUNC(getSizeItem);
[5 * _size, [_item, GVAR(interactionVehicle)], "UnloadCargo", {}, localize LSTRING(UnloadingItem)] call EFUNC(common,progressBar);
[5 * _size, [_item, GVAR(interactionVehicle), ACE_player], "UnloadCargo", {}, localize LSTRING(UnloadingItem)] call EFUNC(common,progressBar);
} else {
private _itemClass = if (_item isEqualType "") then {_item} else {typeOf _item};
private _displayName = getText (configFile >> "CfgVehicles" >> _itemClass >> "displayName");

View File

@ -16,38 +16,31 @@
*/
#include "script_component.hpp"
params ["_item", "_vehicle"];
TRACE_2("params",_item,_vehicle);
params ["_item", "_vehicle", ["_unloader", objNull]];
TRACE_3("params",_item,_vehicle,_unloader);
if !([_item, _vehicle] call FUNC(canUnloadItem)) exitWith {
private _itemClass = if (_item isEqualType "") then {_item} else {typeOf _item};
//This covers testing vehicle stability and finding a safe position
private _emptyPosAGL = [_vehicle, _itemClass, _unloader] call EFUNC(common,findUnloadPosition);
TRACE_1("findUnloadPosition",_emptyPosAGL);
if ((count _emptyPosAGL) != 3) exitWith {
TRACE_4("Could not find unload pos",_vehicle,getPosASL _vehicle,isTouchingGround _vehicle,speed _vehicle);
if ((!isNull _unloader) && {_unloader == ACE_player}) then {
//display text saying there are no safe places to exit the vehicle
["displayTextStructured", [localize ELSTRING(common,NoRoomToUnload)]] call EFUNC(common,localEvent);
};
false
};
_itemClass = if (_item isEqualType "") then {_item} else {typeOf _item};
private _loaded = _vehicle getVariable [QGVAR(loaded), []];
private _validVehiclestate = true;
private _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, _itemClass]); // TODO: if spot is underwater pick another spot.
} else {
if (_vehicle isKindOf "Air" ) then {
if !(speed _vehicle <1 && {isTouchingGround _vehicle}) then {_validVehiclestate = false};
TRACE_1("Vehicle Ground Check", isTouchingGround _vehicle);
_emptyPos = (getPosASL _vehicle) call EFUNC(common,ASLtoPosition);
_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};
TRACE_1("Vehicle Ground Check", isTouchingGround _vehicle);
_emptyPos = ((getPosASL _vehicle) call EFUNC(common,ASLtoPosition) findEmptyPosition [0, 13, _itemClass]);
};
if !(_item in _loaded) exitWith {
ACE_LOGERROR_3("Tried to unload item [%1] not in vehicle[%2] cargo[%3]", _item, _vehicle, _loaded);
false
};
TRACE_1("getPosASL Vehicle Check", getPosASL _vehicle);
if ((!_validVehiclestate) || {_emptyPos isEqualTo []}) exitWith {false};
private _loaded = _vehicle getVariable [QGVAR(loaded), []];
_loaded deleteAt (_loaded find _item);
_vehicle setVariable [QGVAR(loaded), _loaded, true];
@ -57,10 +50,11 @@ _vehicle setVariable [QGVAR(space), (_space + _itemSize), true];
if (_item isEqualType objNull) then {
detach _item;
_item setPosASL (_emptyPos call EFUNC(common,PositiontoASL));
_item setPosASL (AGLtoASL _emptyPosAGL);
["hideObjectGlobal", [_item, false]] call EFUNC(common,serverEvent);
} else {
createVehicle [_item, _emptyPos, [], 0, ""];
private _newItem = createVehicle [_item, _emptyPosAGL, [], 0, ""];
_newItem setPosASL (AGLtoASL _emptyPosAGL);
};
true

View File

@ -47,6 +47,7 @@ PREP(execPersistentFnc);
PREP(execRemoteFnc);
PREP(executePersistent);
PREP(filter);
PREP(findUnloadPosition);
PREP(fixCollision);
PREP(fixFloating);
PREP(fixLoweredRifleAnimation);

View File

@ -0,0 +1,102 @@
/*
* Author: PabstMirror, ViperMaul
* Find a safe place near a vehicle to unload something
* Handles Normal Terrain, In Water or On Buildings (Pier, StaticShip)
*
* Arguments:
* 0: Source Vehicle <OBJECT>
* 1: Cargo Classname <STRING>
* 2: Unloader (player) <OBJECT><OPTIONAL>
* 3: Max Distance (meters) <NUMBER><OPTIONAL>
* 4: Check Vehicle is Stable <BOOL><OPTIONAL>
*
* Return Value:
* Unload PositionAGL (Can Be [] if no valid pos found) <ARRAY>
*
* Example:
* [theCar, "CAManBase", player, 10, true] call ace_common_fnc_findUnloadPosition;
*
* Public: No
*/
#define DEBUG_MODE_FULL
#include "script_component.hpp"
//Number of tests run
#define MAX_TESTS 50
//Manual collision tests (count and radius):
#define COL_TEST_COUNT 12
params ["_vehicle", "_typeOfCargo", ["_theUnloader", objNull], ["_maxDistance", 10], ["_checkVehicleIsStable", true]];
TRACE_5("params",_vehicle,_typeOfCargo,_theUnloader,_maxDistance,_checkVehicleIsStable);
scopeName "main";
if (_checkVehicleIsStable) 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);
[] breakOut "main";
};
};
private _radiusOfItem = 1.1;
//`sizeOf` is unreliable, and does not work with object types that don't exist on map, so estimate size based on cargo size
if (isNumber (configFile >> "CfgVehicles" >> _typeOfCargo >> QEGVAR(cargo,size))) then {
_radiusOfItem = (((getNumber (configFile >> "CfgVehicles" >> _typeOfCargo >> QEGVAR(cargo,size))) ^ 0.35) max 1.1);
};
if (isNull _theUnloader) then {_theUnloader = _vehicle;};
//Ideal unload pos is halfway between unloader and vehicle
private _originASL = ((getPosASL _theUnloader) vectorAdd (getPosASL _vehicle)) vectorMultiply 0.5;
_originASL set [2, (getPosASL _theUnloader) select 2];
private _originAGL = ASLtoAGL _originASL;
//Do a manual search for empty pos (handles underwater, buildings or piers)
TRACE_2("Checking for unload",_originAGL,_radiusOfItem);
private _rangeToCheck = 0.5;
while {_rangeToCheck < (sqrt _maxDistance)} do {
private _roundAGL = _originAGL vectorAdd [(-1 * _rangeToCheck + (random 2 * _rangeToCheck)), (-1 * _rangeToCheck + (random 2 * _rangeToCheck)), 0];
private _belowRoundArray = lineIntersectsSurfaces [(AGLtoASL _roundAGL) vectorAdd [0,0,0.5], (AGLtoASL _roundAGL) vectorAdd [0,0,-2]];
TRACE_2("Testing Pos",_roundAGL,_belowRoundArray);
if (!(_belowRoundArray isEqualTo [])) then {
private _aboveBuilding = (_belowRoundArray select 0) select 2;
//Point is above something: Terrain(null) or Building
if ((isNull _aboveBuilding) || {_aboveBuilding isKindOf "Building"}) then {
//Get the real intersection point:
_roundAGL = ASLtoAGL ((_belowRoundArray select 0) select 0);
//Do a fast check for people in the way
private _roundPointIsValid = (_roundAGL nearEntities ["Man", _radiusOfItem]) isEqualTo [];
if (_roundPointIsValid) then {
for "_index" from 0 to (COL_TEST_COUNT -1) do {
private _angle = _index * (360 / COL_TEST_COUNT);
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 _testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL];
if (!(_testIntersections isEqualTo [])) exitWith {
TRACE_2("test point not valid",_roundAGL,_testIntersections);
_roundPointIsValid = false;
};
_point1ASL = (AGLtoASL _roundAGL) vectorAdd [_radiusOfItem * cos _angle, _radiusOfItem * sin _angle, 0.5];
_point2ASL = (AGLtoASL _roundAGL) vectorAdd [-_radiusOfItem * cos _angle, -_radiusOfItem * sin _angle, 1];
_testIntersections = lineIntersectsSurfaces [_point1ASL, _point2ASL];
if (!(_testIntersections isEqualTo [])) exitWith {
TRACE_2("test point not valid",_roundAGL,_testIntersections);
_roundPointIsValid = false;
};
};
if (_roundPointIsValid) then {
TRACE_3("Valid point found", _rangeToCheck,_roundAGL, (_originAGL distance _roundAGL));
//Add just a little so we don't sink through the floor:
(_roundAGL vectorAdd [0,0,0.05]) breakOut "main";
};
};
};
};
_rangeToCheck = _rangeToCheck + ((sqrt _maxDistance) / MAX_TESTS);
};
TRACE_1("no valid spots found",_rangeToCheck);
[] //return empty array

View File

@ -8,6 +8,9 @@
* Return Value:
* Returns true if succesfully unloaded person <BOOL>
*
* Example:
* [hurtGuy] call ace_common_fnc_unloadPerson
*
* Public: No
*/
#include "script_component.hpp"
@ -20,14 +23,10 @@ private _vehicle = vehicle _unit;
if (_vehicle == _unit) exitWith {false};
if (speed _vehicle > 1 || getPos _vehicle select 2 > 2) exitWith {false};
private _emptyPos = (getPos _vehicle) findEmptyPosition [0, 10, typeOf _unit]; // @todo to small?
if (count _emptyPos == 0) exitWith {false};
if (speed _vehicle > 1 || {((getPos _vehicle) select 2) > 2}) exitWith {false};
if (!isNull _vehicle) then {
[[_unit], QUOTE(FUNC(unloadPersonLocal)), _unit, false] call FUNC(execRemoteFnc);
["unloadPersonEvent", [_unit], [_unit, _vehicle]] call EFUNC(common,targetEvent);
};
true

View File

@ -3,7 +3,9 @@
* Unload a person from a vehicle, local
*
* Arguments:
* 0: unit <OBJECT>
* 0: unit to unload <OBJECT>
* 1: Vehicle <OBJECT>
* 2: Unloader (player) <OBJECT><OPTIONAL>
*
* Return Value:
* Returns true if succesfully unloaded person <BOOL>
@ -14,53 +16,22 @@
#define GROUP_SWITCH_ID QUOTE(FUNC(loadPerson))
params ["_unit", "_vehicle"];
TRACE_2("params",_unit,_vehicle);
params ["_unit", "_vehicle", ["_unloader", objNull]];
TRACE_3("params",_unit,_vehicle,_unloader);
private _validVehiclestate = true;
private _emptyPos = [];
//This covers testing vehicle stability and finding a safe position
private _emptyPos = [_vehicle, (typeOf _unit), _unloader] call EFUNC(common,findUnloadPosition);
TRACE_1("findUnloadPosition",_emptyPos);
if (_vehicle isKindOf "Ship") then {
if (speed _vehicle > 1 || {getPos _vehicle select 2 > 2}) then {
_validVehiclestate = false;
if (count _emptyPos != 3) exitwith {
ACE_LOGWARNING_4("Could not find unload pos %1-ASL: %2 isTouchingGround: %3 Speed: %4",_vehicle, getPosASL _vehicle, isTouchingGround _vehicle, speed _vehicle);
if ((!isNull _unloader) && {[_unloader] call FUNC(isPlayer)}) then {
//display text saying there are no safe places to exit the vehicle
["displayTextStructured", [_unloader], [localize LSTRING(NoRoomToUnload)]] call FUNC(targetEvent);
};
TRACE_1("SHIP Ground Check",getPos _vehicle);
_emptyPos = (ASLToAGL getPosASL _vehicle) findEmptyPosition [0, 13, typeOf _unit]; // TODO: if spot is underwater pick another spot.
} else {
if (_vehicle isKindOf "Air") then {
if (speed _vehicle > 1 || {!isTouchingGround _vehicle}) then {
_validVehiclestate = false;
};
TRACE_1("Vehicle Ground Check",isTouchingGround _vehicle);
_emptyPos = ASLToAGL getPosASL _vehicle;
_emptyPos = _emptyPos vectorAdd [random 10 - 5, random 10 - 5, 0];
} else {
if (speed _vehicle > 1 || {getPos _vehicle select 2 > 2}) then {
_validVehiclestate = false;
};
TRACE_1("Vehicle Ground Check", isTouchingGround _vehicle);
_emptyPos = (ASLToAGL getPosASL _vehicle) findEmptyPosition [0, 13, typeOf _unit];
};
};
TRACE_1("getPosASL Vehicle Check", getPosASL _vehicle);
if !(_validVehiclestate) exitWith {
ACE_LOGWARNING_4("Unable to unload patient because invalid (%1) vehicle state. Either moving or Not close enough on the ground. position: %2 isTouchingGround: %3 Speed: %4",_vehicle,getPos _vehicle,isTouchingGround _vehicle,speed _vehicle);
false
};
if (count _emptyPos == 0) exitWith {
ACE_LOGWARNING_1("No safe empty spots to unload patient. %1",_emptyPos);
false
}; //consider displaying text saying there are no safe places to exit the vehicle
unassignVehicle _unit;
[_unit] orderGetIn false;
@ -87,16 +58,16 @@ _unit action ["Eject", vehicle _unit];
if ((_unit getVariable "ACE_isUnconscious") and (animationState _unit != _anim)) then {
[_unit, _anim, 2, true] call FUNC(doAnimation);
};
}, [_unit, _anim], 0.5, 0] call FUNC(waitAndExecute);
}, [_unit, _anim], 0.5] call FUNC(waitAndExecute);
};
};
}, [_unit, _emptyPos], 0.5, 0] call FUNC(waitAndExecute);
}, [_unit, _emptyPos], 0.5] call FUNC(waitAndExecute);
[_unit, false, GROUP_SWITCH_ID, side group _unit] call FUNC(switchToGroupSide);
private _loaded = _vehicle getVariable [QGVAR(loaded_persons),[]];
private _loaded = _vehicle getvariable [QGVAR(loaded_persons),[]];
_loaded deleteAt (_loaded find _unit);
_vehicle setVariable [QGVAR(loaded_persons), _loaded, true];
_vehicle setvariable [QGVAR(loaded_persons), _loaded, true];
true

View File

@ -762,5 +762,8 @@
<Czech>ACE3 Vozidla</Czech>
<Spanish>ACE3 Vehículos</Spanish>
</Key>
<Key ID="STR_ACE_Common_NoRoomToUnload">
<English>No Room to unload</English>
</Key>
</Package>
</Project>

View File

@ -21,4 +21,4 @@ params ["_caller", "_target", ["_drag", false]];
if (vehicle _target == _target) exitWith {};
if (([_target] call EFUNC(common,isAwake))) exitWith {};
["unloadPersonEvent", _target, [_target, vehicle _target]] call EFUNC(common,targetEvent)
["unloadPersonEvent", _target, [_target, vehicle _target, _caller]] call EFUNC(common,targetEvent);