HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /* Formatright © 2009, OT
  2.  
  3. Block Wallhack is free software;
  4. you can redistribute it and/or modify it under the terms of the
  5. GNU General Public License as published by the Free Software Foundation.
  6.  
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11.  
  12. You should have received a copy of the GNU General Public License
  13. along with Migraine; if not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17.  
  18. /* [Plugin Link]
  19. https://forums.alliedmods.net/showthread.php?t=100886
  20. */
  21.  
  22. /* [Changelog]
  23. - 4.5 - texture check now isn't made that often (less crash risk!), added texture check autodisable cfg, added a new method to ignore entities that are transparent (100% efficient), reupdated the weapon headpoint
  24. - 4.2 - added bitsum remember system, smooth check is made now by FRAME_CONSTANT (1/48), changed alive/dead recognision system (less resource use!)
  25. - 4.1 - fixed plugin_init problem!
  26. - 4.0 - all bugs fixed, added texture check , everything tweaked and tuned!
  27. - 3.0 - removed Engine module (another method), improved smooth engine, removed , fixed flashing bug, target check now works both ways (if you are seen the player will be shown!)
  28. - 2.5 - removed HamSandWich module (useless), improved smooth check, corpse remove bug fixed, optimized the code a little bit.
  29. - 2.4 - bug fix release (weapon index out of bounds fix, reconnect bug fix (with CSDM), made the ent check not so sensitive (not so many blind-spots)
  30. - 2.2 - bug fix release (index out of bounds & weapon confusion bug)
  31. - 2.1 - removed a bugged feature (block_dead cvar), added smooth cvar
  32. - 2.0 - more customizable, less cpu usage (50% TESTED!), weapons grenades check added, bug fixes
  33. - 1.5 - removed some checks, optimized it a bit, added weapon head-point check
  34. - 1.0 - initial release
  35. */
  36.  
  37. /* [Credits]
  38. - joaquimandrade - for pointing out the plugin flaws!
  39. - ShlumPF* - for small improvements (initial v1.0)
  40. - turshija - for some small suggestions.
  41. - h010c - for tests and benchmarks, anti-soundhack tests and code samples
  42. - hlstriker - for finding the way to detect semi-transparent textures!
  43. - .Owyn. - bug reports
  44. */
  45.  
  46. #include <amxmodx>
  47. #include <amxmisc>
  48. #include <cstrike>
  49. #include <fakemeta>
  50. #include <hamsandwich>
  51.  
  52. #define PLUGIN "Block WallHack"
  53. #define AUTHOR "OT"
  54. #define VERSION "4.5"
  55.  
  56. #define MAX_PLAYERS 32
  57. // Uncomment this if you want to see what the plugin actually checks, the plugin will not block any wallhack in test mode!!!
  58. //#define point_test
  59. //#define ignore_bots
  60. //#define target_check
  61.  
  62. #define GENERAL_X_Y_SORROUNDING 18.5 // 16.0
  63. #define CONSTANT_Z_CROUCH_UP 31.25 // 32.0
  64. #define CONSTANT_Z_CROUCH_DOWN 17.5 // 16.0
  65. #define CONSTANT_Z_STANDUP_UP 34.0 // 36.0
  66. #define CONSTANT_Z_STANDUP_DOWN 35.25 // 36.0
  67.  
  68. #define GENERAL_X_Y_SORROUNDING_HALF 9.25 // 8.0
  69. #define GENERAL_X_Y_SORROUNDING_HALF2 12.0 // 8.0
  70. #define CONSTANT_Z_CROUCH_UP_HALF 15.5 // 16.0
  71. #define CONSTANT_Z_CROUCH_DOWN_HALF 8.75 // 8.0
  72. #define CONSTANT_Z_STANDUP_UP_HALF 17.0 // 18.0
  73. #define CONSTANT_Z_STANDUP_DOWN_HALF 17.5 // 18.0
  74.  
  75. #define ANGLE_COS_HEIGHT_CHECK 0.7071 // cos(45 degrees)
  76.  
  77. #define FRAME_OFFSET_CONSTANT 0.0208
  78.  
  79. new const Float:weapon_edge_point[CSW_P90+1] =
  80. {
  81. 0.00, // nothing
  82. 32.8, // p228
  83. 0.00, // shield
  84. 38.9, // scout
  85. 0.00, // hegrenade
  86. 31.2, // xm1014
  87. 0.00, // c4
  88. 26.0, // mac10
  89. 32.9, // aug
  90. 0.00, // smokegrenade
  91. 23.5, // elite
  92. 32.7, // fiveseven
  93. 27.0, // ump45
  94. 40.0, // sg550
  95. 26.5, // galil
  96. 32.6, // famas
  97. 38.9, // usp ( without silencer 23.5 )
  98. 32.6, // glock
  99. 39.5, // awp
  100. 30.4, // mp5
  101. 30.5, // m249
  102. 30.1, // m3
  103. 41.4, // m4a1 ( without silencer 32.6 )
  104. 39.2, // tmp
  105. 42.2, // g3sg1
  106. 0.00, // flashbang
  107. 34.1, // deagle
  108. 34.0, // sg552
  109. 24.8, // ak47
  110. 0.00, // knife
  111. 25.4 // p90
  112. }
  113.  
  114. new const Float:vec_multi_lateral[] =
  115. {
  116. GENERAL_X_Y_SORROUNDING,
  117. -GENERAL_X_Y_SORROUNDING,
  118. GENERAL_X_Y_SORROUNDING_HALF2,
  119. -GENERAL_X_Y_SORROUNDING_HALF
  120. }
  121.  
  122. new const Float:vec_add_height_crouch[] =
  123. {
  124. CONSTANT_Z_CROUCH_UP,
  125. -CONSTANT_Z_CROUCH_DOWN,
  126. CONSTANT_Z_CROUCH_UP_HALF,
  127. -CONSTANT_Z_CROUCH_DOWN_HALF
  128. }
  129.  
  130. new const Float:vec_add_height_standup[] =
  131. {
  132. CONSTANT_Z_STANDUP_UP,
  133. -CONSTANT_Z_STANDUP_DOWN,
  134. CONSTANT_Z_STANDUP_UP_HALF,
  135. -CONSTANT_Z_STANDUP_DOWN_HALF
  136. }
  137.  
  138. new g_cl_team[MAX_PLAYERS + 1]
  139. new g_cl_weapon[MAX_PLAYERS + 1]
  140. new g_cl_viewent[MAX_PLAYERS + 1]
  141. new bs_cl_alive, bs_cl_ducking, bs_cl_connect, bs_cl_bot, bs_cl_announce
  142.  
  143. #define add_bot_property(%1) bs_cl_bot |= (1<<(%1 - 1))
  144. #define del_bot_property(%1) bs_cl_bot &= ~(1<<(%1 - 1))
  145. #define has_bot_property(%1) (bs_cl_bot & (1<<(%1 - 1)))
  146. #define add_connect_property(%1) bs_cl_connect |= (1<<(%1 - 1))
  147. #define del_connect_property(%1) bs_cl_connect &= ~(1<<(%1 - 1))
  148. #define has_connect_property(%1) (bs_cl_connect & (1<<(%1 - 1)))
  149. #define add_duck_property(%1) bs_cl_ducking |= (1<<(%1 - 1))
  150. #define del_duck_property(%1) bs_cl_ducking &= ~(1<<(%1 - 1))
  151. #define has_duck_property(%1) (bs_cl_ducking & (1<<(%1 - 1)))
  152. #define add_alive_property(%1) bs_cl_alive |= (1<<(%1 - 1))
  153. #define del_alive_property(%1) bs_cl_alive &= ~(1<<(%1 - 1))
  154. #define has_alive_property(%1) (bs_cl_alive & (1<<(%1 - 1)))
  155. #define add_alive_property(%1) bs_cl_alive |= (1<<(%1 - 1))
  156. #define del_alive_property(%1) bs_cl_alive &= ~(1<<(%1 - 1))
  157. #define has_alive_property(%1) (bs_cl_alive & (1<<(%1 - 1)))
  158. #define add_announced(%1) bs_cl_announce |= (1<<(%1 - 1))
  159. #define del_announced(%1) bs_cl_announce &= ~(1<<(%1 - 1))
  160. #define has_been_announced(%1) (bs_cl_announce & (1<<(%1 - 1)))
  161.  
  162. new bs_cl_targets[MAX_PLAYERS + 1]
  163. new bs_cl_seen_by[MAX_PLAYERS + 1]
  164. new bs_cl_smooth[MAX_PLAYERS + 1] = {~0, ...} // ~0 = -4294967295
  165.  
  166. // %0 is the player that targets, is seen by , can smooth
  167. #define add_targeted_player(%0,%1) bs_cl_targets[%0] |= (1<<(%1 - 1))
  168. #define del_targeted_player(%0,%1) bs_cl_targets[%0] &= ~(1<<(%1 - 1))
  169. #define player_targets_user(%0,%1) (bs_cl_targets[%0] & (1<<(%1 - 1)))
  170. #define add_seen_by_player(%0,%1) bs_cl_seen_by[%0] |= (1<<(%1 - 1))
  171. #define del_seen_by_player(%0,%1) bs_cl_seen_by[%0] &= ~(1<<(%1 - 1))
  172. #define is_user_seen_by(%0,%1) (bs_cl_seen_by[%0] & (1<<(%1 - 1)))
  173. #define enable_smooth_between(%0,%1) bs_cl_smooth[%0] |= (1<<(%1 - 1))
  174. #define disable_smooth_between(%0,%1) bs_cl_smooth[%0] &= ~(1<<(%1 - 1))
  175. #define can_use_smooth_between(%0,%1) (bs_cl_smooth[%0] & (1<<(%1 - 1)))
  176.  
  177.  
  178. new pcv_on_off
  179. new pcv_ignore_team
  180. new pcv_blockents
  181. new pcv_fov_check
  182. new pcv_tg_check
  183. new pcv_engine_pvs
  184. new pcv_smooth
  185. new pcv_texture
  186.  
  187. new pcg_on_off
  188. new pcg_ignore
  189. new pcg_blockents
  190. new pcg_fov_check
  191. new pcg_tg_check
  192. new pcg_engine_pvs
  193. new pcg_smooth
  194. new pcg_texture
  195.  
  196. new thdl
  197.  
  198. new g_maxplayers
  199.  
  200. stock spr_bomb
  201. stock beampoint
  202.  
  203. // These bitsums allow 2048 entities storage. I think that it is enough :P.
  204. new bs_array_transp[64] // BitSum, This is equal to 64*32 bools (good for quick search)
  205. new bs_array_solid[64] // BitSum, This is equal to 64*32 bools (good for quick search)
  206.  
  207. #define add_transparent_ent(%1) bs_array_transp[((%1 - 1) / 32)] |= (1<<((%1 - 1) % 32))
  208. #define del_transparent_ent(%1) bs_array_transp[((%1 - 1) / 32)] &= ~(1<<((%1 - 1) % 32))
  209. #define is_transparent_ent(%1) (bs_array_transp[((%1 - 1) / 32)] & (1<<((%1 - 1) % 32)))
  210. #define add_solid_ent(%1) bs_array_solid[((%1 - 1) / 32)] |= (1<<((%1 - 1) % 32))
  211. #define del_solid_ent(%1) bs_array_solid[((%1 - 1) / 32)] &= ~(1<<((%1 - 1) % 32))
  212. #define is_solid_ent(%1) (bs_array_solid[((%1 - 1) / 32)] & (1<<((%1 - 1) % 32)))
  213.  
  214. new CFG_FILE[300]
  215. new const CFG_NAME[] = "wb_mapign.cfg"
  216. new bool:g_donttexture = false
  217.  
  218. public plugin_precache()
  219. {
  220. spr_bomb = precache_model("sprites/ledglow.spr")
  221. beampoint = precache_model("sprites/laserbeam.spr")
  222.  
  223. register_forward(FM_Spawn, "fw_spawn", 1)
  224. }
  225.  
  226. public fw_spawn(ent)
  227. {
  228. if (!pev_valid(ent))
  229. return FMRES_IGNORED
  230.  
  231. static rendermode, Float:renderamt
  232.  
  233. rendermode = pev(ent, pev_rendermode)
  234. pev(ent, pev_renderamt, renderamt)
  235.  
  236. if (((rendermode == kRenderTransColor || rendermode == kRenderGlow || rendermode == kRenderTransTexture) && renderamt < 255.0) || (rendermode == kRenderTransAdd))
  237. {
  238. add_transparent_ent(ent)
  239.  
  240. return FMRES_IGNORED
  241. }
  242.  
  243. return FMRES_IGNORED
  244. }
  245.  
  246. public plugin_init()
  247. {
  248. register_plugin(PLUGIN, VERSION, AUTHOR)
  249. register_cvar("wallblocker_version", VERSION, FCVAR_SPONLY | FCVAR_SERVER)
  250. register_cvar("wallblocker_author" , AUTHOR , FCVAR_SPONLY | FCVAR_SERVER)
  251.  
  252. pcv_on_off = register_cvar("wallblocker_enable", "1", FCVAR_SPONLY | FCVAR_SERVER)
  253. pcv_ignore_team = register_cvar("wallblocker_ignore_team", "1")
  254. pcv_blockents = register_cvar("wallblocker_block_ents", "1")
  255. pcv_fov_check = register_cvar("wallblocker_fov_check", "1")
  256. pcv_tg_check = register_cvar("wallblocker_target_check", "1")
  257. pcv_engine_pvs = register_cvar("wallblocker_engine_check", "1")
  258. pcv_smooth = register_cvar("wallblocker_smooth_check", "1")
  259. pcv_texture = register_cvar("wallblocker_textureallow", "1")
  260.  
  261. register_forward(FM_AddToFullPack, "fw_addtofullpack" , 0)
  262. register_forward(FM_PlayerPreThink, "fw_prethink" , 0)
  263. register_forward(FM_TraceLine, "pfw_traceline" , 1)
  264. register_forward(FM_SetView, "fw_setview")
  265.  
  266. RegisterHam(Ham_Spawn, "player", "fw_alive_handle", 1)
  267. RegisterHam(Ham_Killed, "player", "fw_alive_handle", 1)
  268.  
  269. RegisterHam(Ham_Blocked, "func_wall", "fw_stuck")
  270. RegisterHam(Ham_Blocked, "func_ladder", "fw_stuck")
  271.  
  272. register_clcmd("wallblocker", "cmd_version_show")
  273.  
  274. register_event("CurWeapon", "event_active_weapon", "be")
  275.  
  276. register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
  277.  
  278. thdl = create_tr2()
  279.  
  280. g_maxplayers = get_maxplayers()
  281.  
  282. for (new i=1;i<=g_maxplayers;i++)
  283. {
  284. add_solid_ent(i)
  285. g_cl_viewent[i] = i
  286. }
  287.  
  288. new maxents = global_get(glb_maxEntities)
  289.  
  290. for (new i=1;i<maxents;i++)
  291. {
  292. if (is_transparent_ent(i))
  293. {
  294. //set_pev(i, pev_solid, SOLID_BBOX)
  295. }
  296. }
  297.  
  298. get_configsdir(CFG_FILE, charsmax(CFG_FILE))
  299. format(CFG_FILE, charsmax(CFG_FILE),"%s/%s", CFG_FILE, CFG_NAME)
  300.  
  301. new mapname[40]
  302. get_mapname(mapname, charsmax(mapname))
  303.  
  304. if (!file_exists(CFG_FILE))
  305. {
  306. g_donttexture = false
  307. }
  308. else
  309. {
  310. new pf = fopen(CFG_FILE, "r"), line[40]
  311.  
  312. while (!feof(pf))
  313. {
  314. fgets(pf, line, charsmax(line))
  315.  
  316. if (line[0] == ';' || line[0] == '/')
  317. continue
  318.  
  319. if (equal(line, mapname) && validate_map(mapname))
  320. {
  321. g_donttexture = true
  322. break
  323. }
  324. }
  325.  
  326. fclose(pf)
  327. }
  328.  
  329. }
  330.  
  331. public fw_stuck(stuckent, id)
  332. {
  333. if (is_transparent_ent(stuckent) && 1 <= id <= g_maxplayers)
  334. return HAM_SUPERCEDE
  335.  
  336. return HAM_IGNORED
  337. }
  338.  
  339. public fw_setview(id, attachent)
  340. {
  341. g_cl_viewent[id] = attachent
  342.  
  343. return FMRES_IGNORED
  344. }
  345.  
  346. public message_clcorpse(msg_id, msg_dest, entity)
  347. {
  348. if (!has_connect_property(get_msg_arg_int(12)))
  349. return PLUGIN_HANDLED
  350.  
  351. return PLUGIN_CONTINUE
  352. }
  353.  
  354. public plugin_end()
  355. {
  356. free_tr2(thdl)
  357. }
  358.  
  359. public client_connect(id)
  360. {
  361. del_alive_property(id)
  362. del_connect_property(id)
  363. }
  364.  
  365. public client_putinserver(id)
  366. {
  367. #if defined ignore_bots
  368. del_bot_property(id)
  369. #else
  370. if (is_user_bot(id))
  371. add_bot_property(id)
  372. else
  373. del_bot_property(id)
  374. #endif
  375.  
  376. add_connect_property(id)
  377. del_announced(id)
  378. }
  379.  
  380. public cmd_version_show(id)
  381. {
  382. client_print(id, print_console, "This server is using WallBlocker v%s",VERSION)
  383. }
  384.  
  385. public client_disconnect(id)
  386. {
  387. del_bot_property(id)
  388. del_alive_property(id)
  389. del_connect_property(id)
  390. del_announced(id)
  391. }
  392.  
  393. public event_active_weapon(id)
  394. {
  395. pcg_ignore = get_pcvar_num(pcv_ignore_team)
  396. pcg_on_off = get_pcvar_num(pcv_on_off)
  397. pcg_blockents = get_pcvar_num(pcv_blockents)
  398. pcg_fov_check = get_pcvar_num(pcv_fov_check)
  399. pcg_tg_check = get_pcvar_num(pcv_tg_check)
  400. pcg_engine_pvs = get_pcvar_num(pcv_engine_pvs)
  401. pcg_smooth = get_pcvar_num(pcv_smooth)
  402. pcg_texture = get_pcvar_num(pcv_texture)
  403.  
  404. if (read_data(1) == 1)
  405. {
  406. g_cl_weapon[id] = read_data(2)
  407.  
  408. if (g_cl_weapon[id] < CSW_P228 || g_cl_weapon[id] > CSW_P90)
  409. {
  410. g_cl_weapon[id] = CSW_KNIFE
  411. }
  412.  
  413. g_cl_team[id] = _:cs_get_user_team(id)
  414. }
  415.  
  416. return PLUGIN_CONTINUE
  417. }
  418.  
  419. public fw_alive_handle(id)
  420. {
  421. if (!is_user_alive(id))
  422. {
  423. del_alive_property(id)
  424. }
  425. else
  426. {
  427. if (!has_bot_property(id) && !has_been_announced(id))
  428. {
  429. add_announced(id)
  430. // Please let the cheaters know that they are screwed! Do not erase this from the plugin!
  431. client_print(id, print_chat, "This server is using WallBlocker v%s, made by OT",VERSION)
  432. }
  433.  
  434. add_alive_property(id)
  435. reset_plugin_client_status(id)
  436. }
  437. }
  438.  
  439. public fw_prethink(id)
  440. {
  441. if (!pcg_on_off)
  442. return FMRES_IGNORED
  443.  
  444. if (!has_connect_property(id))
  445. return FMRES_IGNORED
  446.  
  447. if (has_alive_property(id))
  448. {
  449. if (pev(id, pev_flags) & FL_DUCKING)
  450. {
  451. add_duck_property(id)
  452. }
  453. else
  454. {
  455. del_duck_property(id)
  456. }
  457. }
  458.  
  459. return FMRES_IGNORED
  460. }
  461. public fw_addtofullpack(es, e, ent, host, flags, player, set)
  462. {
  463. if (!pcg_on_off)
  464. return FMRES_IGNORED
  465.  
  466. if (!has_connect_property(host))
  467. return FMRES_IGNORED
  468.  
  469. if (!has_alive_property(host))
  470. return FMRES_IGNORED
  471.  
  472. if (has_bot_property(host) || g_cl_team[host] == _:CS_TEAM_SPECTATOR || g_cl_team[host] == _:CS_TEAM_UNASSIGNED)
  473. return FMRES_IGNORED
  474.  
  475. if (!player && !pcg_blockents)
  476. {
  477. return FMRES_IGNORED
  478. }
  479.  
  480. if (!player && pcg_blockents)
  481. {
  482. if (!pev_valid(ent))
  483. return FMRES_IGNORED
  484.  
  485. if (pev(ent, pev_owner) == host)
  486. return FMRES_IGNORED
  487.  
  488. static class_name[10]
  489. pev(ent, pev_classname, class_name, charsmax(class_name))
  490.  
  491. if (!equal(class_name, "grenade"))
  492. {
  493. if (!equal(class_name, "g_cl_weaponbox"))
  494. {
  495. return FMRES_IGNORED
  496. }
  497. }
  498.  
  499. if (pcg_engine_pvs && g_cl_viewent[host] == host)
  500. {
  501. if (!engfunc(EngFunc_CheckVisibility, ent, set))
  502. {
  503. // the ent cannot be seen so we block the send channel
  504. forward_return(FMV_CELL, 0)
  505. return FMRES_SUPERCEDE
  506. }
  507. }
  508.  
  509. static Float:origin[3], Float:end[3], Float:plane_vec[3], Float:normal[3]
  510.  
  511. if ( g_cl_viewent[host] == host )
  512. pev(host, pev_origin, origin)
  513. else
  514. pev(g_cl_viewent[host], pev_origin, origin)
  515.  
  516. if (pcg_fov_check)
  517. {
  518. pev(host, pev_v_angle, normal)
  519. angle_vector(normal,ANGLEVECTOR_FORWARD, normal)
  520.  
  521. pev(ent, pev_origin, end)
  522. xs_vec_sub(end, origin, plane_vec)
  523. xs_vec_mul_scalar(plane_vec, (1.0/xs_vec_len(plane_vec)), plane_vec)
  524.  
  525. if (xs_vec_dot(plane_vec, normal) < 0)
  526. {
  527. forward_return(FMV_CELL, 0)
  528. return FMRES_SUPERCEDE
  529. }
  530.  
  531. if (g_cl_viewent[host] == host)
  532. {
  533. pev(host, pev_view_ofs, plane_vec)
  534. xs_vec_add(plane_vec, origin, origin)
  535. }
  536. }
  537. else
  538. {
  539. if (g_cl_viewent[host] == host)
  540. {
  541. pev(host, pev_view_ofs, end)
  542.  
  543. xs_vec_add(end, origin, origin)
  544. }
  545.  
  546. pev(ent, pev_origin, end)
  547. }
  548.  
  549. if (is_point_almost_visible(origin, end, ent))
  550. return FMRES_IGNORED
  551.  
  552. #if defined point_test
  553. return FMRES_IGNORED
  554. #else
  555. // the player cannot be seen so we block the send channel
  556. forward_return(FMV_CELL, 0)
  557. return FMRES_SUPERCEDE
  558. #endif
  559. }
  560.  
  561. if (!has_alive_property(ent))
  562. return FMRES_IGNORED
  563.  
  564. if (pcg_ignore && g_cl_team[ent] == g_cl_team[host])
  565. return FMRES_IGNORED
  566.  
  567. if (host != ent)
  568. {
  569. if (pcg_tg_check)
  570. {
  571. if (is_user_seen_by(host, ent))
  572. {
  573. del_targeted_player(host, ent)
  574. del_seen_by_player(host, ent)
  575. disable_smooth_between(host, ent)
  576.  
  577. return FMRES_IGNORED
  578. }
  579.  
  580. if (player_targets_user(host, ent))
  581. {
  582. del_targeted_player(host, ent)
  583. del_seen_by_player(host, ent)
  584. disable_smooth_between(host, ent)
  585.  
  586. return FMRES_IGNORED
  587. }
  588. }
  589.  
  590. if (pcg_engine_pvs && g_cl_viewent[host] == host)
  591. {
  592. if (!engfunc(EngFunc_CheckVisibility, ent, set))
  593. {
  594. // the ent cannot be seen so we block the send channel
  595. enable_smooth_between(host, ent)
  596.  
  597. forward_return(FMV_CELL, 0)
  598. return FMRES_SUPERCEDE
  599. }
  600. }
  601.  
  602. static Float:origin[3], Float:start[3], Float:end[3], Float:addict[3], Float:plane_vec[3], Float:normal[3], ignore_ent
  603.  
  604. ignore_ent = host
  605.  
  606. if (g_cl_viewent[host] == host)
  607. pev(host, pev_origin, origin)
  608. else
  609. pev(g_cl_viewent[host], pev_origin, origin)
  610.  
  611. if (pcg_fov_check)
  612. {
  613. pev(host, pev_v_angle, normal)
  614. angle_vector(normal, ANGLEVECTOR_FORWARD, normal)
  615.  
  616. pev(ent, pev_origin, end)
  617. xs_vec_sub(end, origin, plane_vec)
  618. xs_vec_mul_scalar(plane_vec, (1.0 / xs_vec_len(plane_vec)), plane_vec)
  619.  
  620. if (xs_vec_dot(plane_vec, normal) < 0)
  621. {
  622. enable_smooth_between(host, ent)
  623.  
  624. forward_return(FMV_CELL, 0)
  625. return FMRES_SUPERCEDE
  626. }
  627.  
  628. if (g_cl_viewent[host] == host)
  629. {
  630. pev(host, pev_view_ofs, start)
  631. xs_vec_add(start, origin, start)
  632. }
  633. else
  634. {
  635. start = origin
  636. }
  637.  
  638. if (pcg_smooth && can_use_smooth_between(host, ent))
  639. {
  640. pev(host, pev_velocity, origin)
  641.  
  642. if (!xs_vec_equal(origin, Float:{0.0, 0.0, 0.0}))
  643. {
  644. xs_vec_mul_scalar(origin, FRAME_OFFSET_CONSTANT, origin)
  645.  
  646. xs_vec_add(start, origin, start)
  647. }
  648.  
  649. pev(ent, pev_velocity, origin)
  650.  
  651. if (!xs_vec_equal(origin, Float:{0.0, 0.0, 0.0}))
  652. {
  653. xs_vec_mul_scalar(origin, FRAME_OFFSET_CONSTANT, origin)
  654.  
  655. xs_vec_add(origin, end, origin)
  656. }
  657. else
  658. {
  659. origin = end
  660. }
  661. }
  662. else
  663. {
  664. origin = end
  665. }
  666. }
  667. else
  668. {
  669. if (g_cl_viewent[host] == host)
  670. {
  671. pev(host, pev_view_ofs, start)
  672. xs_vec_add(start, origin, start)
  673. }
  674. else
  675. {
  676. start = origin
  677. }
  678.  
  679. pev(ent, pev_origin, end)
  680.  
  681. if (pcg_smooth && can_use_smooth_between(host, ent))
  682. {
  683. pev(host, pev_velocity, origin)
  684.  
  685. if (!xs_vec_equal(origin, Float:{0.0, 0.0, 0.0}))
  686. {
  687. xs_vec_mul_scalar(origin, FRAME_OFFSET_CONSTANT, origin)
  688.  
  689. xs_vec_add(start, origin, start)
  690. }
  691.  
  692. pev(ent, pev_velocity, origin)
  693.  
  694. if (!xs_vec_equal(origin, Float:{0.0, 0.0, 0.0}))
  695. {
  696. xs_vec_mul_scalar(origin, FRAME_OFFSET_CONSTANT, origin)
  697.  
  698. xs_vec_add(origin, end, origin)
  699. }
  700. else
  701. {
  702. origin = end
  703. }
  704. }
  705. else
  706. {
  707. origin = end
  708. }
  709. }
  710.  
  711. xs_vec_sub(start, origin, normal)
  712.  
  713. // If origin is visible don't do anything
  714. if (pcg_texture)
  715. {
  716. if (is_point_visible_texture(start, origin, ignore_ent))
  717. {
  718. disable_smooth_between(host, ent)
  719. return FMRES_IGNORED
  720. }
  721. }
  722. else
  723. {
  724. if (is_point_visible(start, origin, ignore_ent))
  725. {
  726. disable_smooth_between(host, ent)
  727. return FMRES_IGNORED
  728. }
  729. }
  730.  
  731. pev(ent, pev_view_ofs, end)
  732. xs_vec_add(end, origin, end)
  733.  
  734. // If eye origin is visible don't do anything
  735. if (is_point_visible(start, end, ignore_ent))
  736. {
  737. disable_smooth_between(host, ent)
  738. return FMRES_IGNORED
  739. }
  740.  
  741. // Check g_cl_weapon point
  742. if (weapon_edge_point[g_cl_weapon[ent]] != 0.00)
  743. {
  744. pev(ent, pev_v_angle, addict)
  745. angle_vector(addict, ANGLEVECTOR_FORWARD, addict)
  746. xs_vec_mul_scalar(addict, weapon_edge_point[g_cl_weapon[ent]], addict)
  747. xs_vec_add(end, addict, end)
  748.  
  749. // If g_cl_weapon head is visible don't do anything
  750. if (is_point_visible(start, end, ignore_ent))
  751. {
  752. disable_smooth_between(host, ent)
  753. return FMRES_IGNORED
  754. }
  755. }
  756.  
  757. // We use this to obtain the plain.
  758. xs_vec_mul_scalar(normal, 1.0/(xs_vec_len(normal)), normal)
  759. vector_to_angle(normal, plane_vec)
  760. angle_vector(plane_vec, ANGLEVECTOR_RIGHT, plane_vec)
  761.  
  762. if (floatabs(normal[2]) <= ANGLE_COS_HEIGHT_CHECK)
  763. {
  764. if (has_duck_property(ent))
  765. {
  766. for (new i=0;i<4;i++)
  767. {
  768. if (i<2)
  769. {
  770. for (new j=0;j<2;j++)
  771. {
  772. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  773. addict[2] = vec_add_height_crouch[j]
  774. xs_vec_add(origin, addict, end)
  775.  
  776. if (is_point_visible(start, end, ignore_ent))
  777. {
  778. disable_smooth_between(host, ent)
  779. return FMRES_IGNORED
  780. }
  781. }
  782. }
  783. else
  784. {
  785. for (new j=2;j<4;j++)
  786. {
  787. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  788. addict[2] = vec_add_height_crouch[j]
  789. xs_vec_add(origin, addict, end)
  790.  
  791. if (is_point_visible(start, end, ignore_ent))
  792. {
  793. disable_smooth_between(host, ent)
  794. return FMRES_IGNORED
  795. }
  796. }
  797. }
  798. }
  799. }
  800. else
  801. {
  802. for (new i=0;i<4;i++)
  803. {
  804. if (i<2)
  805. {
  806. for (new j=0;j<2;j++)
  807. {
  808. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  809. addict[2] = vec_add_height_standup[j]
  810. xs_vec_add(origin, addict, end)
  811.  
  812. if (is_point_visible(start, end, ignore_ent))
  813. {
  814. disable_smooth_between(host, ent)
  815. return FMRES_IGNORED
  816. }
  817. }
  818. }
  819. else
  820. {
  821. for (new j=2;j<4;j++)
  822. {
  823. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  824. addict[2] = vec_add_height_standup[j]
  825. xs_vec_add(origin, addict, end)
  826.  
  827. if (is_point_visible(start, end, ignore_ent))
  828. {
  829. disable_smooth_between(host, ent)
  830. return FMRES_IGNORED
  831. }
  832. }
  833. }
  834. }
  835. }
  836. }
  837. else
  838. {
  839. if (normal[2] > 0.0)
  840. {
  841. normal[2] = 0.0
  842. xs_vec_mul_scalar(normal, 1/(xs_vec_len(normal)), normal)
  843.  
  844. if (has_duck_property(ent))
  845. {
  846. for (new i=0;i<4;i++)
  847. {
  848. if (i<2)
  849. {
  850. for (new j=0;j<2;j++)
  851. {
  852. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  853. addict[2] = vec_add_height_crouch[j]
  854. xs_vec_add(origin, addict, end)
  855. xs_vec_mul_scalar(normal, (j == 0) ? (-GENERAL_X_Y_SORROUNDING) : (GENERAL_X_Y_SORROUNDING), addict)
  856. xs_vec_add(end, addict, end)
  857.  
  858. if (is_point_visible(start, end, ignore_ent))
  859. {
  860. disable_smooth_between(host, ent)
  861. return FMRES_IGNORED
  862. }
  863. }
  864. }
  865. else
  866. {
  867. for (new j=2;j<4;j++)
  868. {
  869. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  870. addict[2] = vec_add_height_crouch[j]
  871. xs_vec_add(origin, addict, end)
  872.  
  873. if (is_point_visible(start, end, ignore_ent))
  874. {
  875. disable_smooth_between(host, ent)
  876. return FMRES_IGNORED
  877. }
  878. }
  879. }
  880. }
  881. }
  882. else
  883. {
  884. for (new i=0;i<4;i++)
  885. {
  886. if (i<2)
  887. {
  888. for (new j=0;j<2;j++)
  889. {
  890. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  891. addict[2] = vec_add_height_standup[j]
  892. xs_vec_add(origin, addict, end)
  893. xs_vec_mul_scalar(normal, (j == 0) ? (-GENERAL_X_Y_SORROUNDING) : (GENERAL_X_Y_SORROUNDING), addict)
  894. xs_vec_add(end, addict, end)
  895.  
  896. if (is_point_visible(start, end, ignore_ent))
  897. {
  898. disable_smooth_between(host, ent)
  899. return FMRES_IGNORED
  900. }
  901. }
  902. }
  903. else
  904. {
  905. for (new j=2;j<4;j++)
  906. {
  907. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  908. addict[2] = vec_add_height_standup[j]
  909. xs_vec_add(origin, addict, end)
  910.  
  911. if (is_point_visible(start, end, ignore_ent))
  912. {
  913. disable_smooth_between(host, ent)
  914. return FMRES_IGNORED
  915. }
  916. }
  917. }
  918. }
  919. }
  920. }
  921. else
  922. {
  923. normal[2] = 0.0
  924. xs_vec_mul_scalar(normal, 1/(xs_vec_len(normal)), normal)
  925.  
  926. if (has_duck_property(ent))
  927. {
  928. for (new i=0;i<4;i++)
  929. {
  930. if (i<2)
  931. {
  932. for (new j=0;j<2;j++)
  933. {
  934. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  935. addict[2] = vec_add_height_crouch[j]
  936. xs_vec_add(origin, addict, end)
  937. xs_vec_mul_scalar(normal, (j == 0) ? GENERAL_X_Y_SORROUNDING : (-GENERAL_X_Y_SORROUNDING), addict)
  938. xs_vec_add(end, addict, end)
  939.  
  940. if (is_point_visible(start, end, ignore_ent))
  941. {
  942. disable_smooth_between(host, ent)
  943. return FMRES_IGNORED
  944. }
  945. }
  946. }
  947. else
  948. {
  949. for (new j=2;j<4;j++)
  950. {
  951. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  952. addict[2] = vec_add_height_crouch[j]
  953. xs_vec_add(origin, addict, end)
  954.  
  955. if (is_point_visible(start, end, ignore_ent))
  956. {
  957. disable_smooth_between(host, ent)
  958. return FMRES_IGNORED
  959. }
  960. }
  961. }
  962. }
  963. }
  964. else
  965. {
  966. for (new i=0;i<4;i++)
  967. {
  968. if (i<2)
  969. {
  970. for (new j=0;j<2;j++)
  971. {
  972. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  973. addict[2] = vec_add_height_standup[j]
  974. xs_vec_add(origin, addict, end)
  975. xs_vec_mul_scalar(normal, (j == 0) ? GENERAL_X_Y_SORROUNDING : (-GENERAL_X_Y_SORROUNDING), addict)
  976. xs_vec_add(end, addict, end)
  977.  
  978. if (is_point_visible(start, end, ignore_ent))
  979. {
  980. disable_smooth_between(host, ent)
  981. return FMRES_IGNORED
  982. }
  983. }
  984. }
  985. else
  986. {
  987. for (new j=2;j<4;j++)
  988. {
  989. xs_vec_mul_scalar(plane_vec, vec_multi_lateral[i], addict)
  990. addict[2] = vec_add_height_standup[j]
  991. xs_vec_add(origin, addict, end)
  992.  
  993. if (is_point_visible(start, end, ignore_ent))
  994. {
  995. disable_smooth_between(host, ent)
  996. return FMRES_IGNORED
  997. }
  998. }
  999. }
  1000. }
  1001. }
  1002. }
  1003. }
  1004.  
  1005. #if defined point_test
  1006. return FMRES_IGNORED
  1007. #else
  1008. enable_smooth_between(host, ent)
  1009.  
  1010. // the player cannot be seen so we block the send channel
  1011. forward_return(FMV_CELL, 0)
  1012. return FMRES_SUPERCEDE
  1013. #endif
  1014. }
  1015.  
  1016. return FMRES_IGNORED
  1017. }
  1018.  
  1019. public pfw_traceline(const Float:start[3], const Float:end[3], cond, id, tr)
  1020. {
  1021. if (!pcg_on_off)
  1022. return FMRES_IGNORED
  1023.  
  1024. if (id <= 0 || id > g_maxplayers)
  1025. return FMRES_IGNORED
  1026.  
  1027. if (!has_connect_property(id))
  1028. return FMRES_IGNORED
  1029.  
  1030. new target = get_tr(TR_pHit)
  1031.  
  1032. if (!has_alive_property(id))
  1033. {
  1034. bs_cl_targets[id] = 0
  1035. }
  1036. else if (is_user_alive(target))
  1037. {
  1038. add_targeted_player(id, target)
  1039. }
  1040.  
  1041. if (pcg_tg_check)
  1042. {
  1043. if (1 <= target <= g_maxplayers)
  1044. add_seen_by_player(target, id)
  1045.  
  1046. #if defined target_check
  1047.  
  1048. new name[32], bs = see_by[id], string[400]
  1049. new i=0
  1050.  
  1051. if (1 <= target[id] <= g_maxplayers)
  1052. {
  1053. get_user_name(target[id], name, charsmax(name))
  1054. client_print(id, print_chat, "SEE: %s", name)
  1055. }
  1056.  
  1057. format(string, charsmax(string), "")
  1058.  
  1059. while (bs != 0)
  1060. {
  1061. if ( bs & (1<<i) )
  1062. {
  1063. get_user_name((i+1), name, charsmax(name))
  1064. format(string, charsmax(string), "%s%s ", string, name)
  1065. bs &= ~(1<<i)
  1066. }
  1067.  
  1068. i++
  1069. }
  1070.  
  1071. client_print(id, print_chat, "SEE BY: %s", string)
  1072. #endif
  1073. }
  1074.  
  1075. return FMRES_IGNORED
  1076. }
  1077.  
  1078. #if !defined point_test
  1079. bool:is_point_visible(const Float:start[3], const Float:point[3], ignore_ent)
  1080. {
  1081. engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
  1082.  
  1083. static Float:fraction
  1084. get_tr2(thdl, TR_flFraction, fraction)
  1085.  
  1086. return (fraction == 1.0)
  1087. }
  1088.  
  1089. bool:is_point_visible_texture(const Float:start[3], const Float:point[3], ignore_ent)
  1090. {
  1091. engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
  1092.  
  1093. static ent
  1094. ent = get_tr2(thdl, TR_pHit)
  1095.  
  1096. static Float:fraction
  1097. get_tr2(thdl, TR_flFraction, fraction)
  1098.  
  1099. if (fraction != 1.0 && ent > g_maxplayers && !g_donttexture)
  1100. {
  1101. if (!is_transparent_ent(ent) && !is_solid_ent(ent))
  1102. {
  1103. static texture_name[2]
  1104. static Float:vec[3]
  1105. xs_vec_sub(point, start, vec)
  1106. xs_vec_mul_scalar(vec, (5000.0 / xs_vec_len(vec)), vec)
  1107. xs_vec_add(start, vec, vec)
  1108.  
  1109. engfunc(EngFunc_TraceTexture, ent, start, vec, texture_name, charsmax(texture_name))
  1110.  
  1111. if (equal(texture_name, "{"))
  1112. {
  1113. add_transparent_ent(ent)
  1114.  
  1115. set_pev(ent, pev_solid, SOLID_BBOX)
  1116.  
  1117. static players[32], num, id, Float:origin[3]
  1118. get_players(players, num, "a")
  1119.  
  1120. for (new i=0;i<num;i++)
  1121. {
  1122. id = players[i]
  1123.  
  1124. if ( pev(id,pev_groundentity) == ent )
  1125. {
  1126. pev(id, pev_origin, origin)
  1127.  
  1128. origin[2] += 1.0
  1129.  
  1130. set_pev(id, pev_origin, origin)
  1131. }
  1132. }
  1133.  
  1134. ignore_ent = ent
  1135.  
  1136. engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
  1137.  
  1138. get_tr2(thdl, TR_flFraction, fraction)
  1139.  
  1140. return (fraction == 1.0)
  1141. }
  1142. else
  1143. {
  1144. add_solid_ent(ent)
  1145. return (fraction == 1.0)
  1146. }
  1147. }
  1148. else
  1149. {
  1150. if (is_solid_ent(ent))
  1151. {
  1152. return (fraction == 1.0)
  1153. }
  1154. else
  1155. {
  1156. ignore_ent = ent
  1157. engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
  1158. get_tr2(thdl, TR_flFraction, fraction)
  1159. return (fraction == 1.0)
  1160. }
  1161. }
  1162. }
  1163.  
  1164. return (fraction == 1.0)
  1165. }
  1166.  
  1167.  
  1168. bool:is_point_almost_visible(const Float:start[3], const Float:point[3], ignore_ent)
  1169. {
  1170. engfunc(EngFunc_TraceLine, start, point, IGNORE_GLASS | IGNORE_MONSTERS, ignore_ent, thdl)
  1171.  
  1172. static Float:fraction
  1173. get_tr2(thdl, TR_flFraction, fraction)
  1174.  
  1175. return (fraction >= 0.9)
  1176. }
  1177. #else
  1178.  
  1179. bool:is_point_visible(const Float:start[3], const Float:point[3], ignore_ent)
  1180. {
  1181. bomb_led(point)
  1182. return false
  1183. }
  1184.  
  1185.  
  1186. bool:is_point_almost_visible(const Float:start[3], const Float:point[3], ignore_ent)
  1187. {
  1188. bomb_led(point)
  1189. return false
  1190. }
  1191. #endif
  1192.  
  1193. stock bool:validate_map(mapname[])
  1194. {
  1195. if ( is_map_valid(mapname) )
  1196. {
  1197. return true;
  1198. }
  1199. // If the is_map_valid check failed, check the end of the string
  1200. new len = strlen(mapname) - 4;
  1201.  
  1202. // The mapname was too short to possibly house the .bsp extension
  1203. if (len < 0)
  1204. {
  1205. return false;
  1206. }
  1207. if ( equali(mapname[len], ".bsp") )
  1208. {
  1209. // If the ending was .bsp, then cut it off.
  1210. // the string is byref'ed, so this copies back to the loaded text.
  1211. mapname[len] = '^0';
  1212.  
  1213. // recheck
  1214. if ( is_map_valid(mapname) )
  1215. {
  1216. return true;
  1217. }
  1218. }
  1219.  
  1220. return false;
  1221. }
  1222.  
  1223. reset_plugin_client_status(id)
  1224. {
  1225. bs_cl_seen_by[id] = 0
  1226. bs_cl_targets[id] = 0
  1227. bs_cl_smooth[id] = ~0
  1228. }
  1229.  
  1230. stock xs_vec_add(const Float:in1[], const Float:in2[], Float:out[])
  1231. {
  1232. out[0] = in1[0] + in2[0];
  1233. out[1] = in1[1] + in2[1];
  1234. out[2] = in1[2] + in2[2];
  1235. }
  1236.  
  1237. stock xs_vec_sub(const Float:in1[], const Float:in2[], Float:out[])
  1238. {
  1239. out[0] = in1[0] - in2[0];
  1240. out[1] = in1[1] - in2[1];
  1241. out[2] = in1[2] - in2[2];
  1242. }
  1243.  
  1244. stock xs_vec_mul_scalar(const Float:vec[], Float:scalar, Float:out[])
  1245. {
  1246. out[0] = vec[0] * scalar;
  1247. out[1] = vec[1] * scalar;
  1248. out[2] = vec[2] * scalar;
  1249. }
  1250.  
  1251. stock Float:xs_vec_len(const Float:vec[3])
  1252. {
  1253. return floatsqroot(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
  1254. }
  1255.  
  1256. stock Float:xs_vec_dot(const Float:vec[], const Float:vec2[])
  1257. {
  1258. return (vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2])
  1259. }
  1260.  
  1261. bool:xs_vec_equal(const Float:vec1[], const Float:vec2[])
  1262. {
  1263. return (vec1[0] == vec2[0]) && (vec1[1] == vec2[1]) && (vec1[2] == vec2[2]);
  1264. }
  1265.  
  1266. stock bomb_led(const Float:point[3])
  1267. {
  1268. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  1269. write_byte(TE_GLOWSPRITE)
  1270. engfunc(EngFunc_WriteCoord, point[0])
  1271. engfunc(EngFunc_WriteCoord, point[1])
  1272. engfunc(EngFunc_WriteCoord, point[2])
  1273. write_short(spr_bomb)
  1274. write_byte(1)
  1275. write_byte(3)
  1276. write_byte(255)
  1277. message_end()
  1278. }
  1279.  
  1280. stock draw_line(const Float:start[3], const Float:end[3])
  1281. {
  1282. engfunc(EngFunc_MessageBegin, MSG_ALL, SVC_TEMPENTITY, Float:{0.0,0.0,0.0}, 0)
  1283. write_byte(TE_BEAMPOINTS)
  1284. engfunc(EngFunc_WriteCoord, start[0])
  1285. engfunc(EngFunc_WriteCoord, start[1])
  1286. engfunc(EngFunc_WriteCoord, start[2])
  1287. engfunc(EngFunc_WriteCoord, end[0])
  1288. engfunc(EngFunc_WriteCoord, end[1])
  1289. engfunc(EngFunc_WriteCoord, end[2])
  1290. write_short(beampoint)
  1291. write_byte(0)
  1292. write_byte(0)
  1293. write_byte(25)
  1294. write_byte(10)
  1295. write_byte(0)
  1296. write_byte(255)
  1297. write_byte(255)
  1298. write_byte(255)
  1299. write_byte(127)
  1300. write_byte(1)
  1301. message_end()
  1302. }