mirror of
https://github.com/EpochModTeam/DayZ-Epoch.git
synced 2025-12-14 04:02:37 +03:00
215 lines
6.9 KiB
Plaintext
215 lines
6.9 KiB
Plaintext
/*
|
|
Created exclusively for ArmA2:OA - DayZMod.
|
|
Please request permission to use/alter/distribute from project leader (R4Z0R49) AND the author (facoptere@gmail.com)
|
|
*/
|
|
|
|
// Check/find a spot before pitching "Land_Fire_DZ", "TentStorage", "Wire_cat1", "Sandbag1_DZ" or "Hedgehog_DZ"
|
|
// _this 0: object class
|
|
// _this 1: object (player) or array (ATL format)
|
|
// _this 2: optional, empty array that will be filled by computed boolean: _testonLadder, _testSea, _testPond, _testBuilding, _testSlope, _testDistance
|
|
// return a worldspace consisting of array [ direction, ATL position ] or empty array if no position is found
|
|
// if 2nd argument is a player, the position returned is just in front of the player, direction is so that the object is "looking to" the player
|
|
|
|
private ["_booleans","_class","_isPlayer","_size","_testPond","_testBuilding","_testonLadder","_testSlope","_testSea","_testDistance","_noCollision","_dir","_obj","_objectsPond","_ok","_maxdistance","_x","_new","_pos"];
|
|
|
|
_class = _this select 0;
|
|
_pos = _this select 1;
|
|
|
|
_realSize = {
|
|
[[0,0], (boundingBox _this) select 1] call BIS_fnc_distance2D
|
|
};
|
|
|
|
// check that tent position is outside the pool footprint.
|
|
// we can't check altitude since pool has no height
|
|
_checkPerimeter = {
|
|
private ["_inside","_relPos","_point","_boundingBox","_min","_max","_myX","_myY","_building"];
|
|
|
|
_building = _this select 0;
|
|
_point = _this select 1;
|
|
_inside = false;
|
|
|
|
_relPos = _building worldToModel _point;
|
|
_boundingBox = boundingBox _building;
|
|
//diag_log format ["%1 %2", _relPos, _boundingBox];
|
|
_min = _boundingBox select 0;
|
|
_max = _boundingBox select 1;
|
|
_myX = _relPos select 0;
|
|
_myY = _relPos select 1;
|
|
|
|
if ((_myX > (_min select 0)) and {(_myX < (_max select 0))}) then {
|
|
if ((_myY > (_min select 1)) and {(_myY < (_max select 1))}) then {
|
|
_inside = true;
|
|
};
|
|
};
|
|
|
|
_inside
|
|
};
|
|
|
|
// check if _pos a player object or some ATL coordinates array
|
|
_isPlayer = (typeName _pos != "ARRAY");
|
|
|
|
_testBuilding = true;
|
|
_testDistance = _isPlayer;
|
|
_maxdistance = 5;
|
|
_testonLadder = _isPlayer;
|
|
_testPond = false;
|
|
_testSea = false;
|
|
_testSlope = false;
|
|
_noCollision = false;
|
|
switch _class do {
|
|
case "TentStorage" : { // tent pitching must follow all restrictions
|
|
_testPond = true;
|
|
_testSea = true;
|
|
};
|
|
case "DomeTentStorage" : { // tent pitching must follow all restrictions
|
|
_testPond = true;
|
|
_testSea = true;
|
|
};
|
|
case "StashSmall" : {
|
|
_testPond = true;
|
|
_testSea = true;
|
|
};
|
|
case "StashMedium" : {
|
|
_testPond = true;
|
|
_testSea = true;
|
|
};
|
|
case "Land_Fire_DZ" : { // no fire in the water :)
|
|
_testPond = true;
|
|
_testSea = true;
|
|
};
|
|
case "CamoNet_DZ" : { // no fire in the water :)
|
|
_testPond = true;
|
|
_testSea = true;
|
|
_testSlope = false;
|
|
_noCollision = false;
|
|
_testBuilding = false;
|
|
};
|
|
case "Wire_cat1" : {};
|
|
case "Sandbag1_DZ" : {};
|
|
case "Hedgehog_DZ" : {};
|
|
default { // = vehicles (used for hive maintenance on startup)
|
|
_testBuilding = false;
|
|
_testSlope = false;
|
|
_noCollision = false;
|
|
};
|
|
};
|
|
|
|
//diag_log(format["niceSpot: will test: pond:%1 building:%2 slope:%3 sea:%4 distance:%5 collide:%6", _testPond, _testBuilding, _testSlope, _testSea, _testDistance, _noCollision]);
|
|
|
|
_dir = if (_isPlayer) then {getDir(_pos)} else {0};
|
|
_obj = _class createVehicleLocal (getMarkerpos "respawn_west");
|
|
sleep 0.01;
|
|
_size = _obj call _realSize;
|
|
if (_isPlayer) then { _size = _size + (_pos call _realSize); };
|
|
|
|
// compute initial position. If _pos is the player, then the object will be in front of him/her
|
|
_new = nil;
|
|
_new = if (_isPlayer) then { _pos modeltoworld [0,_size/2,0] } else { _pos };
|
|
_new set [2, 0];
|
|
|
|
// place a temporary object (not colliding or can colliding)
|
|
if (_noCollision) then {
|
|
deleteVehicle _obj;
|
|
sleep 0.01;
|
|
_obj = _class createVehicleLocal _new;
|
|
// get non colliding position
|
|
_new = getPosATL _obj;
|
|
// get relative angle of object position according to player PoV
|
|
if (_isPlayer) then {
|
|
_x = _pos worldToModel _new;
|
|
_dir = _dir + (if ((_x select 1)==0) then { 0 } else { (_x select 0) atan2 (_x select 1) });
|
|
};
|
|
} else {
|
|
_obj setDir _dir;
|
|
_obj setPosATL(_new);
|
|
};
|
|
|
|
if (_testBuilding) then { // let's proceed to the "something or its operator in a building" test
|
|
_testBuilding = (([_obj, true] call fnc_isInsideBuilding) // obj in/close to a building (enterable or not)
|
|
// or _pos is a player who is in a *enterable* building
|
|
OR {(_isPLayer AND {([_pos, false] call fnc_isInsideBuilding)})});
|
|
};
|
|
|
|
deleteVehicle _obj;
|
|
sleep 0.01;
|
|
|
|
if (_testPond) then { // let's proceed to the "object in the pond" test (not dirty)
|
|
_testPond = false;
|
|
_objectsPond = nearestObjects [_new, [], 100];
|
|
{
|
|
if (((typeOf(_x) == "") // unnamed class?
|
|
AND {((((_x worldToModel _new) select 2) < 0)) // below water level?
|
|
AND {([_x, _new] call _checkPerimeter)}}) // inside pond square footprint?
|
|
AND {(["pond", str(_x), false] call fnc_inString)} // and is actually a pond?
|
|
) exitWith {
|
|
_testPond = true;
|
|
};
|
|
} forEach _objectsPond;
|
|
};
|
|
|
|
if (_testSlope) then { // "flat spot" test
|
|
_testSlope = false;
|
|
_x = _new isflatempty [
|
|
0, // don't check collisions
|
|
0, // don't look around
|
|
(0.1*_size), // slope gradient
|
|
_size, // object size
|
|
1, // do not check in the sea
|
|
false, // don't check far from shore
|
|
if (_isPlayer) then {_pos} else {objNull} // not used -- seems buggy.
|
|
];
|
|
if (count _x < 2) then { // safepos found (gradient ok AND not in sea water)
|
|
_testSlope = true;
|
|
};
|
|
};
|
|
|
|
if (_testSea) then { // "not in the sea, not on the beach" test
|
|
_testSea = false;
|
|
_x = _new isflatempty [
|
|
0, // don't check collisions
|
|
0, // don't look around
|
|
999, // do not check slope gradient
|
|
_size, // object size
|
|
0, // check not in the sea
|
|
false, // don't check far from shore
|
|
if (_isPlayer) then {_pos} else {objNull} // not used -- seems buggy.
|
|
];
|
|
if (count _x < 2) then { // safepos found (gradient ok AND not in sea water)
|
|
_testSea = true;
|
|
}
|
|
else {
|
|
_x set [2,0];
|
|
_x = ATLtoASL _x;
|
|
if (_x select 2 < 3) then { // in the wave foam
|
|
_testSea = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
if (_testDistance) then { // check effective distance from the player
|
|
_testDistance = ((_pos distance _new) > _maxdistance);
|
|
};
|
|
|
|
if (_testonLadder) then { // forbid item install process if player is on a ladder (or in a vehicle)
|
|
_testonLadder = (
|
|
((getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> (animationState _pos) >> "onLadder")) == 1)
|
|
OR {((isPlayer _pos) AND {((vehicle _pos) != _pos)})}
|
|
);
|
|
};
|
|
|
|
//diag_log(format["niceSpot: result pond:%1 building:%2 slope:%3 sea:%4 distance:%5 collide:%6", _testPond, _testBuilding, _testSlope, _testSea, _testDistance, _noCollision]);
|
|
|
|
_ok = !_testPond AND !_testBuilding AND !_testSlope AND !_testSea AND !_testDistance AND !_testonLadder;
|
|
if (count _this > 2) then {
|
|
_booleans = _this select 2;
|
|
_booleans set [0, _testonLadder];
|
|
_booleans set [1, _testSea];
|
|
_booleans set [2, _testPond];
|
|
_booleans set [3, _testBuilding];
|
|
_booleans set [4, _testSlope];
|
|
_booleans set [5, _testDistance];
|
|
//diag_log(format["niceSpot: booleans: %1", _booleans]);
|
|
};
|
|
|
|
if (_ok) then { [round(_dir), _new] } else { [] }
|