cfgplayerrestrictedareahandler.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. class CfgPlayerRestrictedAreaHandler
  2. {
  3. private static bool m_Initialized;
  4. static ref TStringArray m_PRAFiles = new TStringArray();
  5. static ref CfgPlayerRestrictedAreaJsonData m_Data = new CfgPlayerRestrictedAreaJsonData();
  6. //----------------------------------------------------------
  7. //load, inits, validation
  8. static bool LoadData()
  9. {
  10. if (m_Initialized)
  11. return true;
  12. m_Initialized = false;
  13. if (GetGame().ServerConfigGetInt( "enableCfgGameplayFile" )) //only reach into the CfgGameplayHandler if properly loaded!
  14. m_PRAFiles = CfgGameplayHandler.GetPlayerRestrictedAreaFiles();
  15. else
  16. m_PRAFiles = g_Game.GetMission().GetWorldData().GetDefaultPRAPaths();
  17. if (!m_PRAFiles)
  18. return true;
  19. string worldName;
  20. GetGame().GetWorldName(worldName);
  21. foreach (string filename : m_PRAFiles)
  22. {
  23. PlayerRestrictedAreaInstance area = new PlayerRestrictedAreaInstance();
  24. string errorMessage, path;
  25. path = string.Format("$mission:%1", filename);
  26. if (!JsonFileLoader<PlayerRestrictedAreaInstance>.LoadFile(path, area, errorMessage))
  27. {
  28. if (!FileExist(filename))
  29. path = string.Format("dz/worlds/%1/ce/%2", worldName, filename);
  30. if (!JsonFileLoader<PlayerRestrictedAreaInstance>.LoadFile(path, area, errorMessage))
  31. {
  32. ErrorEx(errorMessage);
  33. continue;
  34. }
  35. }
  36. if (area != null)
  37. m_Data.m_Areas.Insert(area);
  38. }
  39. m_Initialized = m_Data.InitializeAreas();
  40. return true;
  41. }
  42. static bool IsInitialized()
  43. {
  44. return m_Initialized;
  45. }
  46. //----------------------------------------------------------
  47. //synchronization
  48. static void SyncDataSend(notnull PlayerIdentity identity)
  49. {
  50. GetGame().RPCSingleParam(null, ERPCs.RPC_PLAYERRESTRICTEDAREAS_SYNC, new Param1<CfgPlayerRestrictedAreaJsonData>(m_Data), true, identity);
  51. }
  52. static void OnRPC(ParamsReadContext ctx)
  53. {
  54. Param1<CfgPlayerRestrictedAreaJsonData> data = new Param1<CfgPlayerRestrictedAreaJsonData>(null);
  55. if (ctx.Read(data))
  56. {
  57. m_Data = data.param1;
  58. m_Initialized = m_Data.m_ValidatedAreas.Count() > 0;
  59. }
  60. else
  61. {
  62. ErrorEx("CfgPlayerRestrictedAreaHandler - client failed to read incoming data");
  63. }
  64. }
  65. //----------------------------------------------------------
  66. //main area checking methods
  67. static bool IsPointInPlayerRestrictedAreaClosest(vector point, out PlayerRestrictedAreaInstance hitArea)
  68. {
  69. if (!IsInitialized())
  70. return false;
  71. PlayerRestrictedAreaInstance area = GetClosestArea(point);
  72. if (area && IsCylinderInAreaBox(area,point) || IsPointInAreaPolygon(area,point))
  73. {
  74. hitArea = area;
  75. return true;
  76. }
  77. return false;
  78. }
  79. static bool IsPointInPlayerRestrictedArea(vector point, out PlayerRestrictedAreaInstance hitArea)
  80. {
  81. if (!IsInitialized())
  82. return false;
  83. foreach (PlayerRestrictedAreaInstance area : m_Data.m_ValidatedAreas)
  84. {
  85. if (IsCylinderInAreaBox(area,point) || IsPointInAreaPolygon(area,point))
  86. {
  87. hitArea = area;
  88. return true;
  89. }
  90. }
  91. return false;
  92. }
  93. //----------------------------------------------------------
  94. //support methods
  95. private static PlayerRestrictedAreaInstance GetClosestArea(vector point)
  96. {
  97. PlayerRestrictedAreaInstance ret;
  98. float closestDist = float.MAX;
  99. float currentDist;
  100. foreach (PlayerRestrictedAreaInstance area : m_Data.m_ValidatedAreas)
  101. {
  102. currentDist = vector.DistanceSq(point,area.GetCenterPos2D());
  103. if (currentDist < closestDist)
  104. {
  105. ret = area;
  106. closestDist = currentDist;
  107. }
  108. }
  109. return ret;
  110. }
  111. //! default cylinder values sufficient for player detection
  112. private static bool IsCylinderInAreaBox(notnull PlayerRestrictedAreaInstance area, vector point, float cylinderRadius = 0.25, float cylinderHeight = 1)
  113. {
  114. foreach (PRAShapeBoxData boxData : area.m_PRABoxDataTranslated)
  115. {
  116. vector matPlayer4[4];
  117. Math3D.MatrixIdentity4(matPlayer4);
  118. matPlayer4[3] = point;
  119. if (Math3D.IntersectCylinderOBB(boxData.m_Mins,boxData.m_Maxs,boxData.m_Mat4,matPlayer4,cylinderRadius,cylinderHeight))
  120. return true;
  121. }
  122. return false;
  123. }
  124. private static bool IsPointInAreaPolygon(notnull PlayerRestrictedAreaInstance area, vector point)
  125. {
  126. array<float> translatedDta = new array<float>;
  127. foreach (array<ref array<float>> polygonData : area.PRAPolygons)
  128. {
  129. translatedDta.Clear();
  130. foreach (array<float> vertexPos : polygonData)
  131. {
  132. translatedDta.Insert(vertexPos[0]);
  133. translatedDta.Insert(vertexPos[1]);
  134. }
  135. if (Math2D.IsPointInPolygon(translatedDta,point[0],point[2]))
  136. return true;
  137. }
  138. return false;
  139. }
  140. //----------------------------------------------------------
  141. //debugs
  142. static private ref array<Shape> m_DbgShapesBoxes;
  143. static private ref array<Shape> m_DbgShapesPolygonLines;
  144. static void DrawBoxesDebug(bool draw)
  145. {
  146. if (!IsInitialized())
  147. return;
  148. if (!m_DbgShapesBoxes)
  149. m_DbgShapesBoxes = {};
  150. if (draw && m_DbgShapesBoxes.Count() == 0)
  151. {
  152. foreach (PlayerRestrictedAreaInstance area : m_Data.m_ValidatedAreas)
  153. {
  154. foreach (PRAShapeBoxData boxData : area.m_PRABoxDataTranslated)
  155. {
  156. Shape shp = Debug.DrawBox(boxData.m_Mins,boxData.m_Maxs);
  157. shp.SetMatrix(boxData.m_Mat4);
  158. m_DbgShapesBoxes.Insert(shp);
  159. }
  160. }
  161. }
  162. else if (!draw && m_DbgShapesBoxes.Count() > 0)
  163. {
  164. foreach (Shape box : m_DbgShapesBoxes)
  165. {
  166. box.Destroy();
  167. }
  168. m_DbgShapesBoxes.Clear();
  169. }
  170. }
  171. static void DrawPolygonLinesDebug(bool draw)
  172. {
  173. if (!IsInitialized())
  174. return;
  175. if (!m_DbgShapesPolygonLines)
  176. m_DbgShapesPolygonLines = {};
  177. if (draw && m_DbgShapesPolygonLines.Count() == 0)
  178. {
  179. array<vector> polygonVectors = {};
  180. foreach (PlayerRestrictedAreaInstance area : m_Data.m_ValidatedAreas)
  181. {
  182. foreach (array<ref array<float>> polygonData : area.PRAPolygons)
  183. {
  184. vector first;
  185. vector current;
  186. vector last;
  187. foreach (array<float> vertexPos : polygonData)
  188. {
  189. polygonVectors.Insert(Vector(vertexPos[0],GetGame().SurfaceY(vertexPos[0],vertexPos[1]) + 2,vertexPos[1]));
  190. }
  191. int count = polygonVectors.Count();
  192. for (int i = 0; i < count; ++i)
  193. {
  194. current = polygonVectors[i];
  195. if (i == 0)
  196. first = polygonVectors[i];
  197. else
  198. Debug.DrawLine(last,current,COLOR_WHITE,ShapeFlags.TRANSP|ShapeFlags.NOZWRITE);
  199. last = current;
  200. }
  201. m_DbgShapesPolygonLines.Insert(Debug.DrawLine(current,first,COLOR_RED,ShapeFlags.TRANSP|ShapeFlags.NOZWRITE));
  202. polygonVectors.Clear();
  203. }
  204. }
  205. }
  206. else if (!draw && m_DbgShapesPolygonLines.Count() > 0)
  207. {
  208. foreach (Shape item : m_DbgShapesPolygonLines)
  209. {
  210. item.Destroy();
  211. }
  212. m_DbgShapesPolygonLines.Clear();
  213. }
  214. }
  215. }