1 |
cstrike |
24 |
/******************************************************************************* |
2 |
|
|
* |
3 |
|
|
* This program is free software; you can redistribute it and/or |
4 |
|
|
* modify it under the terms of the GNU General Public License |
5 |
|
|
* as published by the Free Software Foundation; either version 2 |
6 |
|
|
* of the License, or version 3. |
7 |
|
|
* |
8 |
|
|
* This program is distributed in the hope that it will be useful, |
9 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 |
|
|
* GNU General Public License for more details. |
12 |
|
|
* |
13 |
|
|
* You should have received a copy of the GNU General Public License |
14 |
|
|
* along with this program; if not, write to the Free Software |
15 |
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
16 |
|
|
* |
17 |
|
|
* In addition, as a special exception, the author gives permission to |
18 |
|
|
* link the code of this program with the Half-Life Game Engine ("HL |
19 |
|
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve, |
20 |
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all |
21 |
|
|
* respects for all of the code used other than the HL Engine and MODs |
22 |
|
|
* from Valve. If you modify this file, you must extend this exception |
23 |
|
|
* to your version of the file. |
24 |
|
|
* |
25 |
|
|
******************************************************************************** |
26 |
|
|
|
27 |
|
|
|
28 |
|
|
Molotov Cocktail |
29 |
|
|
Version 3.20 |
30 |
|
|
Maintained by: DynamicBits (Andy) |
31 |
|
|
|
32 |
|
|
* Commands: |
33 |
|
|
- say molotov - Buy a molotov |
34 |
|
|
- say /molotov - Buy a molotov |
35 |
|
|
- molotov_give <player|@all|@t|@ct|@al|@ax> - Gives molotovs to a player, a team, or everyone |
36 |
|
|
- molotov_cocktail [0|1] - Enable/disable the plugin (If no arguments, show the status) |
37 |
|
|
- molotov_override [0|1] - Enable/disable the HE grenade override (If no arguments, show the status) |
38 |
|
|
|
39 |
|
|
* Cvars |
40 |
|
|
- molotov_enabled - Enable/disable the plugin [1 = enabled; 0 = disabled] [default = 1] |
41 |
|
|
- molotov_price - Set the molotov price [default = 1200] |
42 |
|
|
- molotov_damage - Set the damage done by initial molotov explosion [default = 50.0] |
43 |
|
|
- molotov_radius - Set the radius of molotov damage [default = 150.0] |
44 |
|
|
- molotov_firetime - Duration (in seconds) of fire effects, sounds, etc. [default = 6] |
45 |
|
|
- molotov_firedamage - Amount of damage done by fire effects (every 0.2 secs). [default = 3] |
46 |
|
|
- molotov_ff - Disable(0)/enable(1) the ability to damage/kill someone on your team with molotov. [default = 1] (Was molotov_tk) |
47 |
|
|
- molotov_override_he - Override the original hegrenade automaticly with molotov. [default = 0] (Was molotov_tempoverride) |
48 |
|
|
- molotov_max - Max num of molotovs able to carry. [default = 1] (Does not work with override) |
49 |
|
|
- molotov_inmenu - Puts molotov in the end of the equipment buymenu (old menu, not VGUI). [default = 0] |
50 |
|
|
(If the override cvar is enabled the hegrenade will be replaced instead.) |
51 |
|
|
- molotov_buyzone - Do you have to be in buyzone? [default = 1] (If molotov_inmenu=1, this is ignored) |
52 |
|
|
- molotov_menu - Enables menu at beginning of each round [default = 0] (Was amx_molotovmenu) |
53 |
|
|
|
54 |
|
|
* Required Modules: |
55 |
|
|
- Fakemeta |
56 |
|
|
- Fun |
57 |
|
|
- Cstrike |
58 |
|
|
- CSX |
59 |
|
|
|
60 |
|
|
* Changelog/Credit: |
61 |
|
|
- DynamicBits |
62 |
|
|
* Version 3.20 (2008-11-20) |
63 |
|
|
- My first public release |
64 |
|
|
- Finally tracked down and fixed the intermittent crashing problem (I hope!) |
65 |
|
|
- Modified default damage values |
66 |
|
|
- molotov_cocktail/molotov_override commands now change settings *or* display status |
67 |
|
|
- Broken molotov model stays closer to the explosion (looks more realistic) |
68 |
|
|
- Task IDs are now guaranteed to be unique |
69 |
|
|
- Modified anti-lag calculations to be more accurate (less likely to lag) |
70 |
|
|
- Changed amx_molotovmenu CVAR to molotov_menu |
71 |
|
|
- Changed molotov_tk CVAR to molotov_ff |
72 |
|
|
- Changed molotov_tempoverride CVAR to molotov_override_he |
73 |
|
|
- Preparation for support of mods other than Counter-Strike |
74 |
|
|
- Fixed lots of coding mistakes |
75 |
|
|
- Optimized several sections of code |
76 |
|
|
- Corrected grammar/typos |
77 |
|
|
- Clean up code (Removed unused code/unhelpful comments, fixed formatting, and semicolons!) |
78 |
|
|
- Raffe (CantShoot) |
79 |
|
|
* (Unversioned release) |
80 |
|
|
- Originally fixed plugin to run on Linux servers |
81 |
|
|
- Added optional menu to purchase molotov cocktails each round |
82 |
|
|
- Moved models and sounds into proper molotov/ subdirectories |
83 |
|
|
- Fixed molotovs not being reset upon player disconnect |
84 |
|
|
- (Almost) fixed molotovs not being removed for new round |
85 |
|
|
- Added @all/@ct/@t arguments to cmd_MolotovGive |
86 |
|
|
- Changed some models/sound |
87 |
|
|
- [ --<-@ ] Black Rose |
88 |
|
|
* Version 3.0-3.1c ? |
89 |
|
|
- Unknown changes |
90 |
|
|
- SAMURAI |
91 |
|
|
* Original plugin author |
92 |
|
|
|
93 |
|
|
|
94 |
|
|
*/ |
95 |
|
|
|
96 |
|
|
#pragma semicolon 1 |
97 |
|
|
#include <amxmodx> |
98 |
|
|
#include <amxmisc> |
99 |
|
|
#include <fakemeta> |
100 |
|
|
#include <cstrike> |
101 |
|
|
#include <csx> |
102 |
|
|
#include <fun> |
103 |
|
|
#include <fakemeta_util> |
104 |
|
|
|
105 |
|
|
// Uncomment the following line to enable debug logging. |
106 |
|
|
//#define MOLOTOV_DEBUG |
107 |
|
|
|
108 |
|
|
#define AUTHORS "DynamicBits" |
109 |
|
|
|
110 |
|
|
#define ADMIN_ACCESS ADMIN_KICK |
111 |
|
|
|
112 |
|
|
#define ANTI_LAGG 7.0 // Defines max calculations before a flame is spawned without check if onground |
113 |
|
|
// This is to prevent lagg at really narrow ents where you could end up with 400 calculations per flame |
114 |
|
|
// Suggested: <= 10 |
115 |
|
|
|
116 |
|
|
#define MOLOTOV_HARD_LIMIT 10 // Maximum molotov cocktails this code is capable of handling without bugs |
117 |
|
|
// Also how many cocktails people get with molotov_give command |
118 |
|
|
|
119 |
|
|
#define MOLOTOV_MENU_KEYS MENU_KEY_0|MENU_KEY_1|MENU_KEY_2 // Choices to look for with optional menu |
120 |
|
|
|
121 |
|
|
#define MOLOTOV_TASKID_BASE 1000 // What is the lowest task ID? |
122 |
|
|
#define MOLOTOV_TASKID_OFFSET MOLOTOV_HARD_LIMIT |
123 |
|
|
#define MOLOTOV_TASKID_BASE1 MOLOTOV_TASKID_BASE // By default, with 32 players, task ids |
124 |
|
|
#define MOLOTOV_TASKID_BASE2 MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * 32) // from 1000 to 1959 can |
125 |
|
|
#define MOLOTOV_TASKID_BASE3 MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * 32) // potentially be used used. |
126 |
|
|
|
127 |
|
|
#define TEAM_UNASSIGNED 0 |
128 |
|
|
#define TEAM_ONE 1 |
129 |
|
|
#define TEAM_TWO 2 |
130 |
|
|
#define TEAM_SPECTATOR 3 |
131 |
|
|
|
132 |
|
|
new pEnabled, pPrice, pMlDamage, pMlRadius, pFireTime, pOverride; |
133 |
|
|
new pFriendlyFire, pFireDmg, pMaxMolotovs, pBuyMenu, pBuyZone, pMolotovMenu; |
134 |
|
|
|
135 |
|
|
new gmsgScoreInfo, gmsgDeathMsg; |
136 |
|
|
|
137 |
|
|
new g_pAllocModel, g_vAllocModel; |
138 |
|
|
|
139 |
|
|
new g_frags[33]; |
140 |
|
|
new g_hasMolotov[33]; |
141 |
|
|
new g_restarted; |
142 |
|
|
new g_MaxPlayers; |
143 |
|
|
new g_bomb_map; |
144 |
|
|
|
145 |
|
|
new firespr, smokespr[2]; |
146 |
|
|
|
147 |
|
|
new last_Molotov_ent; |
148 |
|
|
new g_Molotov_offset[33]; |
149 |
|
|
|
150 |
|
|
new g_g; |
151 |
|
|
|
152 |
|
|
public plugin_init() { |
153 |
|
|
|
154 |
|
|
register_plugin("Molotov Cocktail", "3.20", AUTHORS); |
155 |
|
|
|
156 |
|
|
register_menucmd(register_menuid("Buy Molotov Coctail"), MOLOTOV_MENU_KEYS, "giveMolotov"); |
157 |
|
|
#if defined MOLOTOV_DEBUG |
158 |
|
|
register_clcmd("molotov_menutest", "show_molotov_menu"); |
159 |
|
|
#endif |
160 |
|
|
|
161 |
|
|
register_clcmd("say /molotov", "buy_molotov"); |
162 |
|
|
register_clcmd("say molotov", "buy_molotov"); |
163 |
|
|
|
164 |
|
|
register_concmd("molotov_give", "cmd_MolotovGive", ADMIN_ACCESS, "<player|@all|@t|@ct|@al|@ax> - Gives free molotov cocktails (default=10)"); |
165 |
|
|
register_concmd("molotov_override", "cmd_Override", ADMIN_ACCESS, "[0|1] - Enable/disable the HE grenade override (If no arguments, show the status)"); |
166 |
|
|
register_concmd("molotov_cocktail", "cmd_PluginStatus", ADMIN_ACCESS, "[0|1] - Enable/disable the plugin (If no arguments, show the status)"); |
167 |
|
|
|
168 |
|
|
pEnabled = register_cvar("molotov_enabled", "1", FCVAR_SPONLY); |
169 |
|
|
pOverride = register_cvar("molotov_override_he", "0", FCVAR_SPONLY); |
170 |
|
|
pPrice = register_cvar("molotov_price", "1200", FCVAR_SPONLY); |
171 |
|
|
pMlDamage = register_cvar("molotov_damage", "50.0", FCVAR_SPONLY); |
172 |
|
|
pMlRadius = register_cvar("molotov_radius", "150.0", FCVAR_SPONLY); |
173 |
|
|
pFireTime = register_cvar("molotov_firetime", "6", FCVAR_SPONLY); |
174 |
|
|
pFireDmg = register_cvar("molotov_firedamage", "3", FCVAR_SPONLY); |
175 |
|
|
pFriendlyFire = register_cvar("molotov_ff", "1", FCVAR_SPONLY); |
176 |
|
|
pMaxMolotovs = register_cvar("molotov_max", "1", FCVAR_SPONLY); |
177 |
|
|
pBuyMenu = register_cvar("molotov_inmenu", "0", FCVAR_SPONLY); |
178 |
|
|
pBuyZone = register_cvar("molotov_buyzone", "1", FCVAR_SPONLY); |
179 |
|
|
pMolotovMenu = register_cvar("molotov_menu", "0", FCVAR_SPONLY); |
180 |
|
|
|
181 |
|
|
register_event("CurWeapon", "Event_CurWeapon", "be", "1=1"); |
182 |
|
|
register_event("HLTV", "event_new_round", "a", "1=0", "2=0"); |
183 |
|
|
register_event("TextMsg", "Event_GameRestart", "a", "2=#Game_Commencing", "2=#Game_will_restart_in"); |
184 |
|
|
register_event("DeathMsg", "event_DeathMsg", "a"); |
185 |
|
|
|
186 |
|
|
register_event("ShowMenu", "event_BuyMenuT", "b", "4=#T_BuyItem", "1=575"); |
187 |
|
|
register_event("ShowMenu", "event_BuyMenuCT", "b", "4=#CT_BuyItem", "1=703"); |
188 |
|
|
register_event("ShowMenu", "event_BuyMenuT", "b", "4=#DT_BuyItem", "1=575"); |
189 |
|
|
register_event("ShowMenu", "event_BuyMenuCT", "b", "4=#DCT_BuyItem", "1=767"); |
190 |
|
|
|
191 |
|
|
register_logevent("logevent_Round_End", 2, "1=Round_End"); |
192 |
|
|
|
193 |
|
|
register_menucmd(register_menuid("#CT_BuyItem"), 1023, "handle_BuyMenuCT"); |
194 |
|
|
register_menucmd(register_menuid("#T_BuyItem"), 1023, "handle_BuyMenuT"); |
195 |
|
|
|
196 |
|
|
register_forward(FM_EmitSound, "fw_EmitSound"); |
197 |
|
|
|
198 |
|
|
g_MaxPlayers = get_maxplayers(); |
199 |
|
|
|
200 |
|
|
gmsgScoreInfo = get_user_msgid("ScoreInfo"); |
201 |
|
|
gmsgDeathMsg = get_user_msgid("DeathMsg"); |
202 |
|
|
|
203 |
|
|
g_pAllocModel = engfunc(EngFunc_AllocString, "models/molotov/p_molotov.mdl"); |
204 |
|
|
g_vAllocModel = engfunc(EngFunc_AllocString, "models/molotov/v_molotov.mdl"); |
205 |
|
|
|
206 |
|
|
g_bomb_map = engfunc(EngFunc_FindEntityByString, g_MaxPlayers, "classname", "info_bomb_target") ? 1 : 0; |
207 |
|
|
} |
208 |
|
|
|
209 |
|
|
public plugin_precache() { |
210 |
|
|
|
211 |
|
|
firespr = precache_model("sprites/flame.spr"); |
212 |
|
|
|
213 |
|
|
smokespr[0] = precache_model("sprites/black_smoke3.spr"); |
214 |
|
|
smokespr[1] = precache_model("sprites/steam1.spr"); |
215 |
|
|
|
216 |
|
|
precache_sound("molotov/molotov_fire.wav"); |
217 |
|
|
|
218 |
|
|
precache_model("models/molotov/p_molotov.mdl"); |
219 |
|
|
precache_model("models/molotov/v_molotov.mdl"); |
220 |
|
|
precache_model("models/molotov/w_molotov.mdl"); |
221 |
|
|
precache_model("models/molotov/w_broke_molotov.mdl"); |
222 |
|
|
|
223 |
|
|
} |
224 |
|
|
|
225 |
|
|
public client_disconnect(id) { |
226 |
|
|
g_hasMolotov[id] = 0; |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
public fw_EmitSound(ent, channel, sample[]) { |
230 |
|
|
|
231 |
|
|
if (equal(sample[8], "he_bounce", 9)) { |
232 |
|
|
|
233 |
|
|
new model[32]; |
234 |
|
|
pev(ent, pev_model, model, 31); |
235 |
|
|
|
236 |
|
|
if (equal(model[9], "lotov/w_molotov.mdl")) { |
237 |
|
|
if (last_Molotov_ent != ent) { |
238 |
|
|
new Float:fFriction, Float:fVelocity[3]; |
239 |
|
|
|
240 |
|
|
pev(ent, pev_friction, fFriction); |
241 |
|
|
pev(ent, pev_velocity, fVelocity); |
242 |
|
|
|
243 |
|
|
fFriction *= 1.3; // Increase friction to make it look more realistic |
244 |
|
|
set_pev(ent, pev_friction, fFriction); |
245 |
|
|
#if defined MOLOTOV_DEBUG |
246 |
|
|
log_amx("[MC] ent:%d Friction:%f Velocity:%f/%f/%f ====================", ent, fFriction, fVelocity[0], fVelocity[1], fVelocity[2]); |
247 |
|
|
#endif |
248 |
|
|
last_Molotov_ent = ent; |
249 |
|
|
grenade_explode(ent); |
250 |
|
|
|
251 |
|
|
return FMRES_SUPERCEDE; |
252 |
|
|
#if defined MOLOTOV_DEBUG |
253 |
|
|
} else { |
254 |
|
|
log_amx("[MC] last_Molotov_ent(%d) ent(%d)", last_Molotov_ent, ent); |
255 |
|
|
#endif |
256 |
|
|
} |
257 |
|
|
} |
258 |
|
|
} |
259 |
|
|
return FMRES_IGNORED; |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
public Event_CurWeapon(id) { |
263 |
|
|
|
264 |
|
|
if (!get_pcvar_num(pEnabled) || !is_user_alive(id)) { |
265 |
|
|
return PLUGIN_CONTINUE; |
266 |
|
|
} |
267 |
|
|
|
268 |
|
|
if (!g_hasMolotov[id] && !get_pcvar_num(pOverride)) { |
269 |
|
|
return PLUGIN_CONTINUE; |
270 |
|
|
} |
271 |
|
|
|
272 |
|
|
new WeaponID = get_user_weapon(id, WeaponID, WeaponID); |
273 |
|
|
|
274 |
|
|
if (WeaponID != CSW_HEGRENADE) { |
275 |
|
|
return PLUGIN_CONTINUE; |
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
set_pev(id, pev_viewmodel, g_vAllocModel); |
279 |
|
|
set_pev(id, pev_weaponmodel, g_pAllocModel); |
280 |
|
|
set_pev(id, pev_weaponanim, 9); |
281 |
|
|
|
282 |
|
|
return PLUGIN_CONTINUE; |
283 |
|
|
} |
284 |
|
|
|
285 |
|
|
public Event_GameRestart() { |
286 |
|
|
g_restarted = 1; |
287 |
|
|
} |
288 |
|
|
|
289 |
|
|
public event_DeathMsg() { |
290 |
|
|
g_hasMolotov[read_data(2)] = 0; |
291 |
|
|
} |
292 |
|
|
|
293 |
|
|
public logevent_Round_End() { |
294 |
|
|
#if defined MOLOTOV_DEBUG |
295 |
|
|
log_amx("[MC] ========== Round_End =========="); |
296 |
|
|
#endif |
297 |
|
|
reset_tasks(); |
298 |
|
|
} |
299 |
|
|
|
300 |
|
|
stock reset_tasks() { |
301 |
|
|
#if defined MOLOTOV_DEBUG |
302 |
|
|
new tmpdbgid; |
303 |
|
|
#endif |
304 |
|
|
for (new i; i < g_MaxPlayers; i++) { |
305 |
|
|
for (new o; o < MOLOTOV_TASKID_OFFSET; o++) { //TODO DEBUG: Verify this fixes the tasks not reset at new round issue |
306 |
|
|
if (task_exists(MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o)) { |
307 |
|
|
remove_task(MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o); |
308 |
|
|
#if defined MOLOTOV_DEBUG |
309 |
|
|
tmpdbgid = MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o; |
310 |
|
|
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid); |
311 |
|
|
#endif |
312 |
|
|
} |
313 |
|
|
|
314 |
|
|
if (task_exists(MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o)) { |
315 |
|
|
remove_task(MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o); |
316 |
|
|
#if defined MOLOTOV_DEBUG |
317 |
|
|
tmpdbgid = MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o; |
318 |
|
|
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid); |
319 |
|
|
#endif |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
if (task_exists(MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o)) { |
323 |
|
|
remove_task(MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o); |
324 |
|
|
#if defined MOLOTOV_DEBUG |
325 |
|
|
tmpdbgid = MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o; |
326 |
|
|
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid); |
327 |
|
|
#endif |
328 |
|
|
} |
329 |
|
|
} |
330 |
|
|
} |
331 |
|
|
} |
332 |
|
|
|
333 |
|
|
public event_new_round(id) { |
334 |
|
|
#if defined MOLOTOV_DEBUG |
335 |
|
|
log_amx("[MC] ========== event_new_round =========="); |
336 |
|
|
#endif |
337 |
|
|
if (!get_pcvar_num(pEnabled)) { |
338 |
|
|
return PLUGIN_CONTINUE; |
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
reset_tasks(); // DEBUG |
342 |
|
|
|
343 |
|
|
if (get_pcvar_num(pMolotovMenu)) { |
344 |
|
|
show_molotov_menu(id); |
345 |
|
|
} |
346 |
|
|
|
347 |
|
|
for (new i; i < g_MaxPlayers; i++) { |
348 |
|
|
if (g_frags[i] && is_user_connected(i)) { |
349 |
|
|
set_user_frags(i, get_user_frags(i) + g_frags[i]); |
350 |
|
|
} |
351 |
|
|
g_frags[i] = 0; |
352 |
|
|
} |
353 |
|
|
|
354 |
|
|
if (g_restarted) { |
355 |
|
|
for (new i; i < g_MaxPlayers; i++) { |
356 |
|
|
g_hasMolotov[i] = 0; |
357 |
|
|
} |
358 |
|
|
g_restarted = 0; |
359 |
|
|
} |
360 |
|
|
|
361 |
|
|
if (get_pcvar_num(pOverride)) { |
362 |
|
|
set_molotovs(); |
363 |
|
|
} else { |
364 |
|
|
reset_molotovs(); |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
return PLUGIN_CONTINUE; |
368 |
|
|
} |
369 |
|
|
|
370 |
|
|
public cmd_Override(id, level, cid) { |
371 |
|
|
|
372 |
|
|
if (!cmd_access(id, level, cid, 1)) { // First argument (passed to molotov_override) is optional |
373 |
|
|
return PLUGIN_HANDLED; |
374 |
|
|
} |
375 |
|
|
|
376 |
|
|
if (!get_pcvar_num(pEnabled)) { |
377 |
|
|
return PLUGIN_HANDLED; |
378 |
|
|
} |
379 |
|
|
|
380 |
|
|
if (read_argc() == 1) { // No arguments; Display status |
381 |
|
|
client_print(id, print_console, "Override is currently %s.", get_pcvar_num(pOverride) ? "enabled" : "disabled"); |
382 |
|
|
return PLUGIN_HANDLED; |
383 |
|
|
} |
384 |
|
|
|
385 |
|
|
new arg[2]; |
386 |
|
|
read_argv(1, arg, 1); |
387 |
|
|
|
388 |
|
|
new num = str_to_num(arg); |
389 |
|
|
|
390 |
|
|
if ((num < 0) || (num > 1) || (!isdigit(arg[0]))) { // If less than 0 or greater than 1 or not a digit |
391 |
|
|
if (id) { |
392 |
|
|
client_print(id, print_console, "Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg); |
393 |
|
|
} else { |
394 |
|
|
server_print("Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg); |
395 |
|
|
} |
396 |
|
|
return PLUGIN_HANDLED; |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
if (num == get_pcvar_num(pOverride)) { |
400 |
|
|
if (id) { |
401 |
|
|
client_print(id, print_console, "Override is already %s.", num ? "enabled" : "disabled"); |
402 |
|
|
} else { |
403 |
|
|
server_print("Override is already %s.", num ? "enabled" : "disabled"); |
404 |
|
|
} |
405 |
|
|
return PLUGIN_HANDLED; |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
set_pcvar_num(pOverride, num); |
409 |
|
|
|
410 |
|
|
if (id) { |
411 |
|
|
client_print(id, print_console, "Override was %s.", num ? "enabled" : "disabled"); |
412 |
|
|
} else { |
413 |
|
|
server_print("Override was %s.", num ? "enabled" : "disabled"); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
if (num) { |
417 |
|
|
set_molotovs(); |
418 |
|
|
} else { |
419 |
|
|
reset_molotovs(); |
420 |
|
|
} |
421 |
|
|
|
422 |
|
|
return PLUGIN_HANDLED; |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
public cmd_PluginStatus(id, level, cid) { |
426 |
|
|
if (!cmd_access(id, level, cid, 1)) { // First argument (passed to molotov_cocktail) is optional |
427 |
|
|
return PLUGIN_HANDLED; |
428 |
|
|
} |
429 |
|
|
|
430 |
|
|
if (read_argc() == 1) { // No arguments; Display status |
431 |
|
|
client_print(id, print_console, "Plugin is currently %s.", get_pcvar_num(pEnabled) ? "enabled" : "disabled"); |
432 |
|
|
return PLUGIN_HANDLED; |
433 |
|
|
} |
434 |
|
|
|
435 |
|
|
new arg[2]; |
436 |
|
|
read_argv(1, arg, 1); |
437 |
|
|
|
438 |
|
|
new num = str_to_num(arg); |
439 |
|
|
|
440 |
|
|
if ((num < 0) || (num > 1) || (!isdigit(arg[0]))) { // If less than 0 or greater than 1 or not a digit |
441 |
|
|
if (id) { |
442 |
|
|
client_print(id, print_console, "Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg); |
443 |
|
|
} else { |
444 |
|
|
server_print("Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg); |
445 |
|
|
} |
446 |
|
|
return PLUGIN_HANDLED; |
447 |
|
|
} |
448 |
|
|
|
449 |
|
|
if (num == get_pcvar_num(pEnabled)) { |
450 |
|
|
if (id) { |
451 |
|
|
client_print(id, print_console, "Plugin is already %s.", num ? "enabled" : "disabled"); |
452 |
|
|
} else { |
453 |
|
|
server_print("Plugin is already %s.", num ? "enabled" : "disabled"); |
454 |
|
|
} |
455 |
|
|
return PLUGIN_HANDLED; |
456 |
|
|
} |
457 |
|
|
|
458 |
|
|
set_pcvar_num(pEnabled, num); |
459 |
|
|
|
460 |
|
|
if (id) { |
461 |
|
|
client_print(id, print_console, "Plugin was %s.", num ? "enabled" : "disabled"); |
462 |
|
|
} else { |
463 |
|
|
server_print("Plugin was %s.", num ? "enabled" : "disabled"); |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
if (num && get_pcvar_num(pOverride)) { |
467 |
|
|
set_molotovs(); |
468 |
|
|
} else { |
469 |
|
|
reset_molotovs(); |
470 |
|
|
} |
471 |
|
|
return PLUGIN_HANDLED; |
472 |
|
|
} |
473 |
|
|
|
474 |
|
|
public cmd_MolotovGive(id, level, cid) { |
475 |
|
|
|
476 |
|
|
#if defined MOLOTOV_DEBUG |
477 |
|
|
log_amx("[MC] cmd_MolotovGive"); |
478 |
|
|
#endif |
479 |
|
|
if (!cmd_access(id, level, cid, 2)) { |
480 |
|
|
return PLUGIN_HANDLED; |
481 |
|
|
} |
482 |
|
|
|
483 |
|
|
new Arg1[64], target; |
484 |
|
|
read_argv(1, Arg1, 63); |
485 |
|
|
|
486 |
|
|
new adminName[32]; |
487 |
|
|
get_user_name(id, adminName, 31); |
488 |
|
|
|
489 |
|
|
new targetTeam, targetTeamName[32]; |
490 |
|
|
new Players[32], iNum; |
491 |
|
|
#if defined MOLOTOV_DEBUG |
492 |
|
|
log_amx("[MC] cmd_MolotovGive Arg1[0](%s) Arg1[1](%s)", Arg1[0], Arg1[1]); |
493 |
|
|
#endif |
494 |
|
|
if (Arg1[0] == '@') { |
495 |
|
|
|
496 |
|
|
if (equali(Arg1[1], "all")) { |
497 |
|
|
targetTeam = 0; |
498 |
|
|
} else if (equali(Arg1[1], "t") || equali(Arg1[1], "al")) { // CS_TEAM_T or ALLIES |
499 |
|
|
targetTeam = TEAM_ONE; |
500 |
|
|
} else if (equali(Arg1[1], "ct") || equali(Arg1[1], "ax")) { // CS_TEAM_CT or AXIS |
501 |
|
|
targetTeam = TEAM_TWO; |
502 |
|
|
} |
503 |
|
|
|
504 |
|
|
get_players(Players, iNum, "ac"); // Bots don't understand molotov cocktails |
505 |
|
|
|
506 |
|
|
for (new i = 0; i < iNum; ++i) { |
507 |
|
|
target = Players[i]; |
508 |
|
|
|
509 |
|
|
if ((targetTeam == 0) || (get_user_team(target) == targetTeam)) { |
510 |
|
|
g_hasMolotov[target] = MOLOTOV_HARD_LIMIT; |
511 |
|
|
|
512 |
|
|
give_item(target, "weapon_hegrenade"); |
513 |
|
|
cs_set_user_bpammo(target, CSW_HEGRENADE, MOLOTOV_HARD_LIMIT); |
514 |
|
|
emit_sound(target, CHAN_WEAPON, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM); |
515 |
|
|
} |
516 |
|
|
} |
517 |
|
|
|
518 |
|
|
switch(targetTeam) { |
519 |
|
|
case 0: { |
520 |
|
|
targetTeamName = "everyone"; |
521 |
|
|
} |
522 |
|
|
case 1: { |
523 |
|
|
if (cstrike_running()) { |
524 |
|
|
targetTeamName = "all terrorists"; |
525 |
|
|
} else if (is_running("dod")) { |
526 |
|
|
targetTeamName = "all allies"; |
527 |
|
|
} else { |
528 |
|
|
targetTeamName = "team 1"; |
529 |
|
|
} |
530 |
|
|
} |
531 |
|
|
case 2: { |
532 |
|
|
if (cstrike_running()) { |
533 |
|
|
targetTeamName = "all ct's"; |
534 |
|
|
} else if (is_running("dod")) { |
535 |
|
|
targetTeamName = "all axis"; |
536 |
|
|
} else { |
537 |
|
|
targetTeamName = "team 2"; |
538 |
|
|
} |
539 |
|
|
} |
540 |
|
|
} |
541 |
|
|
client_print(0, print_chat, "ADMIN %s: has given %s %d Molotov Cocktails!", adminName, targetTeamName, MOLOTOV_HARD_LIMIT); |
542 |
|
|
|
543 |
|
|
} else { |
544 |
|
|
|
545 |
|
|
target = cmd_target(id, Arg1, 0); |
546 |
|
|
|
547 |
|
|
if (!is_user_connected(target) || !is_user_alive(target)) { |
548 |
|
|
return PLUGIN_HANDLED; |
549 |
|
|
} |
550 |
|
|
|
551 |
|
|
new targetName[32]; |
552 |
|
|
get_user_name(target, targetName, 31); |
553 |
|
|
|
554 |
|
|
g_hasMolotov[target] = MOLOTOV_HARD_LIMIT; |
555 |
|
|
|
556 |
|
|
give_item(target, "weapon_hegrenade"); |
557 |
|
|
cs_set_user_bpammo(target, CSW_HEGRENADE, MOLOTOV_HARD_LIMIT); |
558 |
|
|
|
559 |
|
|
emit_sound(target, CHAN_WEAPON, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM); |
560 |
|
|
|
561 |
|
|
client_print(target, print_chat, "ADMIN %s: has given you %d Molotov Cocktails!", adminName, MOLOTOV_HARD_LIMIT); |
562 |
|
|
|
563 |
|
|
} |
564 |
|
|
return PLUGIN_HANDLED; |
565 |
|
|
} |
566 |
|
|
|
567 |
|
|
public buy_molotov(id) { |
568 |
|
|
|
569 |
|
|
if (!get_pcvar_num(pEnabled)) { |
570 |
|
|
return PLUGIN_HANDLED; |
571 |
|
|
} |
572 |
|
|
|
573 |
|
|
if (get_pcvar_num(pOverride)) { |
574 |
|
|
if (get_pcvar_num(pBuyMenu)) { |
575 |
|
|
client_print(id, print_center, "Buy them in the buy equipment menu."); |
576 |
|
|
} else { |
577 |
|
|
client_print(id, print_center, "Just buy a HE grenade and get molotov automatically!"); |
578 |
|
|
} |
579 |
|
|
return PLUGIN_HANDLED; |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
if (!is_user_alive(id)) { |
583 |
|
|
client_print(id, print_center, "You can't buy Molotov Cocktails because you are dead."); |
584 |
|
|
return PLUGIN_HANDLED; |
585 |
|
|
} |
586 |
|
|
|
587 |
|
|
if (!cs_get_user_buyzone(id) && get_pcvar_num(pBuyZone)) { |
588 |
|
|
client_print(id, print_center, "You are not in a buyzone."); |
589 |
|
|
return PLUGIN_HANDLED; |
590 |
|
|
} |
591 |
|
|
|
592 |
|
|
new money = cs_get_user_money(id); |
593 |
|
|
|
594 |
|
|
if (money < get_pcvar_num(pPrice)) { |
595 |
|
|
client_print(id, print_center, "You don't have enough $ to buy a Molotov Cocktail."); |
596 |
|
|
return PLUGIN_HANDLED; |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
if (g_hasMolotov[id] == get_pcvar_num(pMaxMolotovs)) { |
600 |
|
|
if (g_hasMolotov[id] == 1) { |
601 |
|
|
client_print(id, print_center, "You already have a Molotov Cocktail."); |
602 |
|
|
} else { |
603 |
|
|
client_print(id, print_center, "You already have %d Molotov Cocktails.", g_hasMolotov[id]); |
604 |
|
|
} |
605 |
|
|
return PLUGIN_HANDLED; |
606 |
|
|
} |
607 |
|
|
|
608 |
|
|
if (!g_hasMolotov[id] && user_has_weapon(id, CSW_HEGRENADE)) { |
609 |
|
|
client_print(id, print_center, "You already have a HE Grenade."); |
610 |
|
|
return PLUGIN_HANDLED; |
611 |
|
|
} |
612 |
|
|
|
613 |
|
|
cs_set_user_money(id, money - get_pcvar_num(pPrice)); |
614 |
|
|
give_item(id, "weapon_hegrenade"); |
615 |
|
|
cs_set_user_bpammo(id, CSW_HEGRENADE, ++g_hasMolotov[id]); |
616 |
|
|
client_print(id, print_chat, "You got a Molotov Cocktail!"); |
617 |
|
|
|
618 |
|
|
return PLUGIN_HANDLED; |
619 |
|
|
} |
620 |
|
|
|
621 |
|
|
public event_BuyMenuCT(id) { |
622 |
|
|
|
623 |
|
|
if (!get_pcvar_num(pEnabled) || !get_pcvar_num(pBuyMenu)) { |
624 |
|
|
return PLUGIN_CONTINUE; |
625 |
|
|
} |
626 |
|
|
|
627 |
|
|
new Override = get_pcvar_num(pOverride); |
628 |
|
|
|
629 |
|
|
new menu[1024]; |
630 |
|
|
new len = formatex(menu, 1023, "\yBuy Equipment\R$ Cost"); |
631 |
|
|
|
632 |
|
|
len += formatex(menu[len], 1023-len, "^n^n\w1. Kevlar Vest\R\y650"); |
633 |
|
|
len += formatex(menu[len], 1023-len, "^n\w2. Kevlar Vest & Helmet\R\y1000"); |
634 |
|
|
len += formatex(menu[len], 1023-len, "^n\w3. Flashbang\R\y200"); |
635 |
|
|
|
636 |
|
|
if (Override) { |
637 |
|
|
len += formatex(menu[len], 1023-len, "^n\w4. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice)); |
638 |
|
|
} else { |
639 |
|
|
len += formatex(menu[len], 1023-len, "^n\w4. HE Grenade\R\y300"); |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
len += formatex(menu[len], 1023-len, "^n\w5. Smoke Grenade\R\y300"); |
643 |
|
|
len += formatex(menu[len], 1023-len, "^n\w6. NightVision Goggles\R\y1250"); |
644 |
|
|
len += formatex(menu[len], 1023-len, "^n\%c7. Defuse Kit\R\y200 ", g_bomb_map ? 'w' : 'd'); |
645 |
|
|
len += formatex(menu[len], 1023-len, "^n\w8. Tactical Shield\R\y2200"); |
646 |
|
|
|
647 |
|
|
if (!Override) { |
648 |
|
|
len += formatex(menu[len], 1023-len, "^n\w9. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice)); |
649 |
|
|
} |
650 |
|
|
|
651 |
|
|
len += formatex(menu[len], 1023-len, "^n^n\w0. Exit"); |
652 |
|
|
|
653 |
|
|
show_menu(id, read_data(1)|MENU_KEY_9, menu, -1, "#CT_BuyItem"); |
654 |
|
|
|
655 |
|
|
return PLUGIN_HANDLED; |
656 |
|
|
} |
657 |
|
|
|
658 |
|
|
public event_BuyMenuT(id) { |
659 |
|
|
|
660 |
|
|
if (!get_pcvar_num(pEnabled) || !get_pcvar_num(pBuyMenu)) { |
661 |
|
|
return PLUGIN_CONTINUE; |
662 |
|
|
} |
663 |
|
|
|
664 |
|
|
new Override = get_pcvar_num(pOverride); |
665 |
|
|
|
666 |
|
|
new menu[1024]; |
667 |
|
|
new len = formatex(menu, 1023, "\yBuy Equipment\R$ Cost"); |
668 |
|
|
len += formatex(menu[len], 1023-len, "^n^n\w1. Kevlar Vest\R\y650"); |
669 |
|
|
len += formatex(menu[len], 1023-len, "^n\w2. Kevlar Vest & Helmet\R\y1000"); |
670 |
|
|
len += formatex(menu[len], 1023-len, "^n\w3. Flashbang\R\y200"); |
671 |
|
|
|
672 |
|
|
if (Override) { |
673 |
|
|
len += formatex(menu[len], 1023-len, "^n\w4. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice)); |
674 |
|
|
} else { |
675 |
|
|
len += formatex(menu[len], 1023-len, "^n\w4. HE Grenade\R\y300"); |
676 |
|
|
} |
677 |
|
|
|
678 |
|
|
len += formatex(menu[len], 1023-len, "^n\w5. Smoke Grenade\R\y300"); |
679 |
|
|
len += formatex(menu[len], 1023-len, "^n\w6. NightVision Goggles\R\y1250"); |
680 |
|
|
|
681 |
|
|
if (!Override) { |
682 |
|
|
len += formatex(menu[len], 1023-len, "^n\w7. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice)); |
683 |
|
|
} |
684 |
|
|
|
685 |
|
|
len += formatex(menu[len], 1023-len, "^n^n\w0. Exit"); |
686 |
|
|
|
687 |
|
|
show_menu(id, read_data(1)|MENU_KEY_7, menu, -1, "#T_BuyItem"); |
688 |
|
|
|
689 |
|
|
return PLUGIN_HANDLED; |
690 |
|
|
} |
691 |
|
|
|
692 |
|
|
public handle_BuyMenuCT(id, key) { |
693 |
|
|
|
694 |
|
|
if (key == (get_pcvar_num(pOverride) ? 3 : 8)) { |
695 |
|
|
handle_BuyMenu(id); |
696 |
|
|
return PLUGIN_HANDLED; |
697 |
|
|
} |
698 |
|
|
|
699 |
|
|
return PLUGIN_CONTINUE; |
700 |
|
|
} |
701 |
|
|
|
702 |
|
|
public handle_BuyMenuT(id, key) { |
703 |
|
|
|
704 |
|
|
if (key == (get_pcvar_num(pOverride) ? 3 : 6)) { |
705 |
|
|
handle_BuyMenu(id); |
706 |
|
|
return PLUGIN_HANDLED; |
707 |
|
|
} |
708 |
|
|
|
709 |
|
|
return PLUGIN_CONTINUE; |
710 |
|
|
} |
711 |
|
|
|
712 |
|
|
stock handle_BuyMenu(id) { |
713 |
|
|
|
714 |
|
|
new money = cs_get_user_money(id); |
715 |
|
|
|
716 |
|
|
if (money < get_pcvar_num(pPrice)) { |
717 |
|
|
client_print(id, print_center, "You don't have enough $ to buy a Molotov Cocktail."); |
718 |
|
|
return PLUGIN_HANDLED; |
719 |
|
|
} |
720 |
|
|
|
721 |
|
|
if (g_hasMolotov[id] == get_pcvar_num(pMaxMolotovs)) { |
722 |
|
|
if (g_hasMolotov[id] == 1) { |
723 |
|
|
client_print(id, print_center, "You already have a Molotov Cocktail."); |
724 |
|
|
} else { |
725 |
|
|
client_print(id, print_center, "You already have %d Molotov Cocktails.", g_hasMolotov[id]); |
726 |
|
|
} |
727 |
|
|
return PLUGIN_HANDLED; |
728 |
|
|
} else if (!g_hasMolotov[id] && user_has_weapon(id, CSW_HEGRENADE)) { |
729 |
|
|
client_print(id, print_center, "You already have a HE Grenade."); |
730 |
|
|
return PLUGIN_HANDLED; |
731 |
|
|
} |
732 |
|
|
|
733 |
|
|
cs_set_user_money(id, money - get_pcvar_num(pPrice)); |
734 |
|
|
give_item(id, "weapon_hegrenade"); |
735 |
|
|
cs_set_user_bpammo(id, CSW_HEGRENADE, ++g_hasMolotov[id]); |
736 |
|
|
client_print(id, print_chat, "You got a Molotov Cocktail!"); |
737 |
|
|
|
738 |
|
|
return PLUGIN_HANDLED; |
739 |
|
|
} |
740 |
|
|
|
741 |
|
|
public grenade_throw(id, ent, wid) { |
742 |
|
|
|
743 |
|
|
if (!get_pcvar_num(pEnabled) || !is_user_connected(id) || wid != CSW_HEGRENADE) { |
744 |
|
|
return PLUGIN_CONTINUE; |
745 |
|
|
} |
746 |
|
|
|
747 |
|
|
if (!g_hasMolotov[id] && !get_pcvar_num(pOverride)) { |
748 |
|
|
return PLUGIN_CONTINUE; |
749 |
|
|
} |
750 |
|
|
|
751 |
|
|
g_hasMolotov[id]--; |
752 |
|
|
engfunc(EngFunc_SetModel, ent, "models/molotov/w_molotov.mdl"); |
753 |
|
|
set_pev(ent, pev_nextthink, 99999.0); |
754 |
|
|
|
755 |
|
|
return PLUGIN_CONTINUE; |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
public grenade_explode(ent) { |
759 |
|
|
|
760 |
|
|
new param[6], iOrigin[3]; |
761 |
|
|
new Float:fOrigin[3]; |
762 |
|
|
new owner = pev(ent, pev_owner); |
763 |
|
|
new ent2 = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target")); |
764 |
|
|
|
765 |
|
|
pev(ent, pev_origin, fOrigin); |
766 |
|
|
|
767 |
|
|
#if defined MOLOTOV_DEBUG |
768 |
|
|
new iOwnerAlive = is_user_alive(owner); |
769 |
|
|
new iOwnerConnected = is_user_connected(owner); |
770 |
|
|
new iEnt2Valid = pev_valid(ent2); |
771 |
|
|
log_amx("[MC] grenade_explode ent(%d) owner(%d) ent2(%d) iOwnerAlive(%d) iOwnerConnected(%d) iEnt2Valid(%d)", ent, owner, ent2, iOwnerAlive, iOwnerConnected, iEnt2Valid); |
772 |
|
|
#endif |
773 |
|
|
|
774 |
|
|
param[0] = ent; |
775 |
|
|
param[1] = ent2; |
776 |
|
|
param[2] = owner; |
777 |
|
|
param[3] = iOrigin[0] = floatround(fOrigin[0]); |
778 |
|
|
param[4] = iOrigin[1] = floatround(fOrigin[1]); |
779 |
|
|
param[5] = iOrigin[2] = floatround(fOrigin[2]); |
780 |
|
|
|
781 |
|
|
emit_sound(ent, CHAN_AUTO, "molotov/molotov_fire.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM); |
782 |
|
|
|
783 |
|
|
engfunc(EngFunc_SetModel, ent, "models/molotov/w_broke_molotov.mdl"); |
784 |
|
|
|
785 |
|
|
random_fire(iOrigin, ent2); |
786 |
|
|
radius_damage(owner, fOrigin, get_pcvar_float(pMlDamage), get_pcvar_float(pMlRadius), DMG_BLAST); |
787 |
|
|
|
788 |
|
|
new Float:FireTime = get_pcvar_float(pFireTime); |
789 |
|
|
|
790 |
|
|
if (++g_Molotov_offset[owner] == MOLOTOV_HARD_LIMIT) { |
791 |
|
|
g_Molotov_offset[owner] = 0; |
792 |
|
|
} |
793 |
|
|
|
794 |
|
|
set_task(0.2, "fire_damage", MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * (owner - 1)) + g_Molotov_offset[owner], param, 6, "a", floatround(FireTime / 0.2, floatround_floor)); |
795 |
|
|
set_task(1.0, "fire_sound", MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * (owner - 1)) + g_Molotov_offset[owner], param, 6, "a", floatround(FireTime) - 1); |
796 |
|
|
set_task(FireTime, "fire_stop", MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * (owner - 1)) + g_Molotov_offset[owner], param, 6); |
797 |
|
|
|
798 |
|
|
return PLUGIN_CONTINUE; |
799 |
|
|
} |
800 |
|
|
|
801 |
|
|
public fire_sound(param[]) { |
802 |
|
|
emit_sound(param[1], CHAN_AUTO, "molotov/molotov_fire.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM); |
803 |
|
|
} |
804 |
|
|
|
805 |
|
|
public fire_stop(param[]) { |
806 |
|
|
g_g = 0; |
807 |
|
|
|
808 |
|
|
if (pev_valid(param[0])) { engfunc(EngFunc_RemoveEntity, param[0]); } |
809 |
|
|
if (pev_valid(param[1])) { engfunc(EngFunc_RemoveEntity, param[1]); } |
810 |
|
|
|
811 |
|
|
if ((last_Molotov_ent = (param[0]))) { |
812 |
|
|
last_Molotov_ent = 0; |
813 |
|
|
} |
814 |
|
|
} |
815 |
|
|
|
816 |
|
|
public fire_damage(param[]) { |
817 |
|
|
|
818 |
|
|
new iOrigin[3], Float:fOrigin[3]; |
819 |
|
|
iOrigin[0] = param[3]; |
820 |
|
|
iOrigin[1] = param[4]; |
821 |
|
|
iOrigin[2] = param[5]; |
822 |
|
|
|
823 |
|
|
random_fire(iOrigin, param[1]); |
824 |
|
|
|
825 |
|
|
IVecFVec(iOrigin, fOrigin); |
826 |
|
|
radius_damage(param[2], fOrigin, get_pcvar_float(pFireDmg), get_pcvar_float(pMlRadius), DMG_BURN, 0); |
827 |
|
|
} |
828 |
|
|
|
829 |
|
|
stock radius_damage(attacker, Float:origin[3], Float:damage, Float:range, dmgtype, calc = 1) { |
830 |
|
|
|
831 |
|
|
new Float:pOrigin[3], Float:dist, Float:tmpdmg; |
832 |
|
|
new i, ateam = get_user_team(attacker), iFF = get_pcvar_num(pFriendlyFire); |
833 |
|
|
|
834 |
|
|
while (i++ < g_MaxPlayers) { |
835 |
|
|
if (!is_user_alive(i)) { |
836 |
|
|
continue; |
837 |
|
|
} |
838 |
|
|
|
839 |
|
|
if (!iFF && ateam == get_user_team(i)) { |
840 |
|
|
continue; |
841 |
|
|
} |
842 |
|
|
|
843 |
|
|
pev(i, pev_origin, pOrigin); |
844 |
|
|
dist = get_distance_f(origin, pOrigin); |
845 |
|
|
|
846 |
|
|
if (dist > range) { |
847 |
|
|
continue; |
848 |
|
|
} |
849 |
|
|
|
850 |
|
|
if (calc) { |
851 |
|
|
tmpdmg = damage - (damage / range) * dist; |
852 |
|
|
} else { |
853 |
|
|
tmpdmg = damage; |
854 |
|
|
} |
855 |
|
|
|
856 |
|
|
if (pev(i, pev_health) < tmpdmg) { |
857 |
|
|
kill(attacker, i); |
858 |
|
|
} else { |
859 |
|
|
fm_fakedamage(i, "molotov", tmpdmg, dmgtype); |
860 |
|
|
} |
861 |
|
|
} |
862 |
|
|
|
863 |
|
|
while ((i = engfunc(EngFunc_FindEntityInSphere, i, origin, range))) { // warning 211: possibly unintended assignment |
864 |
|
|
if (pev(i, pev_takedamage)) { |
865 |
|
|
if (calc) { |
866 |
|
|
pev(i, pev_origin, pOrigin); |
867 |
|
|
tmpdmg = damage - (damage / range) * get_distance_f(origin, pOrigin); |
868 |
|
|
} else { |
869 |
|
|
tmpdmg = damage; |
870 |
|
|
} |
871 |
|
|
fm_fakedamage(i, "molotov", tmpdmg, dmgtype); |
872 |
|
|
} |
873 |
|
|
} |
874 |
|
|
} |
875 |
|
|
|
876 |
|
|
stock random_fire(Origin[3], ent) { |
877 |
|
|
|
878 |
|
|
new range = get_pcvar_num(pMlRadius); |
879 |
|
|
new iOrigin[3]; |
880 |
|
|
|
881 |
|
|
for (new i = 1; i <= 5; i++) { |
882 |
|
|
|
883 |
|
|
g_g = 1; |
884 |
|
|
|
885 |
|
|
iOrigin[0] = Origin[0] + random_num(-range, range); |
886 |
|
|
iOrigin[1] = Origin[1] + random_num(-range, range); |
887 |
|
|
iOrigin[2] = Origin[2]; |
888 |
|
|
iOrigin[2] = ground_z(iOrigin, ent); |
889 |
|
|
|
890 |
|
|
while (get_distance(iOrigin, Origin) > range) { |
891 |
|
|
g_g++; |
892 |
|
|
#if defined MOLOTOV_DEBUG |
893 |
|
|
//log_amx("[MC] random_fire ent(%d) i(%d) g_g(%d)", ent, i, g_g); |
894 |
|
|
#endif |
895 |
|
|
iOrigin[0] = Origin[0] + random_num(-range, range); |
896 |
|
|
iOrigin[1] = Origin[1] + random_num(-range, range); |
897 |
|
|
iOrigin[2] = Origin[2]; |
898 |
|
|
|
899 |
|
|
if (g_g >= ANTI_LAGG) { |
900 |
|
|
iOrigin[2] = ground_z(iOrigin, ent, 1); |
901 |
|
|
} else { |
902 |
|
|
iOrigin[2] = ground_z(iOrigin, ent); |
903 |
|
|
} |
904 |
|
|
} |
905 |
|
|
|
906 |
|
|
new rand = random_num(5, 15); |
907 |
|
|
|
908 |
|
|
message_begin(MSG_BROADCAST, SVC_TEMPENTITY); |
909 |
|
|
write_byte(TE_SPRITE); |
910 |
|
|
write_coord(iOrigin[0]); |
911 |
|
|
write_coord(iOrigin[1]); |
912 |
|
|
write_coord(iOrigin[2] + rand * 5); |
913 |
|
|
write_short(firespr); |
914 |
|
|
write_byte(rand); |
915 |
|
|
write_byte(100); |
916 |
|
|
message_end(); |
917 |
|
|
|
918 |
|
|
if (!(i % 4)) { // Smoke every 4th flame |
919 |
|
|
message_begin(MSG_BROADCAST, SVC_TEMPENTITY); |
920 |
|
|
write_byte(TE_SMOKE); |
921 |
|
|
write_coord(iOrigin[0]); |
922 |
|
|
write_coord(iOrigin[1]); |
923 |
|
|
write_coord(iOrigin[2] + 120); |
924 |
|
|
write_short(smokespr[random_num(0, 1)]); |
925 |
|
|
write_byte(random_num(10, 30)); |
926 |
|
|
write_byte(random_num(10, 20)); |
927 |
|
|
message_end(); |
928 |
|
|
} |
929 |
|
|
} |
930 |
|
|
} |
931 |
|
|
|
932 |
|
|
stock kill(k, v) { |
933 |
|
|
|
934 |
|
|
user_silentkill(v); |
935 |
|
|
|
936 |
|
|
new kteam = get_user_team(k); |
937 |
|
|
new vteam = get_user_team(v); |
938 |
|
|
|
939 |
|
|
new kfrags = get_user_frags(k) + 1; |
940 |
|
|
new kdeaths = get_user_deaths(k); |
941 |
|
|
if (kteam == vteam) { |
942 |
|
|
kfrags = get_user_frags(k) - 2; |
943 |
|
|
} |
944 |
|
|
|
945 |
|
|
new vfrags = get_user_frags(v); |
946 |
|
|
new vdeaths = get_user_deaths(v); |
947 |
|
|
|
948 |
|
|
message_begin(MSG_ALL, gmsgScoreInfo); |
949 |
|
|
write_byte(k); |
950 |
|
|
write_short(kfrags); |
951 |
|
|
write_short(kdeaths); |
952 |
|
|
write_short(0); |
953 |
|
|
write_short(kteam); |
954 |
|
|
message_end(); |
955 |
|
|
|
956 |
|
|
message_begin(MSG_ALL, gmsgScoreInfo); |
957 |
|
|
write_byte(v); |
958 |
|
|
write_short(vfrags + 1); |
959 |
|
|
write_short(vdeaths); |
960 |
|
|
write_short(0); |
961 |
|
|
write_short(vteam); |
962 |
|
|
message_end(); |
963 |
|
|
|
964 |
|
|
message_begin(MSG_ALL, gmsgDeathMsg, {0,0,0}, 0); |
965 |
|
|
write_byte(k); |
966 |
|
|
write_byte(v); |
967 |
|
|
write_byte(0); |
968 |
|
|
write_string("molotov"); |
969 |
|
|
message_end(); |
970 |
|
|
|
971 |
|
|
g_frags[k]++; |
972 |
|
|
|
973 |
|
|
if (kteam != vteam) { |
974 |
|
|
cs_set_user_money(k, cs_get_user_money(k) + 300); |
975 |
|
|
} else { |
976 |
|
|
cs_set_user_money(k, cs_get_user_money(k) - 300); |
977 |
|
|
} |
978 |
|
|
} |
979 |
|
|
|
980 |
|
|
stock ground_z(iOrigin[3], ent, skip = 0, iRecursion = 0) { |
981 |
|
|
|
982 |
|
|
#if defined MOLOTOV_DEBUG |
983 |
|
|
new iEntValid = pev_valid(ent); |
984 |
|
|
if (iRecursion > 0) { |
985 |
|
|
log_amx("[MC] ground_z ent(%d) iEntValid(%d) skip(%d) iRecursion(%d)", ent, iEntValid, skip, iRecursion); |
986 |
|
|
} |
987 |
|
|
#endif |
988 |
|
|
iOrigin[2] += random_num(5, 80); |
989 |
|
|
|
990 |
|
|
if (!pev_valid(ent)) { // Fix for: Run time error 10: native error (native "set_pev") |
991 |
|
|
return iOrigin[2]; |
992 |
|
|
} |
993 |
|
|
|
994 |
|
|
new Float:fOrigin[3]; |
995 |
|
|
|
996 |
|
|
IVecFVec(iOrigin, fOrigin); |
997 |
|
|
|
998 |
|
|
set_pev(ent, pev_origin, fOrigin); |
999 |
|
|
|
1000 |
|
|
engfunc(EngFunc_DropToFloor, ent); |
1001 |
|
|
|
1002 |
|
|
if (!skip && !engfunc(EngFunc_EntIsOnFloor, ent)) { |
1003 |
|
|
if (iRecursion >= ANTI_LAGG) { |
1004 |
|
|
skip = 1; |
1005 |
|
|
} |
1006 |
|
|
#if defined MOLOTOV_DEBUG |
1007 |
|
|
log_amx("[MC] ground_z ++iRecursion(%d)", ++iRecursion); |
1008 |
|
|
return ground_z(iOrigin, ent, skip, iRecursion); |
1009 |
|
|
#else |
1010 |
|
|
return ground_z(iOrigin, ent, skip, ++iRecursion); |
1011 |
|
|
#endif |
1012 |
|
|
} |
1013 |
|
|
|
1014 |
|
|
pev(ent, pev_origin, fOrigin); |
1015 |
|
|
|
1016 |
|
|
return floatround(fOrigin[2]); |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
stock reset_molotovs() { |
1020 |
|
|
new ent = g_MaxPlayers; |
1021 |
|
|
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "model", "models/molotov/w_molotov.mdl"))) { |
1022 |
|
|
engfunc(EngFunc_SetModel, ent, "models/w_hegrenade.mdl"); |
1023 |
|
|
} |
1024 |
|
|
} |
1025 |
|
|
|
1026 |
|
|
stock set_molotovs() { |
1027 |
|
|
new ent = g_MaxPlayers; |
1028 |
|
|
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "model", "models/w_hegrenade.mdl"))) { |
1029 |
|
|
engfunc(EngFunc_SetModel, ent, "models/molotov/w_molotov.mdl"); |
1030 |
|
|
} |
1031 |
|
|
} |
1032 |
|
|
|
1033 |
|
|
// This will run at event New Round if enabled |
1034 |
|
|
public show_molotov_menu(id) { |
1035 |
|
|
new menu[192]; |
1036 |
|
|
|
1037 |
|
|
// Get a custom menu title with the price |
1038 |
|
|
// When done it should look something like this: |
1039 |
|
|
// Buy Molotov Cocktail ($1200)... |
1040 |
|
|
new menu_title_text[120], the_molotov_price[7]; |
1041 |
|
|
get_cvar_string("molotov_price", the_molotov_price, 6); |
1042 |
|
|
strcat(menu_title_text, "Buy Molotov Cocktail ($", 40); |
1043 |
|
|
strcat(menu_title_text, the_molotov_price, 40); |
1044 |
|
|
strcat(menu_title_text, ")?^n^n1. Yes, I will burn them all...^n2. No, I will kill in some other way...^n^n0. EXIT MENU", 119); |
1045 |
|
|
|
1046 |
|
|
format(menu, 191, menu_title_text); |
1047 |
|
|
|
1048 |
|
|
// This shows the menu for 30 seconds, I tried first with get_cvar_num("mp_buytime")*60 , but it didn't work well |
1049 |
|
|
// when using 0.5 as mp_buytime. If you like, just change the time below |
1050 |
|
|
show_menu(id, MOLOTOV_MENU_KEYS, menu, 30); |
1051 |
|
|
|
1052 |
|
|
return PLUGIN_HANDLED; |
1053 |
|
|
} |
1054 |
|
|
|
1055 |
|
|
//Our menu function will get the player id and the key they pressed |
1056 |
|
|
public giveMolotov(id, key) { |
1057 |
|
|
|
1058 |
|
|
//key will start at zero |
1059 |
|
|
if (key == 0) { |
1060 |
|
|
buy_molotov(id); |
1061 |
|
|
} else if (key == 1) { |
1062 |
|
|
client_print(id, print_center, ">You have chosen not to buy a Molotov Coctail<"); |
1063 |
|
|
} else { |
1064 |
|
|
client_print(id, print_center, ">You have choosen to exit the molotov menu...<"); |
1065 |
|
|
} |
1066 |
|
|
} |