HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /* Formatleft © 2012, ConnorMcLeod
  2.  
  3. Drop All Weapons On Death 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 Drop All Weapons On Death; if not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16.  
  17. Fordította: BBk - Death of Legend
  18. */
  19.  
  20. /*
  21. a p228
  22. b scout
  23. c hegrenade
  24. d xm1014
  25. e mac10
  26. f aug
  27. g smokegrenade
  28. h elite
  29. i fiveseven
  30. j ump45
  31. k sg550
  32. l galil
  33. m famas
  34. n usp
  35. o glock18
  36. p awp
  37. q mp5navy
  38. r m249
  39. s m3
  40. t m4a1
  41. u tmp
  42. v g3sg1
  43. w flashbang
  44. x deagle
  45. x sg552
  46. z ak47
  47. { p90
  48. | defuser
  49. */
  50.  
  51. #include < amxmodx >
  52. #include < amxmisc >
  53. #include < fakemeta >
  54. #include < hamsandwich >
  55.  
  56. #pragma semicolon 1
  57.  
  58. #define VERSION "0.4.0"
  59.  
  60. const MAX_ITEM_TYPES = 6; // hud item selection slots
  61. const MAX_AMMO_SLOTS = 15; // not really slots // MAX_AMMO_SLOTS // don't need to set a 32 array since max ammo index is 14
  62.  
  63. const INT_BYTES = 4;
  64. const BYTE_BITS = 8;
  65.  
  66. // "weapon_..." offsets
  67. const XO_CBASEPLAYERITEM = 4;
  68. // CBasePlayerItem
  69. const m_pPlayer = 41;
  70. const m_pNext = 42;
  71. const m_iId = 43;
  72.  
  73. // "player" offsets
  74. // Store only slots 1,2 and 4 values cause we won't drop knife and let the game drop c4
  75. // new const m_rgpPlayerItems_plr[] = {368, 369, 371}
  76. new const m_rgpPlayerItems_CBasePlayer[6] = { 367 , 368 , ... };
  77. const m_pActiveItem = 373;
  78. new const m_rgAmmo_CBasePlayer[MAX_AMMO_SLOTS] = {376,377,...};
  79.  
  80. const m_bHasDefuser = 774;
  81.  
  82. // "weaponbox" offsets
  83. const XO_CWEAPONBOX = 4;
  84. new const m_rgpPlayerItems_CWeaponBox[MAX_ITEM_TYPES] = { 34 , 35 , ... };
  85. new const m_rgiszAmmo[32] = { 40 , 41 , ... };
  86. new const m_rgAmmo_CWeaponBox[32] = { 72 , 73 , ... };
  87. const m_cAmmoTypes = 104;
  88.  
  89. new const g_iMaxAmmo[] = {
  90. 0, 30, 90, 200, 90,
  91. 32, 100, 100, 35, 52,
  92. 120, 2, 1, 1, 1
  93. };
  94.  
  95. new const g_szOnCBasePlayer_Killed[] = "OnCBasePlayer_Killed";
  96. new const weaponbox[] = "weaponbox";
  97. new iszWeaponBox;
  98.  
  99. const NADES_BS = (1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE);
  100.  
  101. new g_iszAmmoNames[sizeof(g_iMaxAmmo)];
  102.  
  103. new g_iNoSilPluginId, g_iNoSilSetModel;
  104.  
  105. new m_usResetDecals, g_iFhPlaybackEventPost;
  106.  
  107. new g_iFhSetClientKeyValueP;
  108.  
  109. new g_iFlags;
  110.  
  111. new gmsgStatusIcon;
  112.  
  113. public plugin_init()
  114. {
  115. register_plugin("Drop All Weapons On Death", VERSION, "ConnorMcLeod");
  116.  
  117. register_event("HLTV", "Event_HLTV_New_Round", "a", "1=0", "2=0");
  118.  
  119. RegisterHam(Ham_Killed, "player", g_szOnCBasePlayer_Killed);
  120. new modname[7];
  121. get_modname(modname, charsmax(modname));
  122. if( equal(modname, "czero") )
  123. {
  124. g_iFhSetClientKeyValueP = register_forward(FM_SetClientKeyValue, "OnSetClientKeyValue_P", true);
  125. }
  126.  
  127. new const szAmmoNames[][] = {
  128. "", "338Magnum", "762Nato", "556NatoBox", "556Nato",
  129. "buckshot", "45ACP", "57mm", "50AE", "357SIG",
  130. "9mm", "Flashbang", "HEGrenade", "SmokeGrenade", "C4"
  131. };
  132.  
  133. for(new i=1; i<sizeof(szAmmoNames); i++)
  134. {
  135. g_iszAmmoNames[i] = engfunc(EngFunc_AllocString, szAmmoNames[i]);
  136. }
  137.  
  138. iszWeaponBox = engfunc(EngFunc_AllocString, weaponbox);
  139.  
  140. m_usResetDecals = engfunc(EngFunc_PrecacheEvent, 1, "events/decal_reset.sc");
  141.  
  142. gmsgStatusIcon = get_user_msgid("StatusIcon");
  143.  
  144. register_concmd("death_drop_rules", "ConCmd_Rules", ADMIN_CFG, " - <flags>");
  145. }
  146.  
  147. public plugin_cfg()
  148. {
  149. g_iNoSilPluginId = is_plugin_loaded("NoSil");
  150. if( g_iNoSilPluginId > 0 )
  151. {
  152. g_iNoSilSetModel = get_func_id("fw_setmodel", g_iNoSilPluginId);
  153. }
  154. }
  155.  
  156. public ConCmd_Rules(id, level, cid)
  157. {
  158. if( cmd_access(id, level, cid, 2) )
  159. {
  160. static const iWeaponsIds[] = {CSW_P228, CSW_SCOUT, CSW_HEGRENADE, CSW_XM1014, CSW_MAC10, CSW_AUG, CSW_SMOKEGRENADE,
  161. CSW_ELITE, CSW_FIVESEVEN, CSW_UMP45, CSW_SG550, CSW_GALIL, CSW_FAMAS, CSW_USP, CSW_GLOCK18, CSW_AWP,
  162. CSW_MP5NAVY, CSW_M249, CSW_M3, CSW_M4A1, CSW_TMP, CSW_G3SG1, CSW_FLASHBANG, CSW_DEAGLE, CSW_SG552,
  163. CSW_AK47, CSW_P90, 0};
  164.  
  165. new szFlags[sizeof(iWeaponsIds)+1];
  166. read_argv(1, szFlags, charsmax(szFlags));
  167.  
  168. new i, cLetter, iVal;
  169. g_iFlags = 0;
  170.  
  171. while( (cLetter = szFlags[i++]) )
  172. {
  173. iVal = cLetter - 'a';
  174. if( 0 <= iVal < sizeof(iWeaponsIds) )
  175. {
  176. g_iFlags |= 1 << iWeaponsIds[iVal];
  177. }
  178. }
  179. }
  180. return PLUGIN_HANDLED;
  181. }
  182.  
  183. public OnSetClientKeyValue_P(id, const key[])
  184. {
  185. if( equal(key, "*bot") )
  186. {
  187. RegisterHamFromEntity(Ham_Killed, id, g_szOnCBasePlayer_Killed);
  188. unregister_forward(FM_SetClientKeyValue, g_iFhSetClientKeyValueP, true);
  189. }
  190. }
  191.  
  192. public Event_HLTV_New_Round()
  193. {
  194. if( !g_iFhPlaybackEventPost )
  195. {
  196. g_iFhPlaybackEventPost = register_forward(FM_PlaybackEvent, "OnPlaybackEvent_Post", true);
  197. }
  198. }
  199.  
  200. // proceed here at the end of CHalfLifeMultiplay::RestartRound so other weaponbox has already been removed
  201. public OnPlaybackEvent_Post(flags, pInvoker, eventindex)
  202. {
  203. if( g_iFhPlaybackEventPost && eventindex == m_usResetDecals )
  204. {
  205. unregister_forward(FM_PlaybackEvent, g_iFhPlaybackEventPost, true);
  206. g_iFhPlaybackEventPost = 0;
  207.  
  208. new iWpnBx = FM_NULLENT;
  209.  
  210. while( (iWpnBx = engfunc(EngFunc_FindEntityByString, iWpnBx, "classname", weaponbox)) > 0 )
  211. {
  212. WeaponBox_Killed(iWpnBx);
  213. }
  214. }
  215. }
  216.  
  217. public OnCBasePlayer_Killed( id )
  218. {
  219. new iActiveItem = get_pdata_cbase(id, m_pActiveItem);
  220. if( iActiveItem > 0 && pev_valid( iActiveItem ) )
  221. {
  222. if( ~NADES_BS & (1<<get_pdata_int(iActiveItem, m_iId, XO_CBASEPLAYERITEM))
  223. || ~pev(id, pev_button) & IN_ATTACK )
  224. {
  225. ExecuteHam(Ham_Item_Holster, iActiveItem, 1);
  226. iActiveItem = 0;
  227. }
  228. }
  229. else
  230. {
  231. iActiveItem = 0; // depending on windows/linux it can be -1
  232. }
  233.  
  234. if( g_iFlags & 1<<0 && get_pdata_bool(id, m_bHasDefuser) ) // defuser
  235. {
  236. set_pdata_bool(id, m_bHasDefuser, false);
  237. set_pev(id, pev_body, 0);
  238. message_begin(MSG_ONE, gmsgStatusIcon, _, id);
  239. write_byte(0);
  240. write_string("defuser");
  241. message_end();
  242. }
  243.  
  244. new iWeapon, iWeaponBox, iAmmoId, iBpAmmo, iNextWeapon;
  245. new szWeapon[20], szModel[26];
  246. new Float:flOrigin[3], Float:flAngles[3], Float:flWpnBxVelocity[3];
  247.  
  248. pev(id, pev_origin, flOrigin);
  249. pev(id, pev_angles, flAngles);
  250.  
  251. flAngles[0] = 0.0;
  252. flAngles[2] = 0.0;
  253.  
  254. new iId;
  255. for(new i=1; i<sizeof(m_rgpPlayerItems_CBasePlayer); i++)
  256. {
  257. if( i != 1 && i != 2 && i!= 4 ) // primary, secondary, nades
  258. {
  259. continue;
  260. }
  261. iWeapon = get_pdata_cbase(id, m_rgpPlayerItems_CBasePlayer[i]);
  262. while( iWeapon > 0 && pev_valid( iWeapon ) == 2 )
  263. {
  264. iNextWeapon = get_pdata_cbase(iWeapon, m_pNext, XO_CBASEPLAYERITEM);
  265. if( i == 4
  266. && iWeapon == iActiveItem // ready to launch nade
  267. && get_pdata_int(id, m_rgAmmo_CBasePlayer[ ExecuteHam(Ham_Item_PrimaryAmmoIndex, iWeapon) ]) <= 1 )
  268. {
  269. iActiveItem = 0;
  270. iWeapon = iNextWeapon;
  271. continue;
  272. }
  273.  
  274. iWeaponBox = engfunc(EngFunc_CreateNamedEntity, iszWeaponBox);
  275.  
  276. if( pev_valid(iWeaponBox) )
  277. {
  278. set_pev(iWeaponBox, pev_owner, id);
  279.  
  280. engfunc(EngFunc_SetOrigin, iWeaponBox, flOrigin);
  281.  
  282. set_pev(iWeaponBox, pev_angles, flAngles);
  283. ExecuteHamB(Ham_Spawn, iWeaponBox);
  284.  
  285. flWpnBxVelocity[0] = random_float(-250.0,250.0);
  286. flWpnBxVelocity[1] = random_float(-250.0,250.0);
  287. set_pev(iWeaponBox, pev_velocity, flWpnBxVelocity);
  288.  
  289. iId = get_pdata_int(iWeapon, m_iId, XO_CBASEPLAYERITEM);
  290. if( !WeaponBox_PackWeapon(iWeaponBox, iWeapon, id, iId) )
  291. {
  292. set_pev(iWeaponBox, pev_flags, FL_KILLME);
  293. }
  294. else
  295. {
  296. if( !iActiveItem || iWeapon != iActiveItem )
  297. {
  298. iAmmoId = ExecuteHam(Ham_Item_PrimaryAmmoIndex, iWeapon);
  299.  
  300. iBpAmmo = get_pdata_int(id, m_rgAmmo_CBasePlayer[iAmmoId]);
  301. }
  302.  
  303. set_pdata_int(id, m_rgAmmo_CBasePlayer[iAmmoId], 0);
  304.  
  305. WeaponBox_PackAmmo(iWeaponBox, iAmmoId, i == 4 ? iBpAmmo - 1 : iBpAmmo);
  306.  
  307. pev(iWeapon, pev_classname, szWeapon, charsmax(szWeapon));
  308.  
  309. if( szWeapon[10] == 'n' ) // weapon_mp5navy
  310. {
  311. // replace(szWeapon, charsmax(szWeapon), "navy", "")
  312. szWeapon[10] = EOS;
  313. }
  314. formatex(szModel, charsmax(szModel), "models/w_%s.mdl", szWeapon[7]);
  315.  
  316. engfunc(EngFunc_SetModel, iWeaponBox, szModel);
  317.  
  318. const SILENT_WPN_BS = (1<<CSW_USP)|(1<<CSW_M4A1);
  319.  
  320. if( g_iNoSilPluginId > 0
  321. && g_iNoSilSetModel > 0
  322. && (1<<iId) & SILENT_WPN_BS )
  323. {
  324. callfunc_begin_i(g_iNoSilSetModel, g_iNoSilPluginId);
  325. callfunc_push_int(iWeaponBox);
  326. callfunc_push_str(szModel);
  327. callfunc_end();
  328. }
  329.  
  330. }
  331. }
  332.  
  333. iWeapon = iNextWeapon;
  334. }
  335. }
  336. return HAM_HANDLED;
  337. }
  338.  
  339. WeaponBox_PackWeapon(iWeaponBox, iWeapon, id, iId)
  340. {
  341. if( !ExecuteHam(Ham_RemovePlayerItem, id, iWeapon) )
  342. {
  343. return 0;
  344. }
  345.  
  346. if( g_iFlags & 1 << iId )
  347. {
  348. ExecuteHam(Ham_Item_Kill, iWeapon);
  349. user_has_weapon(id, iId, 0);
  350. return 0;
  351. }
  352.  
  353. new iWeaponSlot = ExecuteHam(Ham_Item_ItemSlot, iWeapon);
  354.  
  355. set_pdata_cbase(iWeaponBox, m_rgpPlayerItems_CWeaponBox[ iWeaponSlot ], iWeapon, XO_CWEAPONBOX);
  356. set_pdata_cbase(iWeapon, m_pNext, -1, XO_CBASEPLAYERITEM);
  357.  
  358. set_pev(iWeapon, pev_spawnflags, pev(iWeapon, pev_spawnflags) | SF_NORESPAWN);
  359. set_pev(iWeapon, pev_movetype, MOVETYPE_NONE);
  360. set_pev(iWeapon, pev_solid, SOLID_NOT);
  361. set_pev(iWeapon, pev_effects, EF_NODRAW);
  362. set_pev(iWeapon, pev_modelindex, 0);
  363. set_pev(iWeapon, pev_model, 0);
  364. set_pev(iWeapon, pev_owner, iWeaponBox);
  365. set_pdata_cbase(iWeapon, m_pPlayer, -1, XO_CBASEPLAYERITEM);
  366.  
  367. return 1;
  368. }
  369.  
  370. WeaponBox_Killed(iWpnBx)
  371. {
  372. new iWeapon;
  373. for(new i=0; i<MAX_ITEM_TYPES; i++)
  374. {
  375. iWeapon = get_pdata_cbase(iWpnBx, m_rgpPlayerItems_CWeaponBox[ i ], XO_CWEAPONBOX);
  376. if( pev_valid(iWeapon) )
  377. {
  378. set_pev(iWeapon, pev_flags, FL_KILLME);
  379. }
  380. // don't implement pNext system as it's a custom weaponbox that doesn't use it
  381. }
  382. set_pev(iWpnBx, pev_flags, FL_KILLME);
  383. }
  384.  
  385. WeaponBox_PackAmmo(iWeaponBox, iAmmoId, iCount)
  386. {
  387. if( !iCount )
  388. {
  389. return;
  390. }
  391.  
  392. new iMaxCarry = g_iMaxAmmo[iAmmoId];
  393.  
  394. if( iCount > iMaxCarry )
  395. {
  396. iCount = iMaxCarry;
  397. }
  398.  
  399. set_pdata_int(iWeaponBox, m_rgiszAmmo[0], g_iszAmmoNames[iAmmoId], XO_CWEAPONBOX);
  400. set_pdata_int(iWeaponBox, m_rgAmmo_CWeaponBox[0], iCount, XO_CWEAPONBOX);
  401. }
  402.  
  403. bool:get_pdata_bool(ent, charbased_offset, intbase_linuxdiff = 5)
  404. {
  405. return !!( get_pdata_int(ent, charbased_offset / INT_BYTES, intbase_linuxdiff) & (0xFF<<((charbased_offset % INT_BYTES) * BYTE_BITS)) );
  406. }
  407.  
  408. set_pdata_char(ent, charbased_offset, value, intbase_linuxdiff = 5)
  409. {
  410. value &= 0xFF;
  411. new int_offset_value = get_pdata_int(ent, charbased_offset / INT_BYTES, intbase_linuxdiff);
  412. new bit_decal = (charbased_offset % INT_BYTES) * BYTE_BITS;
  413. int_offset_value &= ~(0xFF<<bit_decal); // clear byte
  414. int_offset_value |= value<<bit_decal;
  415. set_pdata_int(ent, charbased_offset / INT_BYTES, int_offset_value, intbase_linuxdiff);
  416. return 1;
  417. }
  418.  
  419. set_pdata_bool(ent, charbased_offset, bool:value, intbase_linuxdiff = 5)
  420. {
  421. set_pdata_char(ent, charbased_offset, _:value, intbase_linuxdiff);
  422. }