class CfgPlayerRestrictedAreaJsonData { ref array m_ValidatedAreas = new array(); ref array m_Areas = new array(); bool InitializeAreas() { m_ValidatedAreas.Clear(); foreach (PlayerRestrictedAreaInstance instance : m_Areas) { instance.Initialize(); if (instance.IsValid()) m_ValidatedAreas.Insert(instance); } m_Areas.Clear(); return m_ValidatedAreas.Count() > 0; } }; class PRAShapeDataBase { void PRAShapeDataBase(array> shapeDataArray) { InitPRAShapeData(shapeDataArray); } void InitPRAShapeData(array> shapeDataArray) { } } class PRAShapeBoxData : PRAShapeDataBase { vector m_Mins; vector m_Maxs; vector m_Mat4[4]; override void InitPRAShapeData(array> shapeDataArray) { vector sizes = Vector(shapeDataArray[0][0],shapeDataArray[0][1],shapeDataArray[0][2]); vector angle = Vector(shapeDataArray[1][0],shapeDataArray[1][1],shapeDataArray[1][2]); vector targetPoint = Vector(shapeDataArray[2][0],shapeDataArray[2][1],shapeDataArray[2][2]); m_Mins = Vector(-sizes[0]/2,-sizes[1]/2,-sizes[2]/2); m_Maxs = Vector(sizes[0]/2,sizes[1]/2,sizes[2]/2); vector mat3[3]; Math3D.YawPitchRollMatrix(angle,mat3); m_Mat4[0] = mat3[0]; m_Mat4[1] = mat3[1]; m_Mat4[2] = mat3[2]; m_Mat4[3] = targetPoint; } } class PlayerRestrictedAreaInstance { //private private bool m_IsValid = false; private int m_LastUsedSafePosIdx = -1; private ref array m_TranslatedSafePositions3D; private ref array m_RandomizedSafePositions3D; //private ref map m_TimeIndexedSafePositions; private vector m_CenterPos2D; //averaged center position, used for initial filtering //public string areaName = ""; //optional ref array>> PRABoxes = new array>>; //!3D, not used directly! ref array>> PRAPolygons = new array>>; //2D ref array> safePositions2D = new array>; ref array> safePositions3D = new array>; ref array m_PRABoxDataTranslated = new array; //translated data void Initialize() { if (m_IsValid) return; m_IsValid = false; m_IsValid |= ValidatePlayerRestrictedAreaPositions(); m_IsValid |= TranslateSafePositions(); } private bool ValidatePlayerRestrictedAreaPositions() { if (PRABoxes.Count() == 0 && PRAPolygons.Count() == 0) { Debug.Log("No valid coordinates in 'PRABoxes' or 'PRAPolygons' for area: " + areaName,"n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } float xMin,zMin = float.MAX; float xMax,zMax = float.MIN; foreach (array> boxFloatsData : PRABoxes) { if (boxFloatsData.Count() != 3) { Debug.Log("Invalid box defined in " + areaName + ". Box needs to have sizes, rotation, and position defined!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } array boxVectors; //sizes boxVectors = boxFloatsData[0]; if (boxVectors.Count() != 3) { Debug.Log("Invalid box defined in " + areaName + ". Box size needs to be in an XYZ format!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } //rotation boxVectors = boxFloatsData[1]; if (boxVectors.Count() != 3) { Debug.Log("Invalid box defined in " + areaName + ". Box rotation needs to be in an XYZ format!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } //position boxVectors = boxFloatsData[2]; if (boxVectors.Count() != 3) { Debug.Log("Invalid box defined in " + areaName + ". Box position needs to be in an XYZ format!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } //translate to data PRAShapeBoxData dta = new PRAShapeBoxData(boxFloatsData); if (dta) { m_PRABoxDataTranslated.Insert(dta); xMin = Math.Min(xMin,dta.m_Mins[0]); zMin = Math.Min(zMin,dta.m_Mins[2]); xMax = Math.Max(xMax,dta.m_Maxs[0]); zMax = Math.Max(zMax,dta.m_Maxs[2]); } } foreach (array> polygonData : PRAPolygons) { if (polygonData.Count() < 3) { Debug.Log("Invalid polygon defined in " + areaName + ". At least 3 points necessary!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } foreach (array polygonCoords : polygonData) { if (polygonCoords.Count() != 2) { Debug.Log("Invalid polygon defined in " + areaName + ". Polygon coordinates need to be in a XZ format!","n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } xMin = Math.Min(xMin,polygonCoords[0]); zMin = Math.Min(zMin,polygonCoords[1]); xMax = Math.Max(xMax,polygonCoords[0]); zMax = Math.Max(zMax,polygonCoords[1]); } } m_CenterPos2D = Vector(((xMin + xMax) / 2), 0, ((zMin + zMax) / 2)); return true; } private bool TranslateSafePositions() { if (safePositions2D.Count() == 0 && safePositions3D.Count() == 0) { Debug.Log("Undefined safe positions for area: " + areaName,"n/a","n/a","","PlayerRestrictedAreaInstance"); return false; } m_TranslatedSafePositions3D = new array; foreach (array arr2d : safePositions2D) { m_TranslatedSafePositions3D.Insert(Vector(arr2d[0],GetGame().SurfaceY(arr2d[0],arr2d[1]),arr2d[1])); } foreach (array arr3d : safePositions3D) { m_TranslatedSafePositions3D.Insert(Vector(arr3d[0],arr3d[1],arr3d[2])); } return true; } bool IsValid() { return m_IsValid; } vector GetCenterPos2D() { return m_CenterPos2D; } //---------------------------------------------------------- //getters vector GetClosestSafePos3D(vector targetPos) { vector closestPos = targetPos; float smallestDist = float.MAX; float dist; foreach (vector pos : m_TranslatedSafePositions3D) { dist = vector.DistanceSq(targetPos, pos); if (dist < smallestDist) { smallestDist = dist; closestPos = pos; } } return closestPos; } vector GetRandomSafePos3D(vector targetPos) { if (!m_RandomizedSafePositions3D || m_RandomizedSafePositions3D.Count() == 0) { m_RandomizedSafePositions3D = new array; m_RandomizedSafePositions3D.Copy(m_TranslatedSafePositions3D); m_LastUsedSafePosIdx = -1; } int count = m_RandomizedSafePositions3D.Count(); m_LastUsedSafePosIdx++; if (m_LastUsedSafePosIdx == count) { m_RandomizedSafePositions3D.ShuffleArray(); m_LastUsedSafePosIdx = 0; } return m_RandomizedSafePositions3D[m_LastUsedSafePosIdx]; } }