mirror of
https://github.com/EpochModTeam/DayZ-Epoch.git
synced 2025-12-13 19:52:38 +03:00
Bases count as a secure area now. This means it will not rain through a base any longer. Also the temperature will not drop when you are inside of your base. This also affects snow, blizzards and evr storms. Made by @Victor-the-Cleaner
178 lines
7.3 KiB
Plaintext
178 lines
7.3 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// fn_isInsideBuilding.sqf
|
|
//
|
|
// Author: Victor the Cleaner
|
|
// Date: April 2022
|
|
//
|
|
// [_unit] call fnc_isInsideBuilding;
|
|
//
|
|
// Called continuously from player_checkStealth.
|
|
// Used for temperature, stealth vs zombies, and blizzard effects.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
local _unit = _this select 0; // player
|
|
local _inside = false;
|
|
local _scan = 3; // horizontal radius around player (in meters)
|
|
local _zenith = 50; // scan height above and below player
|
|
local _posASL = aimPos _unit; // center of mass (ASL)
|
|
local _posLowASL = getPosASL _unit; // foot of player (ASL)
|
|
_posLowASL set [2, (_posLowASL select 2) + 0.3]; // shin level, below most windows
|
|
|
|
local _posX = _posASL select 0;
|
|
local _posY = _posASL select 1;
|
|
local _posZ = _posASL select 2;
|
|
local _posLowZ = _posLowASL select 2;
|
|
|
|
local _insideBox = objNull; // object the player is inside of
|
|
local _dir = 0;
|
|
local _type = ""; // class name
|
|
local _roofAbove = false; // is there geometry above
|
|
local _intersect = false; // for raycast
|
|
local _hit = []; // array to record hits and misses
|
|
local _idx = 0; // initialize
|
|
local _truth = []; // used with the _hit array
|
|
|
|
local _cowsheds = ["Land_Farm_Cowshed_a","Land_Farm_Cowshed_b","Land_Farm_Cowshed_c"];
|
|
local _isCowshed = false; // special case objects
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Functions
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
local _checkBox = {
|
|
local _object = _this select 0; // object
|
|
_type = typeOf _object; // class name
|
|
|
|
if (_type isKindOf "House" || {_type isKindOf "Church" || {_type in DZE_insideExceptions}}) then {
|
|
|
|
local _pos = _object worldToModel (ASLToATL _posASL);
|
|
local _max = (boundingBox _object) select 1;
|
|
_insideBox = _object;
|
|
|
|
for "_i" from 0 to 2 do {
|
|
if (abs (_pos select _i) > (_max select _i)) exitWith {_insideBox = objNull;};
|
|
};
|
|
};
|
|
};
|
|
local _scanUp = {
|
|
local _pos = [_posX, _posY, _posZ + _zenith];
|
|
local _arr = lineIntersectsWith [_posASL, _pos, _unit, objNull, true]; // sorted (nearest last)
|
|
|
|
for "_i" from (count _arr - 1) to 0 step -1 do { // count backwards
|
|
[_arr select _i] call _checkBox; // validate object
|
|
if (!isNull _insideBox) exitWith {_roofAbove = true;}; // player is within bounds of a candidate object
|
|
};
|
|
};
|
|
local _scanDown = {
|
|
local _pos = [_posX, _posY, _posZ - _zenith];
|
|
local _arr = lineIntersectsWith [_posASL, _pos, _unit, objNull, true]; // sorted (nearest last)
|
|
|
|
for "_i" from (count _arr - 1) to 0 step -1 do { // count backwards
|
|
[_arr select _i] call _checkBox; // validate object
|
|
if (!isNull _insideBox) exitWith {}; // player is within bounds of a candidate object
|
|
};
|
|
};
|
|
local _scanNear = {
|
|
local _north = [_posX, _posY + _scan, _posZ];
|
|
local _east = [_posX + _scan, _posY, _posZ];
|
|
local _south = [_posX, _posY - _scan, _posZ];
|
|
local _west = [_posX - _scan, _posY, _posZ];
|
|
local _cp = [_north, _east, _south, _west, _north]; // compass points
|
|
|
|
scopeName "near";
|
|
for "_i" from 0 to 3 do {
|
|
local _arr = lineIntersectsWith [_cp select _i, _cp select (_i + 1)]; // unsorted
|
|
{
|
|
[_x] call _checkBox; // validate object
|
|
if (!isNull _insideBox) then {breakTo "near";}; // player is within bounds of a candidate object
|
|
} count _arr;
|
|
};
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Cowsheds are arranged from 3 separate classes. Therefore, we need to allow adjacent
|
|
// cowshed class names as substitutes for the object we're scanning.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
local _cowshedCheck = {
|
|
local _array = _this select 0;
|
|
if (_isCowshed) then {
|
|
{
|
|
if (typeOf _x in _cowsheds) exitWith { // is object of similar type?
|
|
_intersect = true; // override radial scan
|
|
_truth set [0,49]; // force hit detection
|
|
};
|
|
} forEach _array;
|
|
};
|
|
};
|
|
local _checkWalls = {
|
|
// known problem buildings
|
|
if (_type == (_cowsheds select 2) && _idx in [3]) exitWith {_hit set [_idx, 49];}; // simulate wall at East sector
|
|
if (_type == (_cowsheds select 1) && _idx in [3,11]) exitWith {_hit set [_idx, 49];}; // simulate walls at East and West sectors
|
|
if (_type == (_cowsheds select 0) && _idx in [11]) exitWith {_hit set [_idx, 49];}; // simulate wall at West sector
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Initial scan to determine if player is above, below, or near a building
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
call _scanUp;
|
|
if (isNull _insideBox) then { // no detectable roof
|
|
call _scanDown;
|
|
if (isNull _insideBox) then { // no detectable floor
|
|
call _scanNear;
|
|
};
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// If player is inside a bounding box, perform radial scan and determine the outcome
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
if (!isNull _insideBox) then { // bounding box detected
|
|
_dir = getDir _insideBox; // direction of object on map
|
|
local _rad = sizeOf (typeOf _insideBox); // scan radius
|
|
local _seg = 16; // radial scan density (must be evenly divisible by 4)
|
|
local _arc = 360 / _seg; // radial scan delta
|
|
local _miss = "00000"; // must be (_seg / 4 + 1) characters in length -- the number of consecutive misses before player is determined to be outside
|
|
_isCowshed = _type in _cowsheds; // special case for known problem buildings
|
|
|
|
for "_n" from _arc to 360 step _arc do { // perform radial scan
|
|
local _angle = (_dir + _n) % 360; // normalize from 0 to 360
|
|
local _a = (sin _angle) * _rad; // X offset
|
|
local _b = (cos _angle) * _rad; // Y offset
|
|
local _v = [_posX + _a, _posY + _b, _posZ]; // radial vector
|
|
_truth = [48,49]; // [miss,hit]
|
|
|
|
local _arr = lineIntersectsWith [_posASL, _v, _unit]; // raycast
|
|
_intersect = (_insideBox in _arr); // did an intersect occur?
|
|
[_arr] call _cowshedCheck; // check known problem buildings
|
|
|
|
if (!_intersect && _roofAbove) then { // if no hit at chest level, check lower. This eliminates most normal windows.
|
|
_v = [_posX + _a, _posY + _b, _posLowZ]; // radial vector Low
|
|
_arr = lineIntersectsWith [_posLowASL, _v, _unit]; // raycast
|
|
[_arr] call _cowshedCheck; // re-check known problem buildings
|
|
};
|
|
_hit set [_idx, _truth select (_insideBox in _arr)]; // record hit or miss
|
|
call _checkWalls; // simulate walls for known problem buildings, and override scan
|
|
_idx = _idx + 1;
|
|
};
|
|
|
|
for "_i" from 0 to 3 do {
|
|
_hit set [_seg + _i, _hit select _i]; // loop (_seg / 4) times to allow wrap-around search
|
|
};
|
|
if (!_roofAbove) then {_miss = "0000";}; // if player is on a roof or in an open area, reduce the consecutive miss criteria by one arc
|
|
|
|
if !([_miss, toString _hit] call fnc_inString) then { // if there are no sufficient consecutive misses, then player is deemed to be inside
|
|
_inside = true;
|
|
};
|
|
};
|
|
dayz_insideBuilding = [objNull, _insideBox] select _inside;
|
|
_dir call fnc_isSheltered;
|
|
_inside
|