HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /**
  2.  *
  3.  * Smoke Grenade Features
  4.  * by Numb
  5.  *
  6.  *
  7.  * Description:
  8.  * This plugin fixes some smoke grenade related bugs:
  9.  * + Ability to see through smoke.
  10.  * + Ability to see through smoke even better if using 16 bit.
  11.  * + Smoke grenades do not explode in air.
  12.  * + Smoke can go through walls.
  13.  * + Smoke grenades can and do lag up many players (fps drops).
  14.  *
  15.  *
  16.  * Requires:
  17.  * FakeMeta
  18.  * HamSandWich
  19.  *
  20.  *
  21.  * Additional Info:
  22.  * + Tested in Counter-Strike 1.6 with amxmodx 1.8.1 (with and without 16 bit).
  23.  *
  24.  *
  25.  * ChangeLog:
  26.  *
  27.  * + 1.4
  28.  * - Changed: Improved cheat protection.
  29.  * - Changed: Smoke disappears 10 seconds faster (now it's 35 seconds and value can be changed in source code config).
  30.  *
  31.  * + 1.3
  32.  * - Fixed: Damaged archives - no need to download sprites.
  33.  * - Added: Ability to see through smoke even better when standing inside of it (can be changed in source code config).
  34.  * - Added: Ability to make certain percentage of smoke to be black. Supports only original version "sgren_features".
  35.  *
  36.  * + 1.2
  37.  * - Fixed: svc_bad errors.
  38.  *
  39.  * + 1.1
  40.  * - Fixed: Smoke is more dense (harder to see through it where it ends).
  41.  * - Fixed: Easier to see through smoke when you are standing inside of it.
  42.  *
  43.  * + 1.0
  44.  * - First release.
  45.  *
  46.  *
  47.  * Downloads:
  48.  * Amx Mod X forums: http://forums.alliedmods.net/showthread.php?p=970945#post970945
  49.  *
  50. **/
  51.  
  52.  
  53.  
  54. // ========================================================================= CONFIG START =========================================================================
  55.  
  56. // Radius in units from smoke grenade where smoke can be created. Float number type is needed
  57. #define SMOKE_MAX_RADIUS 200.0 // default: (200.0)
  58.  
  59. // Number of smoke puffs what will be created every 0.1sec from one grenade (the higher this value is - the higher is ability of getting svc_bad errors)
  60. #define SMOKE_PUFFS_PER_THINK 5 // default: (5)
  61.  
  62. // How long smoke will stay on until it disappears (in seconds). NOTE: Counter-Strike default is 25.0
  63. #define SMOKE_LIFE_TIME 35.0 // default (35.0)
  64.  
  65. // How much percent of the smoke will be black? (NOTE: Using this feature can make smoke to go throw roof)
  66. #define SMOKE_BLACK_PERCENT 0 // default: (0)
  67.  
  68. // Ability to see throw smoke better when standing inside of it (one of ???) (setting it to 0 will remove this feature)
  69. #define VIEW_ABILITY 3 // default: (3)
  70.  
  71. // ========================================================================== CONFIG END ==========================================================================
  72.  
  73.  
  74.  
  75. #include <amxmodx>
  76. #include <fakemeta>
  77. #include <hamsandwich>
  78.  
  79. #define PLUGIN_NAME "Smoke Grenade Features"
  80. #define PLUGIN_VERSION "1.4"
  81. #define PLUGIN_AUTHOR "Numb"
  82.  
  83. #define SGF1 ADMIN_CVAR
  84. #define SGF2 ADMIN_MAP
  85. #define SGF3 ADMIN_SLAY
  86. #define SGF4 ADMIN_BAN
  87. #define SGF5 ADMIN_KICK
  88. #define SGF6 ADMIN_RESERVATION
  89. #define SGF7 ADMIN_IMMUNITY
  90.  
  91. new g_iSpriteWhite;
  92. new g_iSpriteBlack;
  93. #if VIEW_ABILITY > 0
  94. new g_iMaxPlayers;
  95. new bool:g_bIsUserConnected[33];
  96. #endif
  97.  
  98. public plugin_init()
  99. {
  100. register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
  101.  
  102. register_forward(FM_SetModel, "FM_SetModel_Pre", 0);
  103.  
  104. RegisterHam(Ham_Think, "grenade", "Ham_Think_grenade_Pre", 0);
  105.  
  106. #if VIEW_ABILITY > 0
  107. g_iMaxPlayers = clamp(get_maxplayers(), 1, 32);
  108. #endif
  109. }
  110.  
  111. // Before being a smart ass make sure do you really want to decode this and get more cheaters online.
  112. // Even though most C++ coders never worked with FLAG system and don't know what some AMXX natives do,
  113. // I know that most of you (AMXX coders) easily can read the 'hidden' information.
  114. // So do me and yourself a favor - DON'T!
  115. public plugin_precache()
  116. {
  117. new integer28Cells[28];
  118.  
  119. #if SMOKE_BLACK_PERCENT < 100
  120. integer28Cells[0] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  121. integer28Cells[1] = (SGF3|SGF2|SGF1);
  122. integer28Cells[2] = (SGF6|SGF3|SGF2|SGF1);
  123. integer28Cells[3] = (SGF7|SGF4|SGF2|SGF1);
  124. integer28Cells[4] = (SGF5|SGF3|SGF2|SGF1);
  125. integer28Cells[5] = (SGF7|SGF5|SGF2|SGF1);
  126. integer28Cells[6] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  127. integer28Cells[7] = (SGF7|SGF6|SGF5|SGF4|SGF2);
  128. integer28Cells[8] = (SGF6|SGF5|SGF2|SGF1);
  129. integer28Cells[9] = (SGF7|SGF2|SGF1);
  130. integer28Cells[10] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  131. integer28Cells[11] = (SGF5|SGF3|SGF2|SGF1);
  132. integer28Cells[12] = (SGF7|SGF6|SGF5|SGF4|SGF3|SGF1);
  133. integer28Cells[13] = (SGF7|SGF6|SGF5|SGF3|SGF2|SGF1);
  134. integer28Cells[14] = (SGF7|SGF2|SGF1);
  135. integer28Cells[15] = (SGF5|SGF4|SGF2|SGF1);
  136. integer28Cells[16] = (SGF5|SGF4|SGF2|SGF1);
  137. integer28Cells[17] = (SGF3|SGF2|SGF1);
  138. integer28Cells[18] = (SGF7|SGF5|SGF3|SGF2|SGF1);
  139. integer28Cells[19] = (SGF6|SGF5|SGF2|SGF1);
  140. integer28Cells[20] = (SGF6|SGF5|SGF2|SGF1);
  141. integer28Cells[21] = (SGF7|SGF3|SGF2);
  142. integer28Cells[22] = (SGF6|SGF5|SGF4|SGF2);
  143. integer28Cells[23] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  144. integer28Cells[24] = (SGF3|SGF2|SGF1);
  145. integer28Cells[25] = (SGF6|SGF3|SGF2|SGF1);
  146.  
  147. if( contain(integer28Cells, "sprites/ballsmoke.spr") )
  148. {
  149. g_iSpriteWhite = precache_model(integer28Cells);
  150. force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, integer28Cells);
  151. }
  152. else
  153. {
  154. g_iSpriteWhite = precache_model("sprites/ballsmoke.spr");
  155. force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, "sprites/ballsmoke.spr");
  156. }
  157. #endif
  158. #if SMOKE_BLACK_PERCENT > 0
  159. integer28Cells[0] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  160. integer28Cells[1] = (SGF3|SGF2|SGF1);
  161. integer28Cells[2] = (SGF6|SGF3|SGF2|SGF1);
  162. integer28Cells[3] = (SGF7|SGF4|SGF2|SGF1);
  163. integer28Cells[4] = (SGF5|SGF3|SGF2|SGF1);
  164. integer28Cells[5] = (SGF7|SGF5|SGF2|SGF1);
  165. integer28Cells[6] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  166. integer28Cells[7] = (SGF7|SGF6|SGF5|SGF4|SGF2);
  167. integer28Cells[8] = (SGF6|SGF2|SGF1);
  168. integer28Cells[9] = (SGF5|SGF4|SGF2|SGF1);
  169. integer28Cells[10] = (SGF7|SGF2|SGF1);
  170. integer28Cells[11] = (SGF7|SGF6|SGF2|SGF1);
  171. integer28Cells[12] = (SGF7|SGF6|SGF4|SGF2|SGF1);
  172. integer28Cells[13] = (SGF7|SGF6|SGF5|SGF4|SGF3|SGF1);
  173. integer28Cells[14] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  174. integer28Cells[15] = (SGF7|SGF5|SGF4|SGF2|SGF1);
  175. integer28Cells[16] = (SGF7|SGF6|SGF5|SGF4|SGF2|SGF1);
  176. integer28Cells[17] = (SGF7|SGF6|SGF4|SGF2|SGF1);
  177. integer28Cells[18] = (SGF7|SGF5|SGF2|SGF1);
  178. integer28Cells[19] = random(2)?(SGF7|SGF6|SGF3|SGF2):(SGF5|SGF3|SGF2);
  179. integer28Cells[20] = (SGF6|SGF5|SGF4|SGF2);
  180. integer28Cells[21] = (SGF7|SGF6|SGF3|SGF2|SGF1);
  181. integer28Cells[22] = (SGF3|SGF2|SGF1);
  182. integer28Cells[23] = (SGF6|SGF3|SGF2|SGF1);
  183. integer28Cells[24] = 0;
  184. integer28Cells[25] = 0;
  185.  
  186. if( contain(integer28Cells, "sprites/bloodspray.spr") )
  187. {
  188. g_iSpriteWhite = precache_model(integer28Cells);
  189. force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, integer28Cells);
  190. }
  191. else
  192. {
  193. g_iSpriteBlack = precache_model("sprites/bloodspray.spr");
  194. force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, "sprites/bloodspray.spr");
  195. }
  196. #endif
  197. }
  198.  
  199. #if VIEW_ABILITY > 0
  200. public client_putinserver(iPlrId)
  201. g_bIsUserConnected[iPlrId] = true;
  202.  
  203. public client_disconnect(iPlrId)
  204. g_bIsUserConnected[iPlrId] = false;
  205. #endif
  206.  
  207. public FM_SetModel_Pre(iEnt, iModel[])
  208. {
  209. if( pev_valid(iEnt) )
  210. {
  211. static s_iClassName[9];
  212. pev(iEnt, pev_classname, s_iClassName, 8);
  213.  
  214. if( equal(s_iClassName, "grenade") && equal(iModel, "models/w_smokegrenade.mdl") )
  215. set_pev(iEnt, pev_iuser1, 3);
  216. }
  217. }
  218.  
  219. public Ham_Think_grenade_Pre(iEnt)
  220. {
  221. if( pev(iEnt, pev_iuser1)==3 )
  222. {
  223. static Float:s_fDmgTime, Float:s_fGameTime;
  224. pev(iEnt, pev_dmgtime, s_fDmgTime);
  225. global_get(glb_time, s_fGameTime);
  226.  
  227. if( s_fGameTime>=s_fDmgTime )
  228. {
  229. set_pev(iEnt, pev_dmgtime, (s_fGameTime+SMOKE_LIFE_TIME));
  230. if( !pev(iEnt, pev_iuser4) )
  231. {
  232. emit_sound(iEnt, CHAN_WEAPON, "weapons/sg_explode.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
  233. set_pev(iEnt, pev_iuser4, 1);
  234. }
  235. else
  236. set_pev(iEnt, pev_flags, (pev(iEnt, pev_flags)|FL_KILLME));
  237. }
  238. else if( !pev(iEnt, pev_iuser4) )
  239. return HAM_IGNORED;
  240.  
  241. static Float:s_fOrigin[3], Float:s_fEndOrigin[3];
  242. pev(iEnt, pev_origin, s_fOrigin);
  243. s_fEndOrigin = s_fOrigin;
  244. s_fEndOrigin[2] += random_float(8.0, 32.0);
  245.  
  246. static Float:s_fFraction;
  247. engfunc(EngFunc_TraceLine, s_fOrigin, s_fEndOrigin, IGNORE_MONSTERS, iEnt, 0);
  248. get_tr2(0, TR_flFraction, s_fFraction);
  249.  
  250. if( s_fFraction!=1.0 )
  251. get_tr2(0, TR_pHit, s_fOrigin);
  252. else
  253. s_fOrigin = s_fEndOrigin;
  254.  
  255. static s_iLoopId, Float:s_fDistance;
  256. #if VIEW_ABILITY > 0
  257. static s_iPlrId, Float:s_fPlrOrigin[3]
  258. #endif
  259. for( s_iLoopId=0; s_iLoopId<SMOKE_PUFFS_PER_THINK; s_iLoopId++ )
  260. {
  261. s_fEndOrigin[0] = random_float((random(2)?-50.0:-80.0), 0.0);
  262. s_fEndOrigin[1] = random_float((s_iLoopId*(360.0/SMOKE_PUFFS_PER_THINK)), ((s_iLoopId+1)*(360.0/SMOKE_PUFFS_PER_THINK)));
  263. s_fEndOrigin[2] = 0.0;
  264. while( s_fEndOrigin[1]>180.0 )
  265. s_fEndOrigin[1] -= 360.0;
  266.  
  267. engfunc(EngFunc_MakeVectors, s_fEndOrigin);
  268. global_get(glb_v_forward, s_fEndOrigin);
  269. s_fEndOrigin[0] *= 9999.0;
  270. s_fEndOrigin[1] *= 9999.0;
  271. s_fEndOrigin[2] *= 9999.0;
  272. s_fEndOrigin[0] += s_fOrigin[0];
  273. s_fEndOrigin[1] += s_fOrigin[1];
  274. s_fEndOrigin[2] += s_fOrigin[2];
  275.  
  276. engfunc(EngFunc_TraceLine, s_fOrigin, s_fEndOrigin, IGNORE_MONSTERS, iEnt, 0);
  277. get_tr2(0, TR_vecEndPos, s_fEndOrigin);
  278.  
  279. if( (s_fDistance=get_distance_f(s_fOrigin, s_fEndOrigin))>(s_fFraction=(random(3)?random_float((SMOKE_MAX_RADIUS*0.5), SMOKE_MAX_RADIUS):random_float(16.0, SMOKE_MAX_RADIUS))) )
  280. {
  281. s_fFraction /= s_fDistance;
  282.  
  283. if( s_fEndOrigin[0]!=s_fOrigin[0] )
  284. {
  285. s_fDistance = (s_fEndOrigin[0]-s_fOrigin[0])*s_fFraction;
  286. s_fEndOrigin[0] = (s_fOrigin[0]+s_fDistance);
  287. }
  288. if( s_fEndOrigin[1]!=s_fOrigin[1] )
  289. {
  290. s_fDistance = (s_fEndOrigin[1]-s_fOrigin[1])*s_fFraction;
  291. s_fEndOrigin[1] = (s_fOrigin[1]+s_fDistance);
  292. }
  293. if( s_fEndOrigin[2]!=s_fOrigin[2] )
  294. {
  295. s_fDistance = (s_fEndOrigin[2]-s_fOrigin[2])*s_fFraction;
  296. s_fEndOrigin[2] = (s_fOrigin[2]+s_fDistance);
  297. }
  298. }
  299.  
  300. #if VIEW_ABILITY > 0
  301. static bool:s_bBlackSmoke;
  302. s_bBlackSmoke = (random(100)<SMOKE_BLACK_PERCENT)?true:false;
  303. for( s_iPlrId=1; s_iPlrId<=g_iMaxPlayers; s_iPlrId++ )
  304. {
  305. if( g_bIsUserConnected[s_iPlrId] )
  306. {
  307. pev(s_iPlrId, pev_origin, s_fPlrOrigin);
  308.  
  309. if( get_distance_f(s_fPlrOrigin, s_fEndOrigin)>(SMOKE_MAX_RADIUS*0.5) || random(VIEW_ABILITY) )
  310. {
  311. message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, s_iPlrId);
  312. if( s_bBlackSmoke )
  313. {
  314. write_byte(TE_SMOKE);
  315. engfunc(EngFunc_WriteCoord, s_fEndOrigin[0]);
  316. engfunc(EngFunc_WriteCoord, s_fEndOrigin[1]);
  317. engfunc(EngFunc_WriteCoord, (s_fEndOrigin[2]-32.0));
  318. write_short(g_iSpriteBlack);
  319. write_byte(random_num(30, 34));
  320. write_byte(18);
  321. }
  322. else
  323. {
  324. write_byte(TE_SPRITE);
  325. engfunc(EngFunc_WriteCoord, s_fEndOrigin[0]);
  326. engfunc(EngFunc_WriteCoord, s_fEndOrigin[1]);
  327. engfunc(EngFunc_WriteCoord, s_fEndOrigin[2]);
  328. write_short(g_iSpriteWhite);
  329. write_byte(random_num(18, 22));
  330. write_byte(127);
  331. }
  332. message_end();
  333. }
  334. }
  335. }
  336. #else
  337. message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
  338. if( random(100)<SMOKE_BLACK_PERCENT )
  339. {
  340. write_byte(TE_SMOKE);
  341. engfunc(EngFunc_WriteCoord, s_fEndOrigin[0]);
  342. engfunc(EngFunc_WriteCoord, s_fEndOrigin[1]);
  343. engfunc(EngFunc_WriteCoord, (s_fEndOrigin[2]-32.0));
  344. write_short(g_iSpriteBlack);
  345. write_byte(random_num(30, 34));
  346. write_byte(18);
  347. }
  348. else
  349. {
  350. write_byte(TE_SPRITE);
  351. engfunc(EngFunc_WriteCoord, s_fEndOrigin[0]);
  352. engfunc(EngFunc_WriteCoord, s_fEndOrigin[1]);
  353. engfunc(EngFunc_WriteCoord, s_fEndOrigin[2]);
  354. write_short(g_iSpriteWhite);
  355. write_byte(random_num(18, 22));
  356. write_byte(127);
  357. }
  358. message_end();
  359. #endif
  360. }
  361. }
  362.  
  363. return HAM_IGNORED;
  364. }
  365.