HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. #include <amxmodx>
  2. #include <amxmisc>
  3. #include <fakemeta>
  4. #include <fakemeta_util>
  5.  
  6. #define ADMIN_LADDER ADMIN_MENU
  7.  
  8. #define USE_TASK
  9. #define LADDER_DELAY 0.2
  10.  
  11. enum (+= 1000)
  12. {
  13. TASK_ID_MOVE = 1000,
  14. TASK_ID_CHECK
  15. };
  16.  
  17. enum _:Angles
  18. {
  19. ANGLE_VERT1,
  20. ANGLE_VERT2,
  21. ANGLE_HORIZ
  22. };
  23.  
  24. new const LADDER_CLASS[] = "fake_ladder";
  25. new const LADDER_MODEL[] = "models/ladder.mdl";
  26.  
  27. #define IsFakeLadder(%1) fm_is_ent_classname(%1, LADDER_CLASS)
  28.  
  29. new const Float:LADDER_MINS[Angles][3] =
  30. {
  31. { -4.0, -32.0, -32.0},
  32. {-32.0, -4.0, -32.0},
  33. {-32.0, -32.0, -4.0}
  34. };
  35.  
  36. new const Float:LADDER_MAXS[Angles][3] =
  37. {
  38. { 4.0, 32.0, 32.0},
  39. { 32.0, 4.0, 32.0},
  40. { 32.0, 32.0, 4.0}
  41. };
  42.  
  43. new const Float:LADDER_ANGLES[Angles][3] =
  44. {
  45. { 90.0, 0.0, 0.0},
  46. { 90.0, 0.0, 90.0},
  47. { 0.0, 0.0, 0.0}
  48. };
  49.  
  50. new g_ladder_file[64];
  51.  
  52. new bool:g_snapping[33];
  53. new Float:g_move_dist[33];
  54. new Float:g_move_offset[33][3];
  55.  
  56. new g_ladder_ent[33];
  57.  
  58. new info_target;
  59.  
  60. public plugin_precache()
  61. {
  62. precache_model(LADDER_MODEL);
  63. }
  64.  
  65. public plugin_init()
  66. {
  67. register_plugin("Ladder Maker", "0.1", "Exolent");
  68.  
  69. register_clcmd("say /ladder", "CmdLadder");
  70.  
  71. register_clcmd("+move_ladder", "CmdStartMove");
  72. register_clcmd("-move_ladder", "CmdStopMove");
  73.  
  74. register_forward(FM_Touch, "FwdTouch");
  75. register_forward(FM_PlayerPreThink, "FwdPlayerPreThink");
  76.  
  77. info_target = engfunc(EngFunc_AllocString, "info_target");
  78.  
  79. get_datadir(g_ladder_file, sizeof(g_ladder_file) - 1);
  80. add(g_ladder_file, sizeof(g_ladder_file) - 1, "/laddermaker");
  81.  
  82. if( !dir_exists(g_ladder_file) )
  83. {
  84. mkdir(g_ladder_file);
  85. }
  86.  
  87. new mapname[64];
  88. get_mapname(mapname, sizeof(mapname) - 1);
  89. strtolower(mapname);
  90.  
  91. format(g_ladder_file, sizeof(g_ladder_file) - 1, "%s/%s.txt", g_ladder_file, mapname);
  92.  
  93. Load(false);
  94. }
  95.  
  96. public client_connect(client)
  97. {
  98. g_snapping[client] = true;
  99. }
  100.  
  101. public client_disconnect(client)
  102. {
  103. remove_task(client + TASK_ID_MOVE);
  104. }
  105.  
  106. public CmdLadder(client)
  107. {
  108. ShowLadderMenu(client);
  109.  
  110. return PLUGIN_HANDLED;
  111. }
  112.  
  113. public CmdStartMove(client)
  114. {
  115. if( !access(client, ADMIN_LADDER) ) return PLUGIN_HANDLED;
  116.  
  117. new taskid = client + TASK_ID_MOVE;
  118. if( task_exists(taskid) ) return PLUGIN_HANDLED;
  119.  
  120. new ent, body;
  121. g_move_dist[client] = get_user_aiming(client, ent, body);
  122.  
  123. if( IsFakeLadder(ent) )
  124. {
  125. new Float:aim_origin[3];
  126. fm_get_aim_origin(client, aim_origin);
  127.  
  128. pev(ent, pev_origin, g_move_offset[client]);
  129.  
  130. xs_vec_sub(g_move_offset[client], aim_origin, g_move_offset[client]);
  131.  
  132. new params[2];
  133. params[0] = ent;
  134. set_task(0.1, "TaskMoveLadder", taskid, params, 2, "b");
  135. }
  136.  
  137. return PLUGIN_HANDLED;
  138. }
  139.  
  140. public CmdStopMove(client)
  141. {
  142. if( !access(client, ADMIN_LADDER) ) return PLUGIN_HANDLED;
  143.  
  144. remove_task(client + TASK_ID_MOVE);
  145.  
  146. return PLUGIN_HANDLED;
  147. }
  148.  
  149. public FwdTouch(ent, client)
  150. {
  151. if( !IsFakeLadder(ent)
  152. || !is_user_alive(client) ) return;
  153.  
  154. g_ladder_ent[client] = ent;
  155.  
  156. #if defined USE_TASK
  157. remove_task(client + TASK_ID_CHECK);
  158. set_task(LADDER_DELAY, "TaskRemoveLadder", client + TASK_ID_CHECK);
  159. #endif
  160. }
  161.  
  162. public FwdPlayerPreThink(client)
  163. {
  164. if( !pev_valid(g_ladder_ent[client]) ) return;
  165.  
  166. set_pev(client, pev_movetype, MOVETYPE_FLY);
  167.  
  168. static Float:maxspeed;
  169. pev(client, pev_maxspeed, maxspeed);
  170.  
  171. if( pev(client, pev_flags) & FL_DUCKING )
  172. {
  173. // I don't know the real calculation for ducking velocity
  174. // but this will have to do for now
  175. maxspeed /= 2.0;
  176. }
  177.  
  178. static Float:aim_velocity[3];
  179. velocity_by_aim(client, floatround(maxspeed), aim_velocity);
  180.  
  181. static Float:client_origin[3], Float:stop[3];
  182. pev(client, pev_origin, client_origin);
  183.  
  184. // find the side the ladder is in relation to the client
  185. // and remove the velocity in the direction away/towards the ladder
  186. static side;
  187. for( new i = 0; i < 6; i++ )
  188. {
  189. side = i / 2;
  190.  
  191. stop[0] = client_origin[0];
  192. stop[1] = client_origin[1];
  193. stop[2] = client_origin[2];
  194.  
  195. stop[side] += (i % 2 == 0) ? 50.0 : -50.0;
  196.  
  197. engfunc(EngFunc_TraceLine, client_origin, stop, 0, client, 0);
  198.  
  199. if( get_tr2(0, TR_pHit) == g_ladder_ent[client] )
  200. {
  201. aim_velocity[side] = 0.0;
  202.  
  203. side = i;
  204. break;
  205. }
  206. }
  207.  
  208. if( (side / 2) == 2 )
  209. {
  210. new Float:aim_origin[3];
  211. fm_get_aim_origin(client, aim_origin);
  212.  
  213. new Float:head_origin[3];
  214. engfunc(EngFunc_GetBonePosition, client, 8, head_origin, stop); // stop isnt used, just a place holder for the function
  215.  
  216. xs_vec_sub(aim_origin, head_origin, aim_velocity);
  217. aim_velocity[2] = 0.0;
  218. xs_vec_normalize(aim_velocity, aim_velocity);
  219. xs_vec_mul_scalar(aim_velocity, maxspeed, aim_velocity);
  220. }
  221.  
  222. new button = pev(client, pev_button);
  223.  
  224. new Float:velocity[3];
  225. if( button & IN_JUMP )
  226. {
  227. new dim = side / 2;
  228. if( dim == 2 ) // jumping up or down
  229. {
  230. velocity[0] = 0.0;
  231. velocity[1] = 0.0;
  232. velocity[2] = (side % 2) == 0 ? -maxspeed : maxspeed;
  233. }
  234. else
  235. {
  236. velocity[dim] = (side % 2 == 0) ? -maxspeed : maxspeed;
  237. velocity[(dim + 1) % 2] = 0.0;
  238. velocity[2] = 0.0;
  239. }
  240. }
  241. else
  242. {
  243. if( button & IN_FORWARD )
  244. {
  245. velocity[0] += aim_velocity[0];
  246. velocity[1] += aim_velocity[1];
  247.  
  248. velocity[2] += aim_velocity[2];
  249. }
  250. if( button & IN_BACK )
  251. {
  252. velocity[0] -= aim_velocity[0];
  253. velocity[1] -= aim_velocity[1];
  254. velocity[2] -= aim_velocity[2];
  255. }
  256. if( button & IN_MOVERIGHT )
  257. {
  258. // angle velocity_aim -90 degrees
  259.  
  260. //velocity[0] += ((floatcos(-90.0, degrees) * velocity_aim[0]) - (floatsin(-90.0, degrees) * velocity_aim[1]));
  261. // cos 90 = 0 sin -90 = -1
  262. // (( 0 * velocity_aim[0] ) - ( -1 * velocity_aim[1] ))
  263. // velocity_aim[1]
  264. velocity[0] += aim_velocity[1];
  265.  
  266. //velocity[1] += ((floatsin(-90.0, degrees) * velocity_aim[0]) - (floatcos(-90.0, degrees) * velocity_aim[1]));
  267. // sin -90 = -1 cos -90 = 0
  268. // (( -1 * velocity_aim[0] ) - ( 0 * velocity_aim[1] ))
  269. // -velocity_aim[0]
  270. velocity[1] -= aim_velocity[0];
  271. }
  272. if( button & IN_MOVELEFT )
  273. {
  274. // angle velocity_aim 90 degrees
  275.  
  276. //velocity[0] += ((floatcos(90.0, degrees) * velocity_aim[0]) - (floatsin(90.0, degrees) * velocity_aim[1]));
  277. // cos 90 = 0 sin 90 = 1
  278. // (( 0 * velocity_aim[0] ) - ( 1 * velocity_aim[1] ))
  279. // -velocity_aim[1]
  280. velocity[0] -= aim_velocity[1];
  281.  
  282. //velocity[1] += ((floatsin(90.0, degrees) * velocity_aim[0]) - (floatcos(90.0, degrees) * velocity_aim[1]));
  283. // sin 90 = 1 cos 90 = 0
  284. // (( 1 * velocity_aim[0] ) - ( 0 * velocity_aim[1] ))
  285. // velocity_aim[0]
  286. velocity[1] += aim_velocity[0];
  287. }
  288.  
  289. if( (side / 2) == 2 )
  290. {
  291. velocity[2] = 0.0;
  292. }
  293. }
  294.  
  295. set_pev(client, pev_velocity, velocity);
  296.  
  297. #if !defined USE_TASK
  298. g_ladder_ent[client] = 0;
  299. #endif
  300. }
  301.  
  302. #if defined USE_TASK
  303. public TaskRemoveLadder(client)
  304. {
  305. g_ladder_ent[client - TASK_ID_CHECK] = 0;
  306. }
  307. #endif
  308.  
  309. public TaskMoveLadder(params[], taskid)
  310. {
  311. new ent = params[0];
  312.  
  313. if( !pev_valid(ent) )
  314. {
  315. remove_task(taskid);
  316. return;
  317. }
  318.  
  319. new client = taskid - TASK_ID_MOVE;
  320.  
  321. new Float:head_origin[3], Float:aim_origin[3];
  322. engfunc(EngFunc_GetBonePosition, client, 8, head_origin, aim_origin);
  323. fm_get_aim_origin(client, aim_origin);
  324.  
  325. new Float:ent_origin[3];
  326. xs_vec_sub(aim_origin, head_origin, ent_origin);
  327. xs_vec_normalize(ent_origin, ent_origin);
  328. xs_vec_mul_scalar(ent_origin, g_move_dist[client], ent_origin);
  329. xs_vec_add(ent_origin, head_origin, ent_origin);
  330. xs_vec_add(ent_origin, g_move_offset[client], ent_origin);
  331. ent_origin[2] = float(floatround(ent_origin[2], floatround_floor));
  332.  
  333. if( g_snapping[client] )
  334. {
  335. new Float:start[3], Float:end[3], Float:ret[3];
  336.  
  337. new Float:mins[3], Float:maxs[3];
  338. pev(ent, pev_mins, mins);
  339. pev(ent, pev_maxs, maxs);
  340.  
  341. new Float:dist, Float:closestDist = 9999.9;
  342. new trace, closestEnt;
  343.  
  344. new side;
  345.  
  346. for( new i = 0; i < 6; i++ )
  347. {
  348. xs_vec_copy(ent_origin, start);
  349.  
  350. start[i / 2] += ((i % 2) == 0) ? mins[i / 2] : maxs[i / 2];
  351.  
  352. xs_vec_copy(start, end);
  353.  
  354. end[i / 2] += ((i % 2) == 0) ? -10 : 10;
  355.  
  356. trace = fm_trace_line(ent, start, end, ret);
  357.  
  358. if( IsFakeLadder(trace) )
  359. {
  360. dist = get_distance_f(start, ret);
  361. if( dist < closestDist )
  362. {
  363. closestDist = dist;
  364. closestEnt = trace;
  365.  
  366. side = i;
  367. }
  368. }
  369. }
  370.  
  371. if( closestEnt )
  372. {
  373. pev(closestEnt, pev_origin, ent_origin);
  374. pev(closestEnt, pev_mins, start);
  375. pev(closestEnt, pev_maxs, end);
  376.  
  377. ent_origin[side / 2] += ((side % 2) == 0) ? (end[side / 2] + maxs[side / 2]) : (start[side / 2] + mins[side / 2]);
  378. }
  379. }
  380.  
  381. engfunc(EngFunc_SetOrigin, ent, ent_origin);
  382. SetRotation(ent, GetLadderAngle(ent));
  383. }
  384.  
  385. ShowLadderMenu(client)
  386. {
  387. new menu = menu_create("Ladder Menu", "MenuLadder");
  388.  
  389. menu_additem(menu, "Létra készítése", "1", ADMIN_LADDER);
  390. menu_additem(menu, "Létra törlése", "2", ADMIN_LADDER);
  391. menu_additem(menu, "Létra forgatása^n", "3", ADMIN_LADDER);
  392. menu_additem(menu, "Mozgatás", "4", ADMIN_LADDER);
  393. menu_additem(menu, "Mentés", "5", ADMIN_LADDER);
  394.  
  395. menu_display(client, menu);
  396. }
  397.  
  398. public MenuLadder(client, menu, item)
  399. {
  400. if( item == MENU_EXIT )
  401. {
  402. menu_destroy(menu);
  403. return;
  404. }
  405.  
  406. new _access, info[2], callback;
  407. menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
  408. menu_destroy(menu);
  409.  
  410. switch( str_to_num(info) )
  411. {
  412. case 1:
  413. {
  414. static Float:origin[3];
  415. fm_get_aim_origin(client, origin);
  416.  
  417. if( !CreateLadder(origin) )
  418. {
  419. client_print(client, print_chat, "[Ladder] A létra elemet nem sikerült létrehozni.");
  420. }
  421. }
  422. case 2:
  423. {
  424. new ent = fm_get_aim_ent(client);
  425. if( ent && IsFakeLadder(ent) )
  426. {
  427. engfunc(EngFunc_RemoveEntity, ent);
  428.  
  429. client_print(client, print_chat, "[Ladder] Létra elem törölve.");
  430. }
  431. else
  432. {
  433. client_print(client, print_chat, "[Ladder] Nem sikerült megtalálni a létra elemet.");
  434. }
  435. }
  436. case 3:
  437. {
  438. new ent = fm_get_aim_ent(client);
  439. if( ent && IsFakeLadder(ent) )
  440. {
  441. SetRotation(ent, (GetLadderAngle(ent) + 1) % Angles);
  442. }
  443. else
  444. {
  445. client_print(client, print_chat, "[Ladder] Nem sikerült megtalálni a létra elemet.");
  446. }
  447. }
  448. case 4:
  449. {
  450. ShowMoveMenu(client);
  451. return;
  452. }
  453. case 5:
  454. {
  455. ShowSaveMenu(client);
  456. return;
  457. }
  458. }
  459.  
  460. ShowLadderMenu(client);
  461. }
  462.  
  463. ShowMoveMenu(client)
  464. {
  465. new menu = menu_create("Mozgatás menü", "MenuMove");
  466.  
  467. menu_additem(menu, g_snapping[client] ? "Megfogás: \yBe^n" : "Megfogás: \rKi^n", "1", ADMIN_LADDER);
  468. menu_additem(menu, "Mozgatás X+", "2", ADMIN_LADDER);
  469. menu_additem(menu, "Mozgatás X-", "3", ADMIN_LADDER);
  470. menu_additem(menu, "Mozgatás Y+", "4", ADMIN_LADDER);
  471. menu_additem(menu, "Mozgatás Y-", "5", ADMIN_LADDER);
  472. menu_additem(menu, "Mozgatás Z+", "6", ADMIN_LADDER);
  473. menu_additem(menu, "Mozgatás Z-", "7", ADMIN_LADDER);
  474.  
  475. menu_setprop(menu, MPROP_EXITNAME, "Létra Menü");
  476.  
  477. menu_display(client, menu);
  478. }
  479.  
  480. public MenuMove(client, menu, item)
  481. {
  482. if( item == MENU_EXIT )
  483. {
  484. menu_destroy(menu);
  485. ShowLadderMenu(client);
  486. return;
  487. }
  488.  
  489. new _access, info[2], callback;
  490. menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
  491. menu_destroy(menu);
  492.  
  493. new num = str_to_num(info);
  494. if( num == 1 )
  495. {
  496. g_snapping[client] = !g_snapping[client];
  497. }
  498. else
  499. {
  500. num -= 2;
  501.  
  502. new ent = fm_get_aim_ent(client);
  503. if( ent && IsFakeLadder(ent) )
  504. {
  505. new Float:origin[3];
  506. pev(ent, pev_origin, origin);
  507.  
  508. origin[num / 2] += ((num % 2) == 0) ? 1 : -1;
  509.  
  510. set_pev(ent, pev_origin, origin);
  511. }
  512. }
  513.  
  514. ShowMoveMenu(client);
  515. }
  516.  
  517. ShowSaveMenu(client)
  518. {
  519. new menu = menu_create("Save Menu", "MenuSave");
  520.  
  521. menu_additem(menu, "Minden létra mentése", "1", ADMIN_LADDER);
  522. menu_additem(menu, "Minden létra betöltése", "2", ADMIN_LADDER);
  523. menu_additem(menu, "Minden létra törlése", "3", ADMIN_LADDER);
  524.  
  525. menu_setprop(menu, MPROP_EXITNAME, "Létra menü");
  526.  
  527. menu_display(client, menu);
  528. }
  529.  
  530. public MenuSave(client, menu, item)
  531. {
  532. if( item == MENU_EXIT )
  533. {
  534. menu_destroy(menu);
  535. ShowLadderMenu(client);
  536. return;
  537. }
  538.  
  539. new _access, info[2], callback;
  540. menu_item_getinfo(menu, item, _access, info, sizeof(info) - 1, _, _, callback);
  541. menu_destroy(menu);
  542.  
  543. switch( str_to_num(info) )
  544. {
  545. case 1:
  546. {
  547. Save();
  548. }
  549. case 2:
  550. {
  551. Load(true);
  552. }
  553. case 3:
  554. {
  555. new ent = -1;
  556. while( (ent = engfunc(EngFunc_FindEntityByString, ent, "classname", LADDER_CLASS)) )
  557. {
  558. engfunc(EngFunc_RemoveEntity, ent);
  559. }
  560.  
  561. new name[32];
  562. get_user_name(client, name, sizeof(name) - 1);
  563.  
  564. client_print(0, print_chat, "[Ladder] %s törölte az összes létra elemet.", name);
  565. }
  566. }
  567.  
  568. ShowSaveMenu(client);
  569. }
  570.  
  571. CreateLadder(Float:origin[3])
  572. {
  573. static const DEFAULT_ANGLE = ANGLE_VERT1;
  574.  
  575. new ent = engfunc(EngFunc_CreateNamedEntity, info_target);
  576. if( !pev_valid(ent) ) return 0;
  577.  
  578. set_pev(ent, pev_classname, LADDER_CLASS);
  579.  
  580. set_pev(ent, pev_solid, SOLID_BBOX);
  581. set_pev(ent, pev_movetype, MOVETYPE_NONE);
  582.  
  583. engfunc(EngFunc_SetModel, ent, LADDER_MODEL);
  584.  
  585. SetRotation(ent, DEFAULT_ANGLE);
  586.  
  587. engfunc(EngFunc_SetOrigin, ent, origin);
  588.  
  589. return ent;
  590. }
  591.  
  592. SetRotation(ent, angle)
  593. {
  594. set_pev(ent, pev_angles, LADDER_ANGLES[angle]);
  595. engfunc(EngFunc_SetSize, ent, LADDER_MINS[angle], LADDER_MAXS[angle]);
  596. }
  597.  
  598. GetLadderAngle(ent)
  599. {
  600. new Float:angles[3];
  601. pev(ent, pev_angles, angles);
  602.  
  603. for( new angle = 0; angle < Angles; angle++ )
  604. {
  605. if( xs_vec_equal(LADDER_ANGLES[angle], angles) )
  606. {
  607. return angle;
  608. }
  609. }
  610.  
  611. return 0; // should never happen, but use 0 so "index out of bounds" doesnt occur
  612. }
  613.  
  614. Load(bool:deleteall)
  615. {
  616. if( deleteall )
  617. {
  618. new ent = -1;
  619. while( (ent = engfunc(EngFunc_FindEntityByString, ent, "classname", LADDER_CLASS)) )
  620. {
  621. engfunc(EngFunc_RemoveEntity, ent);
  622. }
  623. }
  624.  
  625. if( !file_exists(g_ladder_file) ) return -1;
  626.  
  627. new count;
  628.  
  629. new f = fopen(g_ladder_file, "rt");
  630.  
  631. new data[64];
  632. new origin[3][16];
  633. new Float:_origin[3];
  634. new angle[2];
  635. new ent;
  636.  
  637. while( !feof(f) )
  638. {
  639. fgets(f, data, sizeof(data) - 1);
  640. if( !data[0] ) continue;
  641.  
  642. parse(data,\
  643. origin[0], sizeof(origin[]) - 1,\
  644. origin[1], sizeof(origin[]) - 1,\
  645. origin[2], sizeof(origin[]) - 1,\
  646. angle, sizeof(angle) - 1
  647. );
  648.  
  649. for( new i = 0; i < 3; i++ )
  650. {
  651. _origin[i] = str_to_float(origin[i]);
  652. }
  653.  
  654. ent = CreateLadder(_origin);
  655. if( ent )
  656. {
  657. SetRotation(ent, str_to_num(angle));
  658.  
  659. count++;
  660. }
  661. }
  662.  
  663. fclose(f);
  664.  
  665. return count;
  666. }
  667.  
  668. Save()
  669. {
  670. new f = fopen(g_ladder_file, "wt");
  671.  
  672. new Float:origin[3];
  673.  
  674. new ent = -1;
  675. while( (ent = engfunc(EngFunc_FindEntityByString, ent, "classname", LADDER_CLASS)) )
  676. {
  677. pev(ent, pev_origin, origin);
  678.  
  679. fprintf(f, "%f %f %f %i^n",\
  680. origin[0],\
  681. origin[1],\
  682. origin[2],\
  683. GetLadderAngle(ent)
  684. );
  685. }
  686.  
  687. fclose(f);
  688. }
  689.  
  690. // modified fm_get_aim_origin
  691. stock fm_get_aim_ent(index) {
  692. new Float:start[3], Float:view_ofs[3]
  693. pev(index, pev_origin, start)
  694. pev(index, pev_view_ofs, view_ofs)
  695. xs_vec_add(start, view_ofs, start)
  696.  
  697. new Float:dest[3]
  698. pev(index, pev_v_angle, dest)
  699. engfunc(EngFunc_MakeVectors, dest)
  700. global_get(glb_v_forward, dest)
  701. xs_vec_mul_scalar(dest, 9999.0, dest)
  702. xs_vec_add(start, dest, dest)
  703.  
  704. engfunc(EngFunc_TraceLine, start, dest, 0, index, 0)
  705.  
  706. new ent = get_tr2(0, TR_pHit);
  707. return pev_valid(ent) ? ent : 0;
  708. }
  709.