找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 937|回复: 1

箱子不沉的插件

  [复制链接]

该用户从未签到

发表于 2010-5-31 18:25:13 | 显示全部楼层 |阅读模式
本帖最后由 kaizongjiadao 于 2010-6-1 21:41 编辑

求个箱子不沉的插件。顺便再说下怎么安装,详细点的。麻烦各位了

该用户从未签到

发表于 2010-5-31 22:47:18 | 显示全部楼层
  1. /*
  2. .: Commands :.

  3. kz_mpbhop < 0 | 1 >

  4. This enables the plugin (set block so they can't move when players touch them)

  5. Put this one on 1 in amxx.cfg in you run a bhop server, else, use per prefixes/maps

  6. config files

  7. kz_mpbhop_entitytouch < 0 | 1 >

  8. This enables entity touch detection (set block so they can't move when other entities

  9. than players touch them)

  10. Put this one on 1 in amxx.cfg in you run a bhop server, else, use per prefixes/maps

  11. config files.

  12. This feature works only if kz_mpbhop is set to 1

  13. kz_safe_inform < 0 | 1 >

  14. Inform recorders that their demo will be safe or not safe according to plugin state

  15. kz_showblocks < 0 | 1 >

  16. This make non-movable block transparent and colored so you can quickly notice them.

  17. This is high consuming, so enable it only to config the plugin

  18. kz_mpbhopmenu

  19. To open the menu and set a block, aim the block to make this cmd work.

  20. Then use the menu options to set the block.

  21. */

  22. #include <amxmodx>
  23. #include <amxmisc>
  24. #include <fakemeta>
  25. #include <hamsandwich>
  26. #include <xs>

  27. #define VERSION "1.0.2"

  28. #pragma semicolon 1

  29. #define MAKE_DOORS_SILENT
  30. //#define MAKE_TELEPORT_FX

  31. #define MAX_PLAYERS 32

  32. const MAX_ENTS = 900 + MAX_PLAYERS * 15;
  33. const MAX_ENTSARRAYS_SIZE = (MAX_ENTS / 32) + _:!!(MAX_ENTS % 32);

  34. #define SF_BUTTON_TOUCH_ONLY 256

  35. #define SetIdBits(%1,%2) %1 |= 1<<(%2 & 31)
  36. #define ClearIdBits(%1,%2) %1 &= ~( 1<<(%2 & 31) )
  37. #define GetIdBits(%1,%2) %1 & 1<<(%2 & 31)

  38. #define SetEntBits(%1,%2) %1[%2>>5] |= 1<<(%2 & 31)
  39. #define ClearEntBits(%1,%2) %1[%2>>5] &= ~( 1 << (%2 & 31) )
  40. #define GetEntBits(%1,%2) %1[%2>>5] & 1<<(%2 & 31)

  41. enum _:BlocksClasses
  42. {
  43. FUNC_DOOR,
  44. FUNC_WALL_TOGGLE,
  45. FUNC_BUTTON,
  46. TRIGGER_MULTIPLE
  47. }

  48. enum _:Colors {
  49. DONT_CHANGE,
  50. TERRORIST,
  51. CT,
  52. SPECTATOR
  53. }

  54. new g_bitPresentClass;

  55. const KEYS = ((1<<0)|(1<<1)|(1<<9));

  56. const FL_ONGROUND2 = (FL_ONGROUND | FL_PARTIALGROUND | FL_INWATER | FL_CONVEYOR | FL_FLOAT);

  57. new g_iBlock[MAX_PLAYERS+1];
  58. new Float:g_flFirstTouch[MAX_PLAYERS+1];

  59. new Float:g_flJumpOrigin[MAX_PLAYERS+1][3];
  60. new Float:g_flJumpAnglesGravity[MAX_PLAYERS+1][3];

  61. new g_bBlocks[MAX_ENTSARRAYS_SIZE], g_bBlocksByPlugin[MAX_ENTSARRAYS_SIZE], g_bBlocksByFile[MAX_ENTSARRAYS_SIZE];
  62. new g_bAlives, g_bOnGround, g_bTeleported, g_bAdmin;

  63. new bool:g_bBlockEntityTouch;
  64. new bool:g_bActive;
  65. new bool:g_bSafeInform = true;

  66. new g_iFhAddToFullPack;
  67. new g_iAdminDoor[MAX_PLAYERS+1];
  68. new szConfigFile[64];

  69. new Trie:g_iBlocksClass;

  70. new g_iMaxPlayers, g_iMaxEnts;
  71. #define IsPlayer(%1) ( 1 <= %1 <= g_iMaxPlayers )

  72. public plugin_init()
  73. {
  74. register_plugin("MultiPlayer Bhop", VERSION, "ConnorMcLeod");
  75. new pCvar = register_cvar("mp_bhop_version", VERSION, FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_SPONLY);
  76. set_pcvar_string(pCvar, VERSION);

  77. new const szPossibleBlockClass[][] = {"func_door", "func_wall_toggle", "func_button", "trigger_multiple"};
  78. g_iBlocksClass = TrieCreate();
  79. for(new i; i<sizeof(szPossibleBlockClass); i++)
  80. {
  81. TrieSetCell(g_iBlocksClass, szPossibleBlockClass[i], i);
  82. }

  83. register_event("Health", "Event_Health", "b");
  84. register_event("ResetHUD", "Event_ResetHUD", "b");

  85. register_concmd("kz_mpbhop", "ConsoleCommand_MpBhop", ADMIN_CFG, "<0/1>");
  86. register_concmd("kz_mpbhop_entitytouch", "ConsoleCommand_EntityTouch", ADMIN_CFG, "<0/1>");
  87. register_concmd("kz_safe_inform", "ConsoleCommand_SafeInform", ADMIN_CFG, "<0/1>");

  88. register_clcmd("kz_mpbhopmenu", "ClientCommand_BhopMenu", ADMIN_CFG);
  89. register_clcmd("kz_showblocks", "ClientCommand_ShowBlocks", ADMIN_CFG);


  90. register_clcmd("fullupdate", "ClientCommand_FullUpdate");

  91. register_menucmd(register_menuid("MpBhop Menu"), KEYS ,"MpBhopMenuAction");

  92. g_iMaxPlayers = get_maxplayers();
  93. g_iMaxEnts = global_get(glb_maxEntities);

  94. Set_Doors();
  95. Set_Wall_Toggle();
  96. Set_Buttons();

  97. SetBlocksByFile();

  98. SetTriggerMultiple();
  99. }

  100. public ClientCommand_FullUpdate( id )
  101. {
  102. if( g_bSafeInform )
  103. {
  104. if( g_bActive )
  105. {
  106. client_print(id, print_console, "MpBhop is Activated, recording is NOT SAFE");
  107. ColorChat(id, TERRORIST, "^1 * ^4[MpBhop] ^1MpBhop is ^4Activated^1, recording is ^3NOT SAFE");
  108. }
  109. else
  110. {
  111. client_print(id, print_console, "MpBhop is De-Activated, recording is SAFE");
  112. ColorChat(id, TERRORIST, "^1 * ^4[MpBhop] ^1MpBhop is ^3De-Activated^1, recording is ^4SAFE");
  113. }
  114. }
  115. }

  116. public ConsoleCommand_SafeInform(id, lvl, cid)
  117. {
  118. if( cmd_access(id, lvl, cid, 2) )
  119. {
  120. new szStatus[2];
  121. read_argv(1, szStatus, charsmax(szStatus));
  122. g_bSafeInform = !!str_to_num(szStatus);
  123. }
  124. return PLUGIN_HANDLED;
  125. }

  126. public client_putinserver(id)
  127. {
  128. if( get_user_flags(id) & ADMIN_CFG )
  129. {
  130. SetIdBits(g_bAdmin, id);
  131. }
  132. else
  133. {
  134. ClearIdBits(g_bAdmin, id);
  135. }
  136. ClearIdBits(g_bAlives, id);
  137. ClearIdBits(g_bOnGround, id);
  138. ClearIdBits(g_bTeleported, id);
  139. }

  140. public client_disconnect(id)
  141. {
  142. ClearIdBits(g_bAdmin, id);
  143. ClearIdBits(g_bAlives, id);
  144. ClearIdBits(g_bOnGround, id);
  145. ClearIdBits(g_bTeleported, id);
  146. }

  147. public ClientCommand_ShowBlocks(id, level, cid)
  148. {
  149. if( cmd_access(id, level, cid, 2) )
  150. {
  151. new szStatus[2];
  152. read_argv(1, szStatus, charsmax(szStatus));
  153. if( szStatus[0] == '1' )
  154. {
  155. if( !g_iFhAddToFullPack )
  156. {
  157. g_iFhAddToFullPack = register_forward(FM_AddToFullPack, "AddToFullPack", 1);
  158. client_print(id, print_console, "Recording with this feature Activated is NOT SAFE");
  159. ColorChat(id, TERRORIST, "^1 * ^4[MpBhop] ^1Recording with this feature ^4Activated ^1is ^3NOT SAFE");
  160. }
  161. }
  162. else
  163. {
  164. if( g_iFhAddToFullPack )
  165. {
  166. unregister_forward(FM_AddToFullPack, g_iFhAddToFullPack, 1);
  167. g_iFhAddToFullPack = 0;
  168. }
  169. }
  170. }
  171. return PLUGIN_HANDLED;
  172. }

  173. public MpBhopMenuAction(id, iKey)
  174. {
  175. new iEnt = g_iAdminDoor[id];

  176. switch( iKey )
  177. {
  178. case 0:
  179. {
  180. if( GetEntBits(g_bBlocks, iEnt) )
  181. {
  182. ClearEntBits(g_bBlocks, iEnt);
  183. SetEntBits(g_bBlocksByFile, iEnt);
  184. ColorChat(id, _, "^1 * ^4[MpBhop] ^1Block has been set ^4movable^1.");
  185. }
  186. else
  187. {
  188. ColorChat(id, _, "^1 * ^4[MpBhop] ^1Block is already ^4movable^1.");
  189. }
  190. }
  191. case 1:
  192. {
  193. if( GetEntBits(g_bBlocks, iEnt) )
  194. {
  195. ColorChat(id, TERRORIST, "^1 * ^4[MpBhop] ^1Block is already ^3unmovable^1.");
  196. }
  197. else
  198. {
  199. SetEntBits(g_bBlocks, iEnt);
  200. SetEntBits(g_bBlocksByFile, iEnt);
  201. ColorChat(id, TERRORIST, "^1 * ^4[MpBhop] ^1Block has been set ^3unmovable^1.");
  202. }
  203. }
  204. }
  205. return PLUGIN_HANDLED;
  206. }

  207. ShowMpBhopMenu(id, bIsBlocked)
  208. {
  209. new szMenuBody[150];

  210. formatex(szMenuBody, charsmax(szMenuBody), "\rMpBhop Menu^n\dThis block is actually \
  211. \y%smovable \d:^n^n\r1\w. Mark this block as movable^n\r2\w. Mark this block as \
  212. unmovable^n^n\r0\w. Exit", bIsBlocked ? "un" : "");

  213. show_menu(id, KEYS, szMenuBody, _, "MpBhop Menu");
  214. }

  215. public ClientCommand_BhopMenu(id, level, cid)
  216. {
  217. if( cmd_access(id, level, cid, 1) )
  218. {
  219. new iEnt, crap, iClassType;
  220. get_user_aiming(id, iEnt, crap);
  221. if( iEnt && pev_valid(iEnt) )
  222. {
  223. new szClassName[32];
  224. pev(iEnt, pev_classname, szClassName, charsmax(szClassName));
  225. if( TrieGetCell(g_iBlocksClass, szClassName, iClassType) )
  226. {
  227. g_bitPresentClass |= 1<<iClassType;
  228. g_iAdminDoor[id] = iEnt;
  229. ShowMpBhopMenu(id, !!(GetEntBits(g_bBlocks, iEnt)));
  230. }
  231. }
  232. }
  233. return PLUGIN_HANDLED;
  234. }

  235. public AddToFullPack(es, e, iEnt, id, hostflags, player, pSet)
  236. {
  237. if( !player && GetIdBits(g_bAdmin, id) && GetEntBits(g_bBlocks, iEnt) )
  238. {
  239. set_es(es, ES_RenderMode, kRenderTransColor);
  240. set_es(es, ES_RenderAmt, 150);
  241. set_es(es, ES_RenderColor, {120,75,170});
  242. set_es(es, ES_RenderFx, kRenderFxGlowShell);
  243. }
  244. }

  245. public Event_Health(id)
  246. {
  247. if( is_user_alive(id) )
  248. {
  249. SetIdBits(g_bAlives, id);
  250. }
  251. else
  252. {
  253. ClearIdBits(g_bAlives, id);
  254. }
  255. }

  256. public Event_ResetHUD(id)
  257. {
  258. if( is_user_alive(id) )
  259. {
  260. SetIdBits(g_bAlives, id);
  261. }
  262. else
  263. {
  264. ClearIdBits(g_bAlives, id);
  265. }
  266. }

  267. public CBasePlayer_PreThink(id)
  268. {
  269. if( GetIdBits(g_bAlives, id) )
  270. {
  271. if( GetIdBits(g_bTeleported, id) )
  272. {
  273. ClearIdBits(g_bTeleported, id);
  274. set_pev(id, pev_velocity, 0);
  275. return;
  276. }

  277. static fFlags;
  278. fFlags = pev(id, pev_flags);
  279. if( fFlags & FL_ONGROUND )
  280. {
  281. static iEnt, Float:flVelocity[3], Float:flVecOrigin[3];
  282. iEnt = pev(id, pev_groundentity);
  283. if( !iEnt || !(GetEntBits(g_bBlocks, iEnt)) )
  284. {
  285. if( iEnt )
  286. {
  287. pev(iEnt, pev_velocity, flVelocity);
  288. if( flVelocity[0] || flVelocity[1] || flVelocity[2] )
  289. {
  290. ClearIdBits(g_bOnGround, id);
  291. return;
  292. }
  293. }

  294. if( fFlags & FL_DUCKING )
  295. {
  296. pev(id, pev_origin, flVecOrigin);
  297. flVecOrigin[2] += 18.0;
  298. engfunc(EngFunc_TraceHull, flVecOrigin, flVecOrigin, IGNORE_MONSTERS, HULL_HUMAN, id, 0);
  299. if( !get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen) )
  300. {
  301. flVecOrigin[2] -= 18.0;
  302. xs_vec_copy(flVecOrigin, g_flJumpOrigin[id]);
  303. SetIdBits(g_bOnGround, id);
  304. }
  305. else
  306. {
  307. ClearIdBits(g_bOnGround, id);
  308. return;
  309. }
  310. }
  311. else
  312. {
  313. pev(id, pev_origin, g_flJumpOrigin[id]);
  314. SetIdBits(g_bOnGround, id);
  315. }
  316. }
  317. else
  318. {
  319. ClearIdBits(g_bOnGround, id);
  320. }
  321. }
  322. else if( GetIdBits(g_bOnGround, id) )
  323. {
  324. ClearIdBits(g_bOnGround, id);
  325. pev(id, pev_v_angle, g_flJumpAnglesGravity[id]);
  326. pev(id, pev_gravity, g_flJumpAnglesGravity[id][2]);
  327. }
  328. }
  329. }

  330. public TriggerMultiple_Touch(iEnt, id)
  331. {
  332. if( (IsPlayer(id) || g_bBlockEntityTouch) && GetEntBits(g_bBlocks, iEnt) )
  333. {
  334. return HAM_SUPERCEDE;
  335. }
  336. return HAM_IGNORED;
  337. }

  338. public Touch_Block(iBlock, id)
  339. {
  340. if( !(GetEntBits(g_bBlocks, iBlock)) )
  341. {
  342. return HAM_IGNORED;
  343. }

  344. if( IsPlayer(id) )
  345. {
  346. if( ~GetIdBits(g_bAlives, id) )
  347. {
  348. return HAM_SUPERCEDE;
  349. }
  350. }
  351. else
  352. {
  353. return g_bBlockEntityTouch ? HAM_SUPERCEDE : HAM_IGNORED;
  354. }

  355. if( pev(id, pev_groundentity) != iBlock )
  356. {
  357. return HAM_SUPERCEDE;
  358. }

  359. if( g_iBlock[id] != iBlock )
  360. {
  361. g_iBlock[id] = iBlock;
  362. g_flFirstTouch[id] = get_gametime();
  363. return HAM_SUPERCEDE;
  364. }

  365. static Float:flTime;
  366. flTime = get_gametime();

  367. if( flTime - g_flFirstTouch[id] > 0.25 ) // 0.3 == exploit on cg_cbblebhop oO
  368. {
  369. if( flTime - g_flFirstTouch[id] > 0.7 )
  370. {
  371. g_flFirstTouch[id] = flTime;
  372. return HAM_SUPERCEDE;
  373. }

  374. #if defined MAKE_TELEPORT_FX
  375. new iOrigin[3];
  376. get_user_origin(id, iOrigin);
  377. message_begin(MSG_PVS, SVC_TEMPENTITY, iOrigin);
  378. write_byte(TE_TELEPORT);
  379. write_coord(iOrigin[0]);
  380. write_coord(iOrigin[1]);
  381. write_coord(iOrigin[2]);
  382. message_end();
  383. #endif
  384. static const Float:VEC_DUCK_HULL_MIN[3] = {-16.0, -16.0, -18.0 };
  385. static const Float:VEC_DUCK_HULL_MAX[3] = { 16.0, 16.0, 32.0 };
  386. static const Float:VEC_DUCK_VIEW[3] = { 0.0, 0.0, 12.0 };

  387. set_pev(id, pev_flags, pev(id, pev_flags) | FL_DUCKING);
  388. engfunc(EngFunc_SetSize, id, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX);
  389. engfunc(EngFunc_SetOrigin, id, g_flJumpOrigin[id]);
  390. set_pev(id, pev_view_ofs, VEC_DUCK_VIEW);

  391. set_pev(id, pev_v_angle, 0);
  392. set_pev(id, pev_velocity, 0);
  393. set_pev(id, pev_angles, g_flJumpAnglesGravity[id]);
  394. set_pev(id, pev_punchangle, 0);
  395. set_pev(id, pev_fixangle, 1);
  396. set_pev(id, pev_gravity, g_flJumpAnglesGravity[id][2]);

  397. SetIdBits(g_bTeleported, id);
  398. }
  399. return HAM_SUPERCEDE;
  400. }

  401. public ConsoleCommand_MpBhop(id, lvl, cid)
  402. {
  403. if( cmd_access(id, lvl, cid, 2) )
  404. {
  405. new szStatus[2];
  406. read_argv(1, szStatus, charsmax(szStatus));
  407. static HamHook:iHhPlayerPreThink;
  408. switch( szStatus[0] )
  409. {
  410. case '0':
  411. {
  412. if( !g_bActive )
  413. {
  414. return PLUGIN_HANDLED;
  415. }
  416. if( iHhPlayerPreThink )
  417. {
  418. DisableHamForward( iHhPlayerPreThink );
  419. }
  420. SetTouch( false );
  421. g_bActive = false;

  422. if( g_bSafeInform )
  423. {
  424. client_print(0, print_console, "MpBhop has been De-Activated, recording is now SAFE");
  425. ColorChat(0, TERRORIST, "^1 * ^4[MpBhop] ^1MpBhop has been ^3De-Activated^1, recording is now ^4SAFE");
  426. }
  427. }
  428. case '1':
  429. {
  430. if( g_bActive )
  431. {
  432. return PLUGIN_HANDLED;
  433. }
  434. if( !iHhPlayerPreThink )
  435. {
  436. RegisterHam(Ham_Player_PreThink, "player", "CBasePlayer_PreThink");
  437. }
  438. else
  439. {
  440. EnableHamForward( iHhPlayerPreThink );
  441. }
  442. SetTouch( true );
  443. g_bActive = true;
  444. if( g_bSafeInform )
  445. {
  446. client_print(0, print_console, "MpBhop has been Activated, recording is now NOT SAFE");
  447. ColorChat(0, TERRORIST, "^1 * ^4[MpBhop] ^1MpBhop has been ^4Activated^1, recording is now ^3NOT SAFE");
  448. }
  449. }
  450. default:
  451. {
  452. client_print(id, print_console, "Usage: kz_mpbhop <0/1>");
  453. }
  454. }
  455. }
  456. return PLUGIN_HANDLED;
  457. }

  458. public ConsoleCommand_EntityTouch(id, lvl, cid)
  459. {
  460. if( cmd_access(id, lvl, cid, 2) )
  461. {
  462. new szStatus[2];
  463. read_argv(1, szStatus, charsmax(szStatus));
  464. g_bBlockEntityTouch = !!str_to_num(szStatus);
  465. }
  466. return PLUGIN_HANDLED;
  467. }

  468. Set_Doors()
  469. {
  470. new iDoor = FM_NULLENT;
  471. new Float:flMovedir[3], szNoise[32], Float:flSize[3], Float:flDmg, Float:flSpeed;
  472. new const szNull[] = "common/null.wav";
  473. while( (iDoor = engfunc(EngFunc_FindEntityByString, iDoor, "classname", "func_door")) )
  474. {
  475. // definitly not a bhop block
  476. pev(iDoor, pev_dmg, flDmg);
  477. if( flDmg )
  478. {
  479. #if defined MAKE_DOORS_SILENT
  480. set_pev(iDoor, pev_noise1, szNull); // while here, set healing doors silent xD
  481. set_pev(iDoor, pev_noise2, szNull);
  482. set_pev(iDoor, pev_noise3, szNull);
  483. #endif
  484. continue;
  485. }

  486. // this func_door goes UP, not a bhop block ?
  487. // or bhop block but let them move up (kz_megabhop for example)
  488. pev(iDoor, pev_movedir, flMovedir);
  489. if( flMovedir[2] > 0.0 )
  490. {
  491. continue;
  492. }

  493. // too small : real door ? could this one be skipped ?
  494. pev(iDoor, pev_size, flSize);
  495. if( flSize[0] < 24.0 || flSize[1] < 24.0 )
  496. {
  497. continue;
  498. }

  499. // real door ? not all doors make sound though...
  500. pev(iDoor, pev_noise1, szNoise, charsmax(szNoise));
  501. if( szNoise[0] && !equal(szNoise, szNull) )
  502. {
  503. continue;
  504. }
  505. pev(iDoor, pev_noise2, szNoise, charsmax(szNoise));
  506. if( szNoise[0] && !equal(szNoise, szNull) )
  507. {
  508. continue;
  509. }

  510. // not a bhop block ? too slow // this at least detects the big ent on kzsca_sewerbhop
  511. pev(iDoor, pev_speed, flSpeed);
  512. if( flSpeed < 100.0 )
  513. {
  514. continue;
  515. }

  516. // Pray for this to be a bhop block
  517. SetEntBits(g_bBlocksByPlugin, iDoor);
  518. SetEntBits(g_bBlocks, iDoor);
  519. g_bitPresentClass |= 1<<FUNC_DOOR;
  520. }
  521. }

  522. Set_Wall_Toggle()
  523. {
  524. new iEnt = FM_NULLENT;
  525. while( (iEnt = engfunc(EngFunc_FindEntityByString, iEnt, "classname", "func_wall_toggle")) )
  526. {
  527. g_bitPresentClass |= 1<<FUNC_WALL_TOGGLE;
  528. SetEntBits(g_bBlocksByPlugin, iEnt);
  529. SetEntBits(g_bBlocks, iEnt);
  530. }
  531. }

  532. Set_Buttons()
  533. {
  534. new const szStartStopButtons[][] = {"counter_start", "clockstartbutton", "firsttimerelay", "multi_start",
  535. "counter_start_button", "counter_off", "clockstop", "clockstopbutton", "multi_stop", "stop_counter" };

  536. new Trie:tButtons = TrieCreate();

  537. for(new i; i<sizeof(szStartStopButtons); i++)
  538. {
  539. TrieSetCell(tButtons, szStartStopButtons[i], 1);
  540. }

  541. new iEnt = FM_NULLENT, szTarget[32];
  542. while( (iEnt = engfunc(EngFunc_FindEntityByString, iEnt, "classname", "func_button")) )
  543. {
  544. if( pev(iEnt, pev_spawnflags) & SF_BUTTON_TOUCH_ONLY )
  545. {
  546. pev(iEnt, pev_target, szTarget, charsmax(szTarget));
  547. if( !szTarget[0] || !TrieKeyExists(tButtons, szTarget))
  548. {
  549. pev(iEnt, pev_targetname, szTarget, charsmax(szTarget));
  550. if( !szTarget[0] || !TrieKeyExists(tButtons, szTarget))
  551. {
  552. g_bitPresentClass |= 1<<FUNC_BUTTON;
  553. SetEntBits(g_bBlocksByPlugin, iEnt);
  554. SetEntBits(g_bBlocks, iEnt);
  555. }
  556. }
  557. }
  558. }
  559. TrieDestroy(tButtons);
  560. }

  561. SetTouch(bool:bActive)
  562. {
  563. static HamHook:iHhBlockTouch[BlocksClasses];
  564. if( bActive )
  565. {
  566. static const szClassesAndHandlers[BlocksClasses][][] = {
  567. {"func_door", "Touch_Block"},
  568. {"func_wall_toggle", "Touch_Block"},
  569. {"func_button", "Touch_Block"},
  570. {"trigger_multiple", "TriggerMultiple_Touch"}
  571. };
  572. for(new i; i<sizeof(iHhBlockTouch); i++)
  573. {
  574. if( g_bitPresentClass & (1<<i) )
  575. {
  576. if( iHhBlockTouch[i] )
  577. {
  578. EnableHamForward( iHhBlockTouch[i] );
  579. }
  580. else
  581. {
  582. iHhBlockTouch[i] = RegisterHam(Ham_Touch, szClassesAndHandlers[i][0], szClassesAndHandlers[i][1]);
  583. }
  584. }
  585. }
  586. }
  587. else
  588. {
  589. for(new i; i<sizeof(iHhBlockTouch); i++)
  590. {
  591. if( g_bitPresentClass & (1<<i) && iHhBlockTouch[i] )
  592. {
  593. DisableHamForward( iHhBlockTouch[i] );
  594. }
  595. }
  596. }
  597. }

  598. SetBlocksByFile()
  599. {
  600. get_localinfo("amxx_datadir", szConfigFile, charsmax(szConfigFile));
  601. format(szConfigFile, charsmax(szConfigFile), "%s/mpbhop", szConfigFile);
  602. if( !dir_exists(szConfigFile) )
  603. {
  604. mkdir(szConfigFile);
  605. }

  606. new szMapName[32];
  607. get_mapname(szMapName, charsmax(szMapName));
  608. format(szConfigFile, charsmax(szConfigFile), "%s/%s.dat", szConfigFile, szMapName);

  609. new iFile = fopen(szConfigFile, "rt");
  610. if( iFile )
  611. {
  612. new szDatas[48], szBrushOrigin[3][13], szType[2], Float:flBrushOrigin[3], i, iEnt;
  613. new szClassName[32], iClassType;
  614. while( !feof(iFile) )
  615. {
  616. fgets(iFile, szDatas, charsmax(szDatas));
  617. trim(szDatas);
  618. if(!szDatas[0] || szDatas[0] == ';' || szDatas[0] == '#' || (szDatas[0] == '/' && szDatas[1] == '/'))
  619. {
  620. continue;
  621. }

  622. parse(szDatas, szBrushOrigin[0], 12, szBrushOrigin[1], 12, szBrushOrigin[2], 12, szType, charsmax(szType));
  623. for(i=0; i<3; i++)
  624. {
  625. flBrushOrigin[i] = str_to_float( szBrushOrigin[i] );
  626. }

  627. iEnt = FindEntByBrushOrigin( flBrushOrigin );
  628. if( iEnt )
  629. {
  630. if( szType[0] == '1' )
  631. {
  632. pev(iEnt, pev_classname, szClassName, charsmax(szClassName));
  633. if( TrieGetCell(g_iBlocksClass, szClassName, iClassType) )
  634. {
  635. g_bitPresentClass |= iClassType;
  636. }
  637. SetEntBits(g_bBlocks, iEnt);
  638. }
  639. else
  640. {
  641. ClearEntBits(g_bBlocks, iEnt);
  642. }
  643. SetEntBits(g_bBlocksByFile, iEnt);
  644. }
  645. }
  646. fclose(iFile);
  647. }
  648. }

  649. FindEntByBrushOrigin(Float:flOrigin[3])
  650. {
  651. new Float:flBrushOrigin[3];
  652. for( new iEnt=g_iMaxPlayers+1; iEnt<=g_iMaxEnts; iEnt++ )
  653. {
  654. if( pev_valid(iEnt) )
  655. {
  656. fm_get_brush_entity_origin(iEnt, flBrushOrigin);
  657. if( xs_vec_nearlyequal(flBrushOrigin, flOrigin) )
  658. {
  659. return iEnt;
  660. }
  661. }
  662. }
  663. return 0;
  664. }

  665. fm_get_brush_entity_origin(ent, Float:orig[3])
  666. {
  667. new Float:Min[3], Float:Max[3];

  668. pev(ent, pev_origin, orig);
  669. pev(ent, pev_mins, Min);
  670. pev(ent, pev_maxs, Max);

  671. orig[0] += (Min[0] + Max[0]) * 0.5;
  672. orig[1] += (Min[1] + Max[1]) * 0.5;
  673. orig[2] += (Min[2] + Max[2]) * 0.5;

  674. return 1;
  675. }

  676. SetTriggerMultiple()
  677. {
  678. new iEnt = FM_NULLENT, szTarget[32], iBlock;
  679. while( (iEnt = engfunc(EngFunc_FindEntityByString, iEnt, "classname", "trigger_multiple")) )
  680. {
  681. pev(iEnt, pev_target, szTarget, charsmax(szTarget));
  682. iBlock = engfunc(EngFunc_FindEntityByString, -1, "targetname", szTarget);
  683. if( iBlock && GetEntBits(g_bBlocks, iBlock) )
  684. {
  685. g_bitPresentClass |= 1<<TRIGGER_MULTIPLE;
  686. SetEntBits(g_bBlocksByPlugin, iEnt);
  687. SetEntBits(g_bBlocks, iEnt);
  688. }
  689. }
  690. }

  691. public plugin_end()
  692. {
  693. TrieDestroy(g_iBlocksClass);
  694. delete_file(szConfigFile);

  695. new iFile;

  696. new Float:flBrushOrigin[3], iUnMovable;
  697. for(new iEnt=g_iMaxPlayers+1; iEnt<=g_iMaxEnts; iEnt++)
  698. {
  699. if( GetEntBits(g_bBlocksByFile, iEnt) && pev_valid(iEnt) )
  700. {
  701. iUnMovable = ( GetEntBits(g_bBlocks, iEnt) );
  702. if( !!iUnMovable
  703. != !!( GetEntBits(g_bBlocksByPlugin, iEnt) ) )
  704. {
  705. if( !iFile )
  706. {
  707. iFile = fopen(szConfigFile, "wt");
  708. }
  709. fm_get_brush_entity_origin(iEnt, flBrushOrigin);
  710. fprintf(iFile, "%f %f %f %d^n",
  711. flBrushOrigin[0], flBrushOrigin[1], flBrushOrigin[2], !!iUnMovable);
  712. }
  713. }
  714. }
  715. if( iFile )
  716. {
  717. fclose( iFile );
  718. }
  719. }

  720. ColorChat(id, COLOR=DONT_CHANGE, fmt[], any:...)
  721. {
  722. new szMsg[192];
  723. szMsg[0] = 0x04;
  724. vformat(szMsg[1], charsmax(szMsg)-1, fmt, 4);

  725. new szTeam[11], MSG_DEST = id ? MSG_ONE : MSG_ALL;

  726. static const szTeamNames[Colors][] = {"", "TERRORIST", "CT", "SPECTATOR"};

  727. if( COLOR )
  728. {
  729. Send_TeamInfo(id, szTeamNames[COLOR], MSG_DEST);
  730. }

  731. static iSayText;

  732. if( iSayText || (iSayText = get_user_msgid("SayText")) )
  733. {
  734. message_begin(MSG_DEST, iSayText, _, id);
  735. {
  736. write_byte(id ? id : g_iMaxPlayers);
  737. write_string(szMsg);
  738. }
  739. message_end();
  740. }

  741. if( COLOR )
  742. {
  743. if( id || is_user_connected(g_iMaxPlayers) )
  744. {
  745. get_user_team(id ? id : g_iMaxPlayers, szTeam, charsmax(szTeam));
  746. Send_TeamInfo(id, szTeam, MSG_DEST);
  747. }
  748. else
  749. {
  750. Send_TeamInfo(0, "UNASSIGNED", MSG_DEST);
  751. }
  752. }
  753. }

  754. Send_TeamInfo(const id, const szTeam[], MSG_DEST)
  755. {
  756. static iTeamInfo;
  757. if( iTeamInfo || (iTeamInfo = get_user_msgid("TeamInfo")) )
  758. {
  759. message_begin(MSG_DEST, iTeamInfo, _, id);
  760. {
  761. write_byte(id ? id : g_iMaxPlayers);
  762. write_string(szTeam);
  763. }
  764. message_end();
  765. }
  766. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表