HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /*=========================================================================
  2. [ExTasY] A* Node Pathfinding system
  3. -Started: 2022.09.14
  4. ===========================================================================*/
  5. #include <amxmodx>
  6. #include <amxmisc>
  7. #include <fakemeta>
  8. #include <fakemeta_util>
  9. #include <xs>
  10.  
  11. //Node létrehozásához, debughoz kapcsold be.
  12. #define DEVMODE
  13.  
  14. //Csak akkor vidd feljebb, ha ennél több node is előfordul az egyik pályán.
  15. #define MAX_NODES 256
  16.  
  17. /*===========================================================================/
  18. /--------------------------------Definitions---------------------------------/
  19. /============================================================================*/
  20. new g_dot, g_File[128], g_bhg
  21. new Float:g_iPoints[2][3], g_iNode, g_iActionType
  22. new g_Nodes
  23.  
  24. enum _:Items{
  25. Float:CORNER_0[3],
  26. Float:CORNER_1[3],
  27. Float:CORNER_2[3],
  28. Float:CORNER_3[3],
  29. Float:CORNER_4[3]
  30. }
  31. new Array:g_aNodes[4];
  32.  
  33. enum {
  34. BIT_POINT_SET1,
  35. BIT_POINT_SET2,
  36. BIT_TRACK_EXISTING_POINTS,
  37. BIT_NEW_POINT_SET1,
  38. BIT_NEW_POINT_SET2
  39. }
  40. new g_bits;
  41.  
  42. enum _:Actions{
  43. NORMAL, //Piros
  44. DUCK, //Sárga
  45. JUMP, //Lila
  46. LADDER, //Rózsaszín
  47. SPECIAL //Világoskék
  48. }
  49. new const g_cActionColors[Actions][3] = {
  50. {255, 0, 0},
  51. {235, 239, 0},
  52. {116, 0, 239},
  53. {239, 0, 232},
  54. {0, 239, 217}
  55. }
  56.  
  57. #define SetBit(%0,%1) (%0 |= (1 << %1))
  58. #define ClearBit(%0,%1) (%0 &= ~(1 << %1))
  59. #define GetBit(%0,%1) (%0 & (1 << %1))
  60.  
  61. #define MAIN 0
  62. #define CONNECTED 1
  63. #define ACTION 2
  64. #define MIDPOINT 3
  65.  
  66. #define MAX_CONNECTABLE_NODES 4
  67.  
  68. /*===========================================================================/
  69. /------------------------------Global Functions------------------------------/
  70. /============================================================================*/
  71. public plugin_init(){
  72. register_plugin("[ZM] - Node System", "0.0.1", "DexoN")
  73.  
  74. #if defined DEVMODE
  75. register_clcmd("ActionType", "@ActionType")
  76. register_clcmd("say /nodes", "Menu_Node")
  77. register_concmd("path", "@ManualPath")
  78. set_task(0.7, "review", .flags = "b")
  79. #endif
  80. }
  81.  
  82. public plugin_cfg(){
  83. g_Nodes = 0
  84.  
  85. get_configsdir(g_File, charsmax(g_File))
  86. formatex(g_File, charsmax(g_File), "%s/NodeSystem", g_File)
  87.  
  88. if(!dir_exists(g_File))
  89. mkdir(g_File)
  90.  
  91. new sMap[32]; get_mapname(sMap, charsmax(sMap))
  92.  
  93. formatex(g_File, charsmax(g_File), "%s/%s.cfg", g_File, sMap)
  94.  
  95. new f = fopen(g_File, "r")
  96. if(!f){
  97. log_amx("Nem található node fájl ezen a pályán.")
  98. return;
  99. }
  100.  
  101. new Line[128], szO[7][8]
  102.  
  103. while(!feof(f)){
  104. fgets(f, Line, charsmax(Line))
  105.  
  106. if(strlen(Line) < 2)
  107. break;
  108.  
  109. parse(Line, szO[0], 7, szO[1], 7, szO[2], 7, szO[3], 7, szO[4], 7, szO[5], 7, szO[6], 7)
  110.  
  111. for(new i; i < 3; i++) g_iPoints[0][i] = str_to_float(szO[i])
  112. for(new i; i < 3; i++) g_iPoints[1][i] = str_to_float(szO[i+3])
  113. g_iActionType = str_to_num(szO[6])
  114.  
  115. InsertNode(g_iNode)
  116. SetNodeAction(g_iNode)
  117. SetNodeMidPoint(g_iNode)
  118. }
  119. fclose(f)
  120.  
  121. log_amx("%d node sikeresen betöltve.", g_Nodes)
  122.  
  123. if(g_Nodes > 1)
  124. CreateNetwork()
  125. }
  126.  
  127. public plugin_precache() {
  128. g_dot = precache_model("sprites/dot.spr");
  129.  
  130. g_aNodes[MAIN] = ArrayCreate(Items)
  131. g_aNodes[CONNECTED] = ArrayCreate(Items)
  132. g_aNodes[ACTION] = ArrayCreate()
  133. g_aNodes[MIDPOINT] = ArrayCreate(3)
  134. }
  135.  
  136. /*===========================================================================/
  137. /---------------------------------Natives------------------------------------/
  138. /============================================================================*/
  139. public plugin_natives() {
  140. register_native("zm_npc_find_path", "_npc_find_path", 1);
  141. register_native("zm_get_user_node", "_get_user_node", 1)
  142. register_native("zm_is_ent_in_node", "_is_ent_in_node", 1)
  143. register_native("zm_get_random_node", "_get_random_node", 1)
  144. register_native("zm_get_node_action", "_get_node_action", 1)
  145. register_native("zm_get_user_closest_node", "_get_user_closest_node", 1)
  146. register_native("zm_get_node_closest_point", "_get_node_closest_point", 1)
  147. }
  148.  
  149. public Array:_npc_find_path(npc, player)
  150. return FindPathToNode(npc, player);
  151.  
  152. public _get_user_node(iId)
  153. return GetNodeByOrigin(iId);
  154.  
  155. public _is_ent_in_node(iEnt, Node){
  156. static Float:fO[3], l_Array[Items]
  157. pev(iEnt, pev_origin, fO)
  158. ArrayGetArray(g_aNodes[MAIN], Node, l_Array)
  159.  
  160. if((IsPosInRectangle(fO, l_Array[CORNER_0], l_Array[CORNER_1]))
  161. ||(IsPosInRectangle(fO, l_Array[CORNER_0], l_Array[CORNER_1]))
  162. ||(IsPosInRectangle(fO, l_Array[CORNER_0], l_Array[CORNER_1]))
  163. ||(IsPosInRectangle(fO, l_Array[CORNER_0], l_Array[CORNER_1]))
  164. ||(IsPosInRectangle(fO, l_Array[CORNER_0], l_Array[CORNER_1]))) return 1
  165.  
  166. return 0
  167. }
  168.  
  169. public _get_random_node(iEnt, Type){
  170. new iNode = GetNodeByOrigin(iEnt)
  171. new rNode
  172. for(new i; i < g_Nodes*MAX_CONNECTABLE_NODES; i++){
  173. rNode = random(g_Nodes)
  174.  
  175. if(rNode == iNode || ArrayGetCell(g_aNodes[ACTION], rNode) != Type)
  176. continue;
  177.  
  178. return rNode;
  179. }
  180. return 0
  181. }
  182.  
  183. public _get_node_action(iNode)
  184. return ArrayGetCell(g_aNodes[ACTION], iNode);
  185.  
  186. public _get_user_closest_node(iEnt){
  187. static Float:fDist, l_Array[Items], Float:Mid[3], Float:fO[3], l_Node;
  188. fDist = 5000.0
  189. pev(iEnt, pev_origin, fO)
  190.  
  191. for(new i; i < g_Nodes; i++){
  192. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  193.  
  194. GetMidpoint(l_Array[CORNER_0], l_Array[CORNER_1], Mid)
  195.  
  196. if(xs_vec_distance(Mid, fO) < fDist){
  197. fDist = xs_vec_distance(Mid, fO)
  198. l_Node = i;
  199. }
  200. }
  201. return l_Node
  202. }
  203.  
  204. public Array:_get_node_closest_point(iEnt, Node){
  205. static Array:aGoodPoint, Float:Point[3], Float:fO[3]
  206. aGoodPoint = ArrayCreate(3)
  207.  
  208. pev(iEnt, pev_origin, fO)
  209.  
  210. GetClosestPointToOrigin(fO, Node, Point)
  211.  
  212. ArrayPushArray(aGoodPoint, Point)
  213.  
  214. return aGoodPoint;
  215. }
  216.  
  217. /*===========================================================================/
  218. /----------------------------------Menus-------------------------------------/
  219. /============================================================================*/
  220. public Menu_Node(iId){
  221. new menu = menu_create(fmt("Node menu^n\yNodes: \r%d db", g_Nodes), "@MenuH_Node")
  222.  
  223. menu_additem(menu, "Node létrehozása")
  224. menu_additem(menu, "Node törlése")
  225. menu_additem(menu, "Node szerkesztése")
  226. menu_additem(menu, fmt("Közeli nodeok mutatása %s", g_bhg ? "\r[\yON\r]" : "\r[\dOFF\r]"))
  227. menu_additem(menu, "Node csatlakozási pontjai")
  228. menu_additem(menu, "Nodeok mentése")
  229.  
  230. menu_display(iId, menu)
  231. }
  232.  
  233. @MenuH_Node(iId, menu, item){
  234. if(item==MENU_EXIT)
  235. return PLUGIN_HANDLED;
  236.  
  237. switch(item){
  238. case 0: Menu_Create_Node(iId)
  239. case 1: Menu_Delete_Node(iId)
  240. case 2: Modify_Node(iId)
  241. case 3: {
  242. g_bhg = g_bhg ? 0 : iId
  243. Menu_Node(iId)
  244. }
  245. case 4: GetNodeNetwork(GetNodeByOrigin(iId))
  246. case 5: SaveNodes()
  247. }
  248.  
  249. return PLUGIN_HANDLED;
  250. }
  251.  
  252. public Menu_Create_Node(iId){
  253. new sLine[128], iLen;
  254. iLen += formatex(sLine[iLen], charsmax(sLine), GetBit(g_bits, BIT_POINT_SET1) ? fmt("^n\yPoint 1 - \r[\w%.2f %.2f %.2f\r]", g_iPoints[0][0], g_iPoints[0][1], g_iPoints[0][2]) : "")
  255. iLen += formatex(sLine[iLen], charsmax(sLine)-iLen, GetBit(g_bits, BIT_POINT_SET2) ? fmt("^n\yPoint 2 - \r[\w%.2f %.2f %.2f\r]", g_iPoints[1][0], g_iPoints[1][1], g_iPoints[1][2]) : "")
  256. iLen += formatex(sLine[iLen], charsmax(sLine)-iLen, g_iNode ? fmt("^n\yNode %d", g_iNode-1) : "")
  257.  
  258. new menu = menu_create(fmt("Node létrehozás menü%s", sLine), "@MenuH_Create_Node")
  259.  
  260. menu_additem(menu, "Pont beállítása.")
  261. menu_additem(menu, "Nézett pont felkapása.")
  262. menu_additem(menu, fmt("%sJelöld meg a nodeomat.", (GetBit(g_bits, BIT_POINT_SET1) && GetBit(g_bits, BIT_POINT_SET2)) ? "\w" : "\d"))
  263. menu_additem(menu, fmt("Cselekvéstípus: \r[\d%d\r]", g_iActionType))
  264. menu_additem(menu, "Node létrehozása.")
  265.  
  266. menu_display(iId, menu)
  267. }
  268.  
  269. @MenuH_Create_Node(iId, menu, item){
  270. menu_destroy(menu)
  271.  
  272. if(item == MENU_EXIT){
  273. return PLUGIN_HANDLED;
  274. }
  275.  
  276. switch(item){
  277. case 0: {
  278. fm_get_aim_origin(iId, (!GetBit(g_bits, BIT_POINT_SET2) || GetBit(g_bits, BIT_NEW_POINT_SET2)) ? g_iPoints[1] : g_iPoints[0])
  279. if(GetBit(g_bits, BIT_POINT_SET1)){
  280. SetBit(g_bits, BIT_POINT_SET2)
  281. }else SetBit(g_bits, BIT_POINT_SET1);
  282. if(GetBit(g_bits, BIT_NEW_POINT_SET1))
  283. ClearBit(g_bits, BIT_NEW_POINT_SET1)
  284. else if(GetBit(g_bits, BIT_NEW_POINT_SET2))
  285. ClearBit(g_bits, BIT_NEW_POINT_SET2);
  286. SetBit(g_bits, BIT_TRACK_EXISTING_POINTS)
  287. if(!task_exists(iId))
  288. set_task(0.1, "ShowBeam", iId, .flags = "b")
  289. }
  290. case 1: PickUpViewingPoint(iId)
  291. case 2: (GetBit(g_bits, BIT_POINT_SET1) && GetBit(g_bits, BIT_POINT_SET2)) ? DrawRectangle(g_iPoints[0], g_iPoints[1], 50, g_cActionColors[g_iActionType][0], g_cActionColors[g_iActionType][1], g_cActionColors[g_iActionType][2]) : client_print_color(0,0, "Nincs 2 pontod.")
  292. case 3: {
  293. client_cmd(iId, "messagemode ActionType")
  294. return PLUGIN_HANDLED;
  295. }
  296. case 4: {
  297. new Float:f[3]; pev(iId, pev_origin, f)
  298. InsertNode(g_iNode)
  299. SetNodeAction(g_iNode)
  300. SetNodeMidPoint(g_iNode)
  301. ClearBits()
  302. CreateNetwork()
  303. Menu_Node(iId)
  304. return PLUGIN_HANDLED;
  305. }
  306. }
  307.  
  308. Menu_Create_Node(iId)
  309.  
  310. return PLUGIN_HANDLED;
  311. }
  312.  
  313. public Menu_Delete_Node(iId){
  314. new iNode, l_Array[Items]
  315. if((iNode = GetNodeByAim(iId)) == -1){
  316. Menu_Node(iId)
  317. return;
  318. }
  319.  
  320. ArrayGetArray(g_aNodes[MAIN], iNode, l_Array)
  321.  
  322. xs_vec_copy(l_Array[CORNER_0], g_iPoints[0])
  323. xs_vec_copy(l_Array[CORNER_1], g_iPoints[1])
  324.  
  325. SetBit(g_bits, BIT_POINT_SET2);
  326. SetBit(g_bits, BIT_POINT_SET1);
  327.  
  328. g_iNode = iNode+1;
  329.  
  330. new sLine[128], iLen;
  331. iLen += formatex(sLine[iLen], charsmax(sLine), GetBit(g_bits, BIT_POINT_SET1) ? fmt("^n\yPoint 1 - \r[\w%.2f %.2f %.2f\r]", g_iPoints[0][0], g_iPoints[0][1], g_iPoints[0][2]) : "")
  332. iLen += formatex(sLine[iLen], charsmax(sLine)-iLen, GetBit(g_bits, BIT_POINT_SET2) ? fmt("^n\yPoint 2 - \r[\w%.2f %.2f %.2f\r]", g_iPoints[1][0], g_iPoints[1][1], g_iPoints[1][2]) : "")
  333. iLen += formatex(sLine[iLen], charsmax(sLine)-iLen, g_iNode ? fmt("^n\yNode %d", g_iNode) : "")
  334.  
  335. new menu = menu_create(fmt("Biztosan törlöd ezt a node-ot?%s", sLine), "@MenuH_Delete_Node")
  336.  
  337. menu_additem(menu, "Igen.")
  338. menu_additem(menu, "Nem.")
  339.  
  340. menu_display(iId, menu)
  341. }
  342.  
  343. @MenuH_Delete_Node(iId, menu, item){
  344. menu_destroy(menu)
  345.  
  346. if(item == MENU_EXIT){
  347. return PLUGIN_HANDLED;
  348. }
  349.  
  350. switch(item){
  351. case 0: {
  352. DeleteNode(g_iNode-1)
  353. ClearBits()
  354. CreateNetwork()
  355. Menu_Node(iId)
  356. }
  357. case 1: {
  358. ClearBits()
  359. Menu_Node(iId)
  360. }
  361. }
  362.  
  363. return PLUGIN_HANDLED;
  364. }
  365.  
  366. /*===========================================================================/
  367. /----------------------------Internal Functions------------------------------/
  368. /============================================================================*/
  369. GetClosestPointToOrigin(Float:fO[3], Node, Float:GoodPoint[3]){
  370. static l_Array[Items], Float:fDiff, Float:Lowest;
  371. ArrayGetArray(g_aNodes[MAIN], Node, l_Array)
  372.  
  373. fDiff = 5000.0
  374.  
  375. Lowest = l_Array[CORNER_0][2] > l_Array[CORNER_1][2] ? l_Array[CORNER_1][2] : l_Array[CORNER_0][2]
  376.  
  377. if(xs_vec_distance(fO, l_Array[CORNER_0]) < fDiff){
  378. fDiff = xs_vec_distance(fO, l_Array[CORNER_0])
  379. xs_vec_copy(l_Array[CORNER_0], GoodPoint)
  380. }
  381. else if(xs_vec_distance(fO, l_Array[CORNER_1]) < fDiff){
  382. fDiff = xs_vec_distance(fO, l_Array[CORNER_1])
  383. xs_vec_copy(l_Array[CORNER_1], GoodPoint)
  384. }
  385. else if(xs_vec_distance(fO, l_Array[CORNER_2]) < fDiff){
  386. fDiff = xs_vec_distance(fO, l_Array[CORNER_2])
  387. xs_vec_copy(l_Array[CORNER_2], GoodPoint)
  388. }
  389. else if(xs_vec_distance(fO, l_Array[CORNER_3]) < fDiff){
  390. fDiff = xs_vec_distance(fO, l_Array[CORNER_3])
  391. xs_vec_copy(l_Array[CORNER_3], GoodPoint)
  392. }
  393. else if(xs_vec_distance(fO, l_Array[CORNER_4]) < fDiff){
  394. fDiff = xs_vec_distance(fO, l_Array[CORNER_4])
  395. xs_vec_copy(l_Array[CORNER_4], GoodPoint)
  396. }
  397.  
  398. GoodPoint[2] = Lowest
  399. }
  400.  
  401. #if defined DEVMODE
  402. public review(){
  403. if(!g_bhg)
  404. return;
  405.  
  406. static node; node = GetNodeByOrigin(g_bhg)
  407. if(node != -1)
  408. GetNodeNetwork(node)
  409. }
  410.  
  411. @ManualPath(iId){
  412. new sString[16]
  413. read_args(sString, charsmax(sString))
  414.  
  415. remove_quotes(sString)
  416.  
  417. new sItems[2][8]
  418. parse(sString, sItems[0], 7, sItems[1], 7)
  419.  
  420. FindPathToNode(str_to_num(sItems[0]), str_to_num(sItems[1]))
  421. }
  422. #endif
  423.  
  424. SaveNodes(){
  425. if(!g_Nodes){
  426. client_print_color(0,0, "Nincs egy darab node sem.")
  427. return;
  428. }
  429.  
  430. HighlightNode(-2)
  431.  
  432. new l_Array[Items], l_Type;
  433. new f = fopen(g_File, "w")
  434. if(f){
  435. for(new i; i < g_Nodes; i++){
  436. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  437. l_Type = ArrayGetCell(g_aNodes[ACTION], i)
  438. fputs(f, fmt("%.2f %.2f %.2f %.2f %.2f %.2f %d^n",\
  439. l_Array[CORNER_0][0], l_Array[CORNER_0][1], l_Array[CORNER_0][2], l_Array[CORNER_1][0], l_Array[CORNER_1][1], l_Array[CORNER_1][2], l_Type))
  440. }
  441. fclose(f)
  442. }
  443. client_print_color(0,0, "^4Koordináták elmentve. ^3:)")
  444. }
  445.  
  446. @ActionType(iId){
  447. new sString[4]
  448. read_args(sString, charsmax(sString))
  449.  
  450. remove_quotes(sString)
  451.  
  452. g_iActionType = str_to_num(sString)
  453. Menu_Create_Node(iId)
  454. }
  455.  
  456. DeleteNode(Node){
  457. ArrayDeleteItem(g_aNodes[MAIN], Node)
  458. ArrayDeleteItem(g_aNodes[CONNECTED], Node)
  459. ArrayDeleteItem(g_aNodes[ACTION], Node)
  460. ArrayDeleteItem(g_aNodes[MIDPOINT], Node)
  461. g_Nodes--
  462. }
  463.  
  464. InsertNode(Node = 0){
  465. new Float:fO[Items]
  466. xs_vec_copy(g_iPoints[0], fO[CORNER_0]);
  467. xs_vec_copy(g_iPoints[1], fO[CORNER_1]);
  468.  
  469. new Float:Lowest = g_iPoints[0][2] < g_iPoints[1][2] ? g_iPoints[0][2] : g_iPoints[1][2]
  470. new Float:fHighest[3]; xs_vec_copy(g_iPoints[0][2] > g_iPoints[1][2] ? g_iPoints[0] : g_iPoints[1], fHighest)
  471. fHighest[2] = Lowest; xs_vec_copy(fHighest, fO[CORNER_4])
  472.  
  473. xs_vec_copy(g_iPoints[0], fO[CORNER_2]); fO[CORNER_2][2] = Lowest; fO[CORNER_2][0] = g_iPoints[1][0];
  474. xs_vec_copy(g_iPoints[1], fO[CORNER_3]); fO[CORNER_3][2] = Lowest; fO[CORNER_3][0] = g_iPoints[0][0];
  475.  
  476. if(!Node){
  477. ArrayPushArray(g_aNodes[MAIN], fO)
  478. g_Nodes++
  479. }
  480. else
  481. ArraySetArray(g_aNodes[MAIN], g_iNode-1, fO)
  482. }
  483.  
  484. SetNodeAction(Node = 0){
  485. if(!Node)
  486. ArrayPushCell(g_aNodes[ACTION], g_iActionType)
  487. else
  488. ArraySetCell(g_aNodes[ACTION], g_iNode-1, g_iActionType)
  489. }
  490.  
  491. SetNodeMidPoint(Node = 0){
  492. new Float:Mid[3]
  493. GetMidpoint(g_iPoints[0], g_iPoints[1], Mid)
  494. if(!Node)
  495. ArrayPushArray(g_aNodes[MIDPOINT], Mid)
  496. else
  497. ArraySetArray(g_aNodes[MIDPOINT], g_iNode-1, Mid)
  498. }
  499.  
  500. CreateNetwork(){
  501. new l_Array[Items], l_Array2[Items], l_Array3[MAX_CONNECTABLE_NODES]
  502. new aSize = g_Nodes
  503. client_print_color(0,0, "^3Node létrehozva: ^4#^1%d", g_Nodes)
  504. if(aSize == 1 || !aSize){
  505. client_print_color(0,0, "return")
  506. return;
  507. }
  508.  
  509. ArrayClear(g_aNodes[CONNECTED]);
  510.  
  511. new count
  512. for(new i; i < aSize; i++){
  513. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  514.  
  515. arrayset(l_Array3, -1, MAX_CONNECTABLE_NODES)
  516. count = 0
  517.  
  518. for(new j; j < aSize; j++){
  519. if(i==j)
  520. continue;
  521.  
  522. if(count == MAX_CONNECTABLE_NODES)
  523. break;
  524.  
  525. ArrayGetArray(g_aNodes[MAIN], j, l_Array2)
  526.  
  527. if((IsPosInRectangle(l_Array2[CORNER_0], l_Array[CORNER_0], l_Array[CORNER_1]))
  528. ||(IsPosInRectangle(l_Array2[CORNER_1], l_Array[CORNER_0], l_Array[CORNER_1]))
  529. ||(IsPosInRectangle(l_Array2[CORNER_2], l_Array[CORNER_0], l_Array[CORNER_1]))
  530. ||(IsPosInRectangle(l_Array2[CORNER_3], l_Array[CORNER_0], l_Array[CORNER_1]))
  531. ||(IsPosInRectangle(l_Array2[CORNER_4], l_Array[CORNER_0], l_Array[CORNER_1]))) l_Array3[++count-1] = j
  532.  
  533. else if((IsPosInRectangle(l_Array[CORNER_0], l_Array2[CORNER_0], l_Array2[CORNER_1]))
  534. ||(IsPosInRectangle(l_Array[CORNER_1], l_Array2[CORNER_0], l_Array2[CORNER_1]))
  535. ||(IsPosInRectangle(l_Array[CORNER_2], l_Array2[CORNER_0], l_Array2[CORNER_1]))
  536. ||(IsPosInRectangle(l_Array[CORNER_3], l_Array2[CORNER_0], l_Array2[CORNER_1]))
  537. ||(IsPosInRectangle(l_Array[CORNER_4], l_Array2[CORNER_0], l_Array2[CORNER_1]))) l_Array3[++count-1] = j
  538. }
  539.  
  540. ArrayPushArray(g_aNodes[CONNECTED], l_Array3)
  541. }
  542. }
  543.  
  544. GetNodeNetwork(Node){
  545. static l_Array[MAX_CONNECTABLE_NODES], l_Array2[Items]
  546.  
  547. ArrayGetArray(g_aNodes[CONNECTED], Node, l_Array)
  548.  
  549. for(new i; i < MAX_CONNECTABLE_NODES; i++){
  550. if(l_Array[i] == -1){
  551. continue;
  552. }
  553. ArrayGetArray(g_aNodes[MAIN], l_Array[i], l_Array2)
  554. HighlightNode(l_Array[i])
  555. }
  556.  
  557. #if defined DEVMODE
  558. client_print_color(0,0, "Node: %d | Connected: %d, %d, %d, %d", Node, l_Array[0], l_Array[1], l_Array[2], l_Array[3])
  559. #endif
  560. }
  561.  
  562. Array:FindPathToNode(From, To){
  563. static Array:Path; Path = ArrayCreate()
  564. if(From < 0 || To < 0){
  565. log_to_file("Bad_Path.log", "A plugin nem tudott útvonalat találni 2 node között mert az egyik nem létezik. (#id < 0)")
  566. return Path
  567. }
  568.  
  569. #if defined DEVMODE
  570. static Float:time; time = get_gametime()
  571. #endif
  572.  
  573. static l_OpenList[MAX_NODES], l_OpenList_Count, i
  574. static l_CloseList[MAX_NODES], l_CloseList_Count
  575. static l_ListFather[MAX_NODES], Float:l_ListG[MAX_NODES], Float:l_ListF[MAX_NODES]
  576.  
  577. l_OpenList_Count = 0
  578. l_CloseList_Count = 0
  579.  
  580. for(i = 0; i < MAX_NODES; i++){
  581. l_ListFather[i] = -1
  582. l_ListF[i] = 0.0
  583. l_ListG[i] = 0.0
  584. l_OpenList[i] = 0
  585. l_CloseList[i] = 0
  586. }
  587.  
  588. ASTAR_Add_To_List(From, l_OpenList, l_OpenList_Count)
  589.  
  590. static Found, CurrentNode, Temp; Found = 1, CurrentNode = From, Temp = 0
  591.  
  592. while(CurrentNode != To){
  593. ASTAR_Add_To_List(CurrentNode, l_CloseList, l_CloseList_Count)
  594.  
  595. ASTAR_Remove_OpenList(CurrentNode, l_OpenList, l_OpenList_Count)
  596.  
  597. ASTAR_HandleCost(CurrentNode, To, l_OpenList, l_OpenList_Count, l_CloseList, l_CloseList_Count, l_ListFather, l_ListG, l_ListF)
  598.  
  599. if((Temp = ASTAR_Get_Less_F(To, l_OpenList, l_OpenList_Count, l_ListF)) == -1){
  600. Found = 0
  601. break;
  602. } else CurrentNode = Temp
  603. }
  604.  
  605. if(!Found){
  606. log_to_file("Bad_Path.log", "A plugin nem tudott találni útvonalat #%d és #%d node közt.", From, To)
  607. return Path
  608. }
  609.  
  610. ASTAR_ReversePath(CurrentNode, l_ListFather, From, Path)
  611.  
  612. #if defined DEVMODE
  613. client_print_color(0,0, "^1[^4ASTAR^1] ^1Útvonal megtervezve. ^4| ^1Időtartam: ^3%f", time-get_gametime())
  614. #endif
  615.  
  616. new Bad
  617. return FindBestWays(Path, Bad)
  618. }
  619.  
  620. ASTAR_ReversePath(CurrentNode, l_ListFather[], From, Array:Path){
  621. static N; N = CurrentNode
  622. static Temp_Result_Count; Temp_Result_Count = 0
  623.  
  624. static Reverse[MAX_NODES], Result[MAX_NODES], Result_Count
  625.  
  626. while(l_ListFather[N] != -1)
  627. {
  628. Reverse[Temp_Result_Count++] = N
  629. N = l_ListFather[N]
  630. }
  631. Reverse[Temp_Result_Count++] = From
  632.  
  633. for(new i = Temp_Result_Count-1; i > -1; i--)
  634. {
  635. Result[++Result_Count-1] = Reverse[i]
  636. ArrayPushCell(Path, Result[Result_Count-1])
  637. }
  638.  
  639. Result_Count = Temp_Result_Count
  640. }
  641.  
  642. ASTAR_Add_To_List(CurrentNode, l_List[], &l_List_Count)
  643. l_List[l_List_Count++] = CurrentNode;
  644.  
  645. ASTAR_Is_In_List(Node, l_List[], &l_List_Count){
  646. for(new i; i < l_List_Count; i++)
  647. if(Node == l_List[i])
  648. return 1
  649.  
  650. return 0
  651. }
  652.  
  653. ASTAR_Remove_OpenList(Node, l_OpenList[], &l_OpenList_Count){
  654. if(!l_OpenList_Count) return -1
  655.  
  656. static i, x
  657. for(i = 0; i < l_OpenList_Count; i++)
  658. {
  659. if(Node == l_OpenList[i])
  660. {
  661. if(i < (--l_OpenList_Count))
  662. for(x = i; x < l_OpenList_Count; x++)
  663. l_OpenList[x] = l_OpenList[x+1]
  664. break
  665. }
  666. }
  667.  
  668. return i
  669. }
  670.  
  671. Float:Get_NodeDistance(NodeA, NodeB){
  672. new Float:mid1[3], Float:mid2[3]
  673.  
  674. ArrayGetArray(g_aNodes[MIDPOINT], NodeA, mid1)
  675. ArrayGetArray(g_aNodes[MIDPOINT], NodeB, mid2)
  676.  
  677. return xs_vec_distance(mid1, mid2)
  678. }
  679.  
  680. ASTAR_Get_Less_F(Node, l_OpenList[], l_OpenList_Count, Float:l_ListF[]){
  681. if(!l_OpenList_Count)
  682. return -1
  683.  
  684. static min_n, Float:min_f
  685. min_n = l_OpenList[0], min_f = l_ListF[l_OpenList[0]]
  686.  
  687. for(new i = 0; i < l_OpenList_Count; i++)
  688. {
  689. if(l_OpenList[i] == Node)
  690. return l_OpenList[i]
  691.  
  692. if(min_f > l_ListF[l_OpenList[i]])
  693. {
  694. min_n = l_OpenList[i]
  695. min_f = l_ListF[l_OpenList[i]]
  696. }
  697. }
  698.  
  699. return min_n
  700. }
  701.  
  702. ASTAR_HandleCost(NodeA, NodeB, l_OpenList[], &l_OpenList_Count, l_CloseList[], &l_CloseList_Count, l_ListFather[], Float:l_ListG[], Float:l_ListF[]){
  703. static aNodes[MAX_CONNECTABLE_NODES]
  704. ArrayGetArray(g_aNodes[CONNECTED], NodeA, aNodes);
  705. for(new i = 0, neighboor; i < MAX_CONNECTABLE_NODES; i++)
  706. {
  707. if(aNodes[i] == -1)
  708. continue
  709.  
  710. neighboor = aNodes[i]
  711.  
  712. if(ASTAR_Is_In_List(neighboor, l_CloseList, l_CloseList_Count)) continue
  713. else {
  714. if(!ASTAR_Is_In_List(neighboor, l_OpenList, l_OpenList_Count))
  715. {
  716. l_ListFather[neighboor] = NodeA
  717. l_ListG[neighboor] = l_ListG[NodeA] + Get_NodeDistance(NodeA, neighboor);
  718.  
  719. ASTAR_Set_F(neighboor, Get_NodeDistance(neighboor, NodeB), l_ListF, l_ListG)
  720.  
  721. l_OpenList[l_OpenList_Count++] = neighboor
  722. } else {
  723. if(l_ListG[neighboor] < l_ListG[NodeA])
  724. {
  725. l_ListFather[neighboor] = NodeA
  726. l_ListG[neighboor] = l_ListG[NodeA] + Get_NodeDistance(NodeA, neighboor)
  727.  
  728. l_OpenList[l_OpenList_Count++] = neighboor
  729. } else continue
  730. }
  731. }
  732. }
  733. }
  734.  
  735. ASTAR_Set_F(Node, Float:H, Float:l_ListF[], Float:l_ListG[])
  736. l_ListF[Node] = l_ListG[Node] + H;
  737.  
  738. Array:FindBestWays(Array:TempArray, &Bad){
  739. static aSize, Float:Points[3], l_Array[Items], l_Array2[Items], i, Array:Way
  740. aSize = ArraySize(TempArray)
  741.  
  742. Way = ArrayCreate(4)
  743.  
  744. static Float:lowest1, Float:lowest2, Float:l_All[4], rip
  745.  
  746. for(i = 0; i < aSize-1; i++){
  747. ArrayGetArray(g_aNodes[MAIN], ArrayGetCell(TempArray, i), l_Array)
  748. ArrayGetArray(g_aNodes[MAIN], ArrayGetCell(TempArray, i+1), l_Array2)
  749.  
  750. rip = 0
  751. lowest2 = l_Array2[CORNER_0][2] > l_Array2[CORNER_1][2] ? l_Array2[CORNER_1][2] : l_Array2[CORNER_0][2]
  752. lowest1 = l_Array[CORNER_0][2] > l_Array[CORNER_1][2] ? l_Array[CORNER_1][2] : l_Array[CORNER_0][2]
  753.  
  754. if(IsPosInRectangle(l_Array2[CORNER_0], l_Array[CORNER_0], l_Array[CORNER_1])) {
  755. xs_vec_copy(l_Array2[CORNER_0], Points); Points[2] = lowest2
  756. }
  757. else if(IsPosInRectangle(l_Array2[CORNER_1], l_Array[CORNER_0], l_Array[CORNER_1])){
  758. xs_vec_copy(l_Array2[CORNER_1], Points); Points[2] = lowest2
  759. }
  760. else if(IsPosInRectangle(l_Array2[CORNER_2], l_Array[CORNER_0], l_Array[CORNER_1])){
  761. xs_vec_copy(l_Array2[CORNER_2], Points); Points[2] = lowest2
  762. }
  763. else if(IsPosInRectangle(l_Array2[CORNER_3], l_Array[CORNER_0], l_Array[CORNER_1])){
  764. xs_vec_copy(l_Array2[CORNER_3], Points); Points[2] = lowest2
  765. }
  766. else if(IsPosInRectangle(l_Array2[CORNER_4], l_Array[CORNER_0], l_Array[CORNER_1])){
  767. xs_vec_copy(l_Array2[CORNER_4], Points); Points[2] = lowest2
  768. }
  769. else if(IsPosInRectangle(l_Array[CORNER_0], l_Array2[CORNER_0], l_Array2[CORNER_1])){
  770. xs_vec_copy(l_Array[CORNER_0], Points); Points[2] = lowest1
  771. }
  772. else if(IsPosInRectangle(l_Array[CORNER_1], l_Array2[CORNER_0], l_Array2[CORNER_1])){
  773. xs_vec_copy(l_Array[CORNER_1], Points); Points[2] = lowest1
  774. }
  775. else if(IsPosInRectangle(l_Array[CORNER_2], l_Array2[CORNER_0], l_Array2[CORNER_1])){
  776. xs_vec_copy(l_Array[CORNER_2], Points); Points[2] = lowest1
  777. }
  778. else if(IsPosInRectangle(l_Array[CORNER_3], l_Array2[CORNER_0], l_Array2[CORNER_1])){
  779. xs_vec_copy(l_Array[CORNER_3], Points); Points[2] = lowest1
  780. }
  781. else if(IsPosInRectangle(l_Array[CORNER_4], l_Array2[CORNER_0], l_Array2[CORNER_1])){
  782. xs_vec_copy(l_Array[CORNER_4], Points); Points[2] = lowest1
  783. }
  784. else rip = ArrayGetCell(TempArray, i)
  785.  
  786. if(rip){
  787. Bad = rip
  788. break;
  789. }
  790.  
  791. #if defined DEVMODE
  792. log_amx("what: %d | rip: %d | p0: %.2f | p1: %.2f | p2: %.2f", ArrayGetCell(TempArray, i), rip, Points[0], Points[1], Points[2])
  793. #endif
  794.  
  795. xs_vec_copy(Points, l_All)
  796. l_All[3] = float(ArrayGetCell(g_aNodes[ACTION], ArrayGetCell(TempArray, i)))
  797. ArrayPushArray(Way, l_All)
  798. }
  799.  
  800. #if defined DEVMODE
  801. static Float:Points2[3]
  802. for(i = 0; i < ArraySize(Way)-1; i++){
  803. ArrayGetArray(Way, i, Points)
  804. xs_vec_copy(Points, Points2); Points2[2] += 50.0
  805. exbeam(Points, Points2, 0, 0, 255)
  806.  
  807. ArrayGetArray(Way, i+1, Points2)
  808. exbeam(Points, Points2, 0, 255, 0)
  809.  
  810. xs_vec_copy(Points2, Points); Points[2] += 50.0
  811. exbeam(Points2, Points, 0, 0, 255)
  812. }
  813. #endif
  814.  
  815. return Way
  816. }
  817.  
  818. IsPosInRectangle(Float:Origin[3], Float:pt1[3], Float:pt2[3]){
  819. new Float:Lowest[3], Float:Highest[3]
  820. for(new i; i < 3; i++){
  821. Lowest[i] = pt1[i] < pt2[i] ? pt1[i] : pt2[i]
  822. Highest[i] = pt1[i] < pt2[i] ? pt2[i] : pt1[i]
  823. }
  824. remove_places(Lowest); remove_places(Highest); remove_places(Origin)
  825.  
  826. return Origin[0] >= Lowest[0] && Origin[0] <= Highest[0] && Origin[1] >= Lowest[1] && Origin[1] <= Highest[1] && Origin[2] >= Lowest[2] && Origin[2] <= Highest[2]
  827. }
  828.  
  829. HighlightNode(Node, life = 7){
  830. new l_Array[Items], l_Type
  831. switch(Node){
  832. case -1: return;
  833. case -2: {
  834. for(new i; i < ArraySize(g_aNodes[MAIN]); i++){
  835. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  836. l_Type = ArrayGetCell(g_aNodes[ACTION], i)
  837.  
  838. DrawRectangle(l_Array[CORNER_0], l_Array[CORNER_1], life, g_cActionColors[l_Type][0], g_cActionColors[l_Type][1], g_cActionColors[l_Type][2])
  839. }
  840. }
  841. default:{
  842. ArrayGetArray(g_aNodes[MAIN], Node, l_Array)
  843. l_Type = ArrayGetCell(g_aNodes[ACTION], Node)
  844.  
  845. DrawRectangle(l_Array[CORNER_0], l_Array[CORNER_1], life, g_cActionColors[l_Type][0], g_cActionColors[l_Type][1], g_cActionColors[l_Type][2])
  846. }
  847. }
  848. }
  849.  
  850. ClearBits(){
  851. ClearBit(g_bits, BIT_TRACK_EXISTING_POINTS); ClearBit(g_bits, BIT_NEW_POINT_SET1); ClearBit(g_bits, BIT_NEW_POINT_SET2);
  852. ClearBit(g_bits, BIT_POINT_SET1); ClearBit(g_bits, BIT_POINT_SET2)
  853. g_iNode = 0;
  854. g_iActionType = 0;
  855. }
  856.  
  857. public ShowBeam(iId){
  858. if(!GetBit(g_bits, BIT_TRACK_EXISTING_POINTS)){
  859. remove_task(iId)
  860. return;
  861. }
  862.  
  863. new inp;
  864. if((inp = GetNewPoint()) != -1){
  865. new Float:aim[3]; fm_get_aim_origin(iId, aim)
  866. exbeam(g_iPoints[inp], aim, 0, 255, 0, 1)
  867. exbeam(g_iPoints[!inp ? 1 : 0], aim, 0, 0, 255, 1)
  868. DrawRectangle(g_iPoints[!inp ? 1 : 0], aim, 1, g_cActionColors[g_iActionType][0], g_cActionColors[g_iActionType][1], g_cActionColors[g_iActionType][2])
  869. return;
  870. }
  871.  
  872. if(!g_iPoints[1]){
  873. new Float:o[3]; pev(iId, pev_origin, o)
  874. exbeam(g_iPoints[0], o, 0, 0, 255, 1)
  875. } else exbeam(g_iPoints[0], g_iPoints[1], 0, 0, 255, 1)
  876. }
  877.  
  878. GetNodeByOrigin(iId){
  879. if(g_Nodes != 0){
  880. new Float:aim[3]
  881. pev(iId, pev_origin, aim)
  882. new l_Array[Items]
  883. for(new i; i < g_Nodes; i++){
  884. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  885.  
  886. if(IsPosInRectangle(aim, l_Array[CORNER_0], l_Array[CORNER_1])){
  887. #if defined DEVMODE
  888. HighlightNode(i)
  889. #endif
  890. return i;
  891. }
  892. }
  893. }
  894. return -1
  895. }
  896.  
  897. GetNodeByAim(iId){
  898. new Float:aim[3]; fm_get_aim_origin(iId, aim)
  899. new l_Array[Items]
  900. for(new i; i < g_Nodes; i++){
  901. ArrayGetArray(g_aNodes[MAIN], i, l_Array)
  902.  
  903. if(IsPosInRectangle(aim, l_Array[CORNER_0], l_Array[CORNER_1])){
  904. HighlightNode(i)
  905. return i;
  906. }
  907. }
  908. return -1
  909. }
  910.  
  911. Modify_Node(iId){
  912. new iNode, l_Array[Items]
  913. if((iNode = GetNodeByAim(iId)) == -1){
  914. Menu_Node(iId)
  915. return;
  916. }
  917.  
  918. ArrayGetArray(g_aNodes[MAIN], iNode, l_Array)
  919.  
  920. g_iActionType = ArrayGetCell(g_aNodes[ACTION], iNode)
  921.  
  922. xs_vec_copy(l_Array[CORNER_0], g_iPoints[0])
  923. xs_vec_copy(l_Array[CORNER_1], g_iPoints[1])
  924.  
  925. SetBit(g_bits, BIT_POINT_SET2);
  926. SetBit(g_bits, BIT_POINT_SET1);
  927.  
  928. g_iNode = iNode+1
  929.  
  930. Menu_Create_Node(iId)
  931. }
  932.  
  933. GetNewPoint(){
  934. if(GetBit(g_bits, BIT_NEW_POINT_SET1))
  935. return 0
  936. else if(GetBit(g_bits, BIT_NEW_POINT_SET2))
  937. return 1
  938. return -1
  939. }
  940.  
  941. PickUpViewingPoint(iId){
  942. new Float:aim[3]; fm_get_aim_origin(iId, aim)
  943. new Float:nPoints[Items], item = -1
  944.  
  945. CheckEquality(g_iPoints[0], g_iPoints[1], aim, 100.0, item)
  946.  
  947. if(item != -1){
  948. SetBit(g_bits, BIT_TRACK_EXISTING_POINTS)
  949.  
  950. if(nPoints[item])
  951. xs_vec_copy(nPoints[item], g_iPoints[item])
  952.  
  953. if(!item)
  954. SetBit(g_bits, BIT_NEW_POINT_SET1)
  955. else
  956. SetBit(g_bits, BIT_NEW_POINT_SET2)
  957. if(!task_exists(iId))
  958. set_task(0.1, "ShowBeam", iId, .flags = "b")
  959.  
  960. Menu_Create_Node(iId)
  961. }
  962.  
  963. return PLUGIN_HANDLED;
  964. }
  965.  
  966. CheckEquality(Float:p1v1[3], Float:p1v2[3], Float:p2[3], Float:fDiff, &item){
  967. if(xs_vec_unique_equal(p1v1, p2, fDiff)){
  968. item = 0;
  969. }
  970.  
  971. if(xs_vec_unique_equal(p1v2, p2, fDiff)){
  972. item = 1
  973. if(!item){
  974. if(xs_vec_distance(p1v1, p2) < xs_vec_distance(p1v2, p2))
  975. item = 0
  976. else
  977. item = 1
  978. }
  979. }
  980. if(item != -1) xs_vec_copy(!item ? p1v1 : p1v2, g_iPoints[item])
  981. }
  982.  
  983. GetMidpoint(Float:fOrigin[3], Float:fOrigin2[3], Float:fOutPut[3]){
  984. for(new i; i < 3; i++) fOutPut[i] = (fOrigin[i] + fOrigin2[i]) / 2.0
  985. }
  986.  
  987. DrawRectangle(Float:Origin[3], Float:Origin2[3], life = 101, r = 255, g = 0, b = 0){
  988. new Float:Highest, Float:Lowest
  989. Highest = Origin[2] < Origin2[2] ? Origin2[2] : Origin[2]
  990. Lowest = Origin[2] < Origin2[2] ? Origin[2] : Origin2[2]
  991.  
  992. new Float:p1[3]; xs_vec_copy(Origin, p1); new Float:p2[3]; xs_vec_copy(Origin2, p2)
  993.  
  994. new Float:vertex[4][3];
  995.  
  996. #define A 0
  997. #define B 1
  998. #define C 2
  999. #define D 3
  1000.  
  1001. p1[2] = Lowest; p2[2] = Lowest;
  1002.  
  1003. xs_vec_copy(p1, vertex[A])
  1004. xs_vec_copy(p2, vertex[C])
  1005. p2[0] = p1[0]; xs_vec_copy(p2, vertex[B])
  1006. p1[0] = Origin2[0]; xs_vec_copy(p1, vertex[D])
  1007.  
  1008. exbeam(vertex[A], vertex[D], r, g, b, life)
  1009. exbeam(vertex[A], vertex[B], r, g, b, life)
  1010. exbeam(vertex[C], vertex[B], r, g, b, life)
  1011. exbeam(vertex[C], vertex[D], r, g, b, life)
  1012.  
  1013. new Float:vertexup[4][3];
  1014.  
  1015. for(new i; i < 4; i++){
  1016. xs_vec_copy(vertex[i], vertexup[i])
  1017. vertexup[i][2] = Highest;
  1018. exbeam(vertex[i], vertexup[i], r, g, b, life)
  1019. }
  1020.  
  1021. xs_vec_copy(Origin, p1); xs_vec_copy(Origin2, p2)
  1022.  
  1023. p1[2] = Highest; p2[2] = Highest;
  1024.  
  1025. xs_vec_copy(p1, vertex[A])
  1026. xs_vec_copy(p2, vertex[C])
  1027. p2[0] = p1[0]; xs_vec_copy(p2, vertex[B])
  1028. p1[0] = Origin2[0]; xs_vec_copy(p1, vertex[D])
  1029.  
  1030. exbeam(vertex[A], vertex[D], r, g, b, life)
  1031. exbeam(vertex[A], vertex[B], r, g, b, life)
  1032. exbeam(vertex[C], vertex[B], r, g, b, life)
  1033. exbeam(vertex[C], vertex[D], r, g, b, life)
  1034. }
  1035.  
  1036. xs_vec_unique_equal(Float:vec1[3], Float:vec2[3], Float:Diff){
  1037. if(xs_vec_distance(vec1, vec2) <= Diff){
  1038. return 1
  1039. }
  1040. return 0;
  1041. }
  1042.  
  1043. exbeam(Float:iorigin[3], Float:forigin[3], r, g, b, life = 202){
  1044. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  1045. write_byte(TE_BEAMPOINTS)
  1046. for(new k; k < 3; k++) write_coord_f(iorigin[k])
  1047. for(new k; k < 3; k++) write_coord_f(forigin[k])
  1048. write_short(g_dot)
  1049. write_byte(0); write_byte(1); write_byte(life); write_byte(5); write_byte(0)
  1050. write_byte(r); write_byte(g); write_byte(b); write_byte(200); write_byte(0)
  1051. message_end()
  1052. }
  1053.  
  1054. remove_places(Float:vec[3]){
  1055. vec[0] = float(floatround(vec[0]))
  1056. vec[1] = float(floatround(vec[1]))
  1057. vec[2] = float(floatround(vec[2]))
  1058. }