Цитата(Legenda @ 8.11.2014, 12:23)

как раз наоборот
есть hlds, он занимает какую-то область в памяти
у эту область входят так же и данные от glibs
плагины, моды, карты и подобное так же работают с памятью...
они обычно криво написаны с кучей ошибок и багов, в итоге фигачат и трут данные от glibs
glibs охреневает от такой наглости и убивает процесс
уверен на 99% что эта проблема вызвана кривым кодов в каком-то плагине, где память через одной место выделяется
Похоже ты прав. Эта проблема иногда вырождается в "Ошибку сегментирования", явно из-за проблемы с выделением памяти.
Это опять плагин Коктейля Молотова....
Можешь глянуть исходный код, в чём там кривизна???
Код:
/**
* Modified by Safety1st
*
* Home post:
* https://c-s.net.ua/forum/index.php?act=find...&pid=670636
*
* Last update:
* 10/19/2014
*
* Changes are:
* - fix: take into account disconnected 'molotov' owners
* - change: improved 'kill' stock, removed frag counting and adding at new round
* - change: the way to set custom weapon models and preallocate string 'info_target' for custom entity
*
* Notes:
* Ignore 'recursive function' warning if compiling under AMXX 1.8.3-dev
*/
/*******************************************************************************
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you must extend this exception
* to your version of the file.
*
********************************************************************************
Molotov Cocktail
Version 3.20
Maintained by: DynamicBits (Andy)
* Commands:
- say molotov - Buy a molotov
- say /molotov - Buy a molotov
- molotov_give <player|@all|@t|@ct|@al|@ax> - Gives molotovs to a player, a team, or everyone
- molotov_cocktail [0|1] - Enable/disable the plugin (If no arguments, show the status)
- molotov_override [0|1] - Enable/disable the HE grenade override (If no arguments, show the status)
* Cvars
- molotov_enabled - Enable/disable the plugin [1 = enabled; 0 = disabled] [default = 1]
- molotov_price - Set the molotov price [default = 1200]
- molotov_damage - Set the damage done by initial molotov explosion [default = 50.0]
- molotov_radius - Set the radius of molotov damage [default = 150.0]
- molotov_firetime - Duration (in seconds) of fire effects, sounds, etc. [default = 6]
- molotov_firedamage - Amount of damage done by fire effects (every 0.2 secs). [default = 3]
- molotov_ff - Disable(0)/enable(1) the ability to damage/kill someone on your team with molotov. [default = 1] (Was molotov_tk)
- molotov_override_he - Override the original hegrenade automatically with molotov. [default = 0] (Was molotov_tempoverride)
- molotov_max - Max num of molotovs able to carry. [default = 1] (Does not work with override)
- molotov_inmenu - Puts molotov in the end of the equipment buymenu (old menu, not VGUI). [default = 0]
(If the override cvar is enabled the hegrenade will be replaced instead.)
- molotov_buyzone - Do you have to be in buyzone? [default = 1] (If molotov_inmenu=1, this is ignored)
- molotov_menu - Enables menu at beginning of each round [default = 0] (Was amx_molotovmenu)
* Required Modules:
- Fakemeta
- Fakemeta Utilities
- Cstrike
* Changelog/Credit:
- DynamicBits
* (SVN)
- Removed unnecessary csx include
- Converted fun functions to fakemeta_util functions (removed fun include)
- Minor optimizations
- Fixed a few typos
* Version 3.20 (2008-11-20)
- My first public release
- Finally tracked down and fixed the intermittent crashing problem (I hope!)
- Modified default damage values
- molotov_cocktail/molotov_override commands now change settings *or* display status
- Broken molotov model stays closer to the explosion (looks more realistic)
- Task IDs are now guaranteed to be unique
- Modified anti-lag calculations to be more accurate (less likely to lag)
- Changed amx_molotovmenu CVAR to molotov_menu
- Changed molotov_tk CVAR to molotov_ff
- Changed molotov_tempoverride CVAR to molotov_override_he
- Preparation for support of mods other than Counter-Strike
- Fixed lots of coding mistakes
- Optimized several sections of code
- Corrected grammar/typos
- Clean up code (Removed unused code/unhelpful comments, fixed formatting, and semicolons!)
- Raffe (CantShoot)
* (Unversioned release)
- Originally fixed plugin to run on Linux servers
- Added optional menu to purchase molotov cocktails each round
- Moved models and sounds into proper molotov/ subdirectories
- Fixed molotovs not being reset upon player disconnect
- (Almost) fixed molotovs not being removed for new round
- Added @all/@ct/@t arguments to cmd_MolotovGive
- Changed some models/sound
- [ --<-@ ] Black Rose
* Version 3.0-3.1c ?
- Unknown changes
- SAMURAI
* Original plugin author
*/
#pragma semicolon 1
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <fakemeta_util>
#include <cstrike>
// Uncomment the following line to enable debug logging.
//#define MOLOTOV_DEBUG
#define AUTHORS "DynamicBits"
#define ADMIN_ACCESS ADMIN_KICK
#define ANTI_LAGG 7.0 // Defines max calculations before a flame is spawned without check if onground
// This is to prevent lagg at really narrow ents where you could end up with 400 calculations per flame
// Suggested: <= 10
#define MOLOTOV_HARD_LIMIT 10 // Maximum molotov cocktails this code is capable of handling without bugs
// Also how many cocktails people get with molotov_give command
#define MOLOTOV_MENU_KEYS MENU_KEY_0|MENU_KEY_1|MENU_KEY_2 // Choices to look for with optional menu
#define MOLOTOV_TASKID_BASE 1000 // What is the lowest task ID?
#define MOLOTOV_TASKID_OFFSET MOLOTOV_HARD_LIMIT
#define MOLOTOV_TASKID_BASE1 MOLOTOV_TASKID_BASE // By default, with 32 players, task ids
#define MOLOTOV_TASKID_BASE2 MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * 32) // from 1000 to 1959 can
#define MOLOTOV_TASKID_BASE3 MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * 32) // potentially be used used.
#define TEAM_UNASSIGNED 0
#define TEAM_ONE 1
#define TEAM_TWO 2
#define TEAM_SPECTATOR 3
new pEnabled, pPrice, pMlDamage, pMlRadius, pFireTime, pOverride;
new pFriendlyFire, pFireDmg, pMaxMolotovs, pBuyMenu, pBuyZone, pMolotovMenu;
new gmsgScoreInfo, gmsgDeathMsg;
new giszInfoTarget, giszModelP, giszModelV;
new g_hasMolotov[33];
new g_restarted;
new g_MaxPlayers;
new g_bomb_map;
new firespr, smokespr[2];
new last_Molotov_ent;
new g_Molotov_offset[33];
new g_g;
public plugin_init() {
register_plugin("Molotov Cocktail", "3.20SVN-s2", AUTHORS);
register_menucmd(register_menuid("Buy Molotov Cocktail"), MOLOTOV_MENU_KEYS, "giveMolotov");
#if defined MOLOTOV_DEBUG
register_clcmd("molotov_menutest", "show_molotov_menu");
#endif
register_clcmd("say /molotov", "buy_molotov");
register_clcmd("say molotov", "buy_molotov");
register_concmd("molotov_give", "cmd_MolotovGive", ADMIN_ACCESS, "<player|@all|@t|@ct|@al|@ax> - Gives free molotov cocktails (default=10)");
register_concmd("molotov_override", "cmd_Override", ADMIN_ACCESS, "[0|1] - Enable/disable the HE grenade override (If no arguments, show the status)");
register_concmd("molotov_cocktail", "cmd_PluginStatus", ADMIN_ACCESS, "[0|1] - Enable/disable the plugin (If no arguments, show the status)");
pEnabled = register_cvar("molotov_enabled", "1", FCVAR_SPONLY);
pOverride = register_cvar("molotov_override_he", "0", FCVAR_SPONLY);
pPrice = register_cvar("molotov_price", "800", FCVAR_SPONLY);
pMlDamage = register_cvar("molotov_damage", "70.0", FCVAR_SPONLY);
pMlRadius = register_cvar("molotov_radius", "150.0", FCVAR_SPONLY);
pFireTime = register_cvar("molotov_firetime", "8", FCVAR_SPONLY);
pFireDmg = register_cvar("molotov_firedamage", "12", FCVAR_SPONLY);
pFriendlyFire = register_cvar("molotov_ff", "1", FCVAR_SPONLY);
pMaxMolotovs = register_cvar("molotov_max", "2", FCVAR_SPONLY);
pBuyMenu = register_cvar("molotov_inmenu", "0", FCVAR_SPONLY);
pBuyZone = register_cvar("molotov_buyzone", "1", FCVAR_SPONLY);
pMolotovMenu = register_cvar("molotov_menu", "0", FCVAR_SPONLY);
register_event("CurWeapon", "Event_CurWeapon", "be", "1=1");
register_event("HLTV", "event_new_round", "a", "1=0", "2=0");
register_event("TextMsg", "Event_GameRestart", "a", "2=#Game_Commencing", "2=#Game_will_restart_in");
register_event("DeathMsg", "event_DeathMsg", "a");
register_event("ShowMenu", "event_BuyMenuT", "b", "4=#T_BuyItem", "1=575");
register_event("ShowMenu", "event_BuyMenuCT", "b", "4=#CT_BuyItem", "1=703");
register_event("ShowMenu", "event_BuyMenuT", "b", "4=#DT_BuyItem", "1=575");
register_event("ShowMenu", "event_BuyMenuCT", "b", "4=#DCT_BuyItem", "1=767");
register_logevent("logevent_Round_End", 2, "1=Round_End");
register_menucmd(register_menuid("#CT_BuyItem"), 1023, "handle_BuyMenuCT");
register_menucmd(register_menuid("#T_BuyItem"), 1023, "handle_BuyMenuT");
register_forward(FM_EmitSound, "fw_EmitSound");
g_MaxPlayers = get_maxplayers();
gmsgScoreInfo = get_user_msgid("ScoreInfo");
gmsgDeathMsg = get_user_msgid("DeathMsg");
giszInfoTarget = engfunc( EngFunc_AllocString, "info_target" );
giszModelP = engfunc(EngFunc_AllocString, "models/molotov/p_molotov.mdl");
giszModelV = engfunc(EngFunc_AllocString, "models/molotov/v_molotov.mdl");
g_bomb_map = engfunc(EngFunc_FindEntityByString, g_MaxPlayers, "classname", "info_bomb_target") ? 1 : 0;
}
public plugin_precache() {
firespr = precache_model("sprites/flame.spr");
smokespr[0] = precache_model("sprites/black_smoke3.spr");
smokespr[1] = precache_model("sprites/steam1.spr");
precache_sound("molotov/molotov_fire.wav");
precache_model("models/molotov/p_molotov.mdl");
precache_model("models/molotov/v_molotov.mdl");
precache_model("models/molotov/w_molotov.mdl");
precache_model("models/molotov/w_broke_molotov.mdl");
}
public client_disconnect(id) {
g_hasMolotov[id] = 0;
}
public fw_EmitSound(ent, channel, sample[]) {
if (equal(sample[8], "he_bounce", 9)) {
new model[32];
pev(ent, pev_model, model, 31);
if (equal(model[9], "lotov/w_molotov.mdl")) {
if (last_Molotov_ent != ent) {
new Float:fFriction, Float:fVelocity[3];
pev(ent, pev_friction, fFriction);
pev(ent, pev_velocity, fVelocity);
fFriction *= 1.3; // Increase friction to make it look more realistic
set_pev(ent, pev_friction, fFriction);
#if defined MOLOTOV_DEBUG
log_amx("[MC] ent:%d Friction:%f Velocity:%f/%f/%f ====================", ent, fFriction, fVelocity[0], fVelocity[1], fVelocity[2]);
#endif
last_Molotov_ent = ent;
grenade_explode(ent);
return FMRES_SUPERCEDE;
#if defined MOLOTOV_DEBUG
} else {
log_amx("[MC] last_Molotov_ent(%d) ent(%d)", last_Molotov_ent, ent);
#endif
}
}
}
return FMRES_IGNORED;
}
public Event_CurWeapon(id) {
if (!get_pcvar_num(pEnabled) || !is_user_alive(id)) {
return PLUGIN_CONTINUE;
}
if (!g_hasMolotov[id] && !get_pcvar_num(pOverride)) {
return PLUGIN_CONTINUE;
}
new WeaponID = get_user_weapon(id, WeaponID, WeaponID);
if (WeaponID != CSW_HEGRENADE) {
return PLUGIN_CONTINUE;
}
set_pev_string(id, pev_viewmodel2, giszModelV);
set_pev_string(id, pev_weaponmodel2, giszModelP);
set_pev(id, pev_weaponanim, 9);
return PLUGIN_CONTINUE;
}
public Event_GameRestart() {
g_restarted = 1;
}
public event_DeathMsg() {
g_hasMolotov[read_data(2)] = 0;
}
public logevent_Round_End() {
#if defined MOLOTOV_DEBUG
log_amx("[MC] ========== Round_End ==========");
#endif
reset_tasks();
}
stock reset_tasks() {
#if defined MOLOTOV_DEBUG
new tmpdbgid;
#endif
for (new i; i < g_MaxPlayers; i++) {
for (new o; o < MOLOTOV_TASKID_OFFSET; o++) { //TODO DEBUG: Verify this fixes the tasks not reset at new round issue
if (task_exists(MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o)) {
remove_task(MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o);
#if defined MOLOTOV_DEBUG
tmpdbgid = MOLOTOV_TASKID_BASE1 + (MOLOTOV_TASKID_OFFSET * i) + o;
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid);
#endif
}
if (task_exists(MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o)) {
remove_task(MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o);
#if defined MOLOTOV_DEBUG
tmpdbgid = MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * i) + o;
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid);
#endif
}
if (task_exists(MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o)) {
remove_task(MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o);
#if defined MOLOTOV_DEBUG
tmpdbgid = MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * i) + o;
log_amx("[MC] %d exists. ----------==========----------", tmpdbgid);
#endif
}
}
}
}
public event_new_round(id) {
#if defined MOLOTOV_DEBUG
log_amx("[MC] ========== event_new_round ==========");
#endif
if (!get_pcvar_num(pEnabled)) {
return PLUGIN_CONTINUE;
}
reset_tasks(); // DEBUG
if (get_pcvar_num(pMolotovMenu)) {
show_molotov_menu(id);
}
if (g_restarted) {
for (new i; i < g_MaxPlayers; i++) {
g_hasMolotov[i] = 0;
}
g_restarted = 0;
}
if (get_pcvar_num(pOverride)) {
set_molotovs();
} else {
reset_molotovs();
}
return PLUGIN_CONTINUE;
}
public cmd_Override(id, level, cid) {
if (!cmd_access(id, level, cid, 1)) { // First argument (passed to molotov_override) is optional
return PLUGIN_HANDLED;
}
if (!get_pcvar_num(pEnabled)) {
return PLUGIN_HANDLED;
}
if (read_argc() == 1) { // No arguments; Display status
client_print(id, print_console, "Override is currently %s.", get_pcvar_num(pOverride) ? "enabled" : "disabled");
return PLUGIN_HANDLED;
}
new arg[2];
read_argv(1, arg, 1);
new num = str_to_num(arg);
if ((num < 0) || (num > 1) || (!isdigit(arg[0]))) { // If less than 0 or greater than 1 or not a digit
if (id) {
client_print(id, print_console, "Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg);
} else {
server_print("Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg);
}
return PLUGIN_HANDLED;
}
if (num == get_pcvar_num(pOverride)) {
if (id) {
client_print(id, print_console, "Override is already %s.", num ? "enabled" : "disabled");
} else {
server_print("Override is already %s.", num ? "enabled" : "disabled");
}
return PLUGIN_HANDLED;
}
set_pcvar_num(pOverride, num);
if (id) {
client_print(id, print_console, "Override was %s.", num ? "enabled" : "disabled");
} else {
server_print("Override was %s.", num ? "enabled" : "disabled");
}
if (num) {
set_molotovs();
} else {
reset_molotovs();
}
return PLUGIN_HANDLED;
}
public cmd_PluginStatus(id, level, cid) {
if (!cmd_access(id, level, cid, 1)) { // First argument (passed to molotov_cocktail) is optional
return PLUGIN_HANDLED;
}
if (read_argc() == 1) { // No arguments; Display status
client_print(id, print_console, "Plugin is currently %s.", get_pcvar_num(pEnabled) ? "enabled" : "disabled");
return PLUGIN_HANDLED;
}
new arg[2];
read_argv(1, arg, 1);
new num = str_to_num(arg);
if ((num < 0) || (num > 1) || (!isdigit(arg[0]))) { // If less than 0 or greater than 1 or not a digit
if (id) {
client_print(id, print_console, "Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg);
} else {
server_print("Invalid argument(%s). Valid arguments are ^"0^" and ^"1^".", arg);
}
return PLUGIN_HANDLED;
}
if (num == get_pcvar_num(pEnabled)) {
if (id) {
client_print(id, print_console, "Plugin is already %s.", num ? "enabled" : "disabled");
} else {
server_print("Plugin is already %s.", num ? "enabled" : "disabled");
}
return PLUGIN_HANDLED;
}
set_pcvar_num(pEnabled, num);
if (id) {
client_print(id, print_console, "Plugin was %s.", num ? "enabled" : "disabled");
} else {
server_print("Plugin was %s.", num ? "enabled" : "disabled");
}
if (num && get_pcvar_num(pOverride)) {
set_molotovs();
} else {
reset_molotovs();
}
return PLUGIN_HANDLED;
}
public cmd_MolotovGive(id, level, cid) {
#if defined MOLOTOV_DEBUG
log_amx("[MC] cmd_MolotovGive");
#endif
if (!cmd_access(id, level, cid, 2)) {
return PLUGIN_HANDLED;
}
new Arg1[64], target;
read_argv(1, Arg1, 63);
new adminName[32];
get_user_name(id, adminName, 31);
new targetTeam, targetTeamName[32];
new Players[32], iNum;
#if defined MOLOTOV_DEBUG
log_amx("[MC] cmd_MolotovGive Arg1[0](%s) Arg1[1](%s)", Arg1[0], Arg1[1]);
#endif
if (Arg1[0] == '@') {
if (equali(Arg1[1], "all")) {
targetTeam = 0;
} else if (equali(Arg1[1], "t") || equali(Arg1[1], "al")) { // CS_TEAM_T or ALLIES
targetTeam = TEAM_ONE;
} else if (equali(Arg1[1], "ct") || equali(Arg1[1], "ax")) { // CS_TEAM_CT or AXIS
targetTeam = TEAM_TWO;
}
get_players(Players, iNum, "ac"); // Bots don't understand molotov cocktails
for (new i = 0; i < iNum; ++i) {
target = Players[i];
if ((targetTeam == 0) || (get_user_team(target) == targetTeam)) {
g_hasMolotov[target] = MOLOTOV_HARD_LIMIT;
fm_give_item(target, "weapon_hegrenade");
cs_set_user_bpammo(target, CSW_HEGRENADE, MOLOTOV_HARD_LIMIT);
emit_sound(target, CHAN_WEAPON, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
}
}
switch(targetTeam) {
case 0: {
targetTeamName = "everyone";
}
case 1: {
if (cstrike_running()) {
targetTeamName = "all terrorists";
} else if (is_running("dod")) {
targetTeamName = "all allies";
} else {
targetTeamName = "team 1";
}
}
case 2: {
if (cstrike_running()) {
targetTeamName = "all ct's";
} else if (is_running("dod")) {
targetTeamName = "all axis";
} else {
targetTeamName = "team 2";
}
}
}
client_print(0, print_chat, "ADMIN %s: has given %s %d Molotov Cocktails!", adminName, targetTeamName, MOLOTOV_HARD_LIMIT);
} else {
target = cmd_target(id, Arg1, 0);
if (!is_user_connected(target) || !is_user_alive(target)) {
return PLUGIN_HANDLED;
}
new targetName[32];
get_user_name(target, targetName, 31);
g_hasMolotov[target] = MOLOTOV_HARD_LIMIT;
fm_give_item(target, "weapon_hegrenade");
cs_set_user_bpammo(target, CSW_HEGRENADE, MOLOTOV_HARD_LIMIT);
emit_sound(target, CHAN_WEAPON, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
client_print(target, print_chat, "ADMIN %s: has given you %d Molotov Cocktails!", adminName, MOLOTOV_HARD_LIMIT);
}
return PLUGIN_HANDLED;
}
public buy_molotov(id) {
if (!get_pcvar_num(pEnabled)) {
return PLUGIN_HANDLED;
}
if (get_pcvar_num(pOverride)) {
if (get_pcvar_num(pBuyMenu)) {
client_print(id, print_center, "Buy them in the buy equipment menu.");
} else {
client_print(id, print_center, "Just buy a HE grenade and get molotov automatically!");
}
return PLUGIN_HANDLED;
}
if (!is_user_alive(id)) {
client_print(id, print_center, "Вы не можете приобрести Молотова пока убиты.");
return PLUGIN_HANDLED;
}
if (!cs_get_user_buyzone(id) && get_pcvar_num(pBuyZone)) {
client_print(id, print_center, "Вы находитесь не в зоне покупки.");
return PLUGIN_HANDLED;
}
new money = cs_get_user_money(id);
if (money < get_pcvar_num(pPrice)) {
client_print(id, print_center, "У Вас не достаточно денег для приобретения Молотова!");
return PLUGIN_HANDLED;
}
if (g_hasMolotov[id] == get_pcvar_num(pMaxMolotovs)) {
if (g_hasMolotov[id] == 1) {
client_print(id, print_center, "Вы уже приобрели Молотова.");
} else {
client_print(id, print_center, "Вы уже приобрели %d Молотова.", g_hasMolotov[id]);
}
return PLUGIN_HANDLED;
}
if (!g_hasMolotov[id] && user_has_weapon(id, CSW_HEGRENADE)) {
client_print(id, print_center, "Вы уже приобрели HE гранату.");
return PLUGIN_HANDLED;
}
cs_set_user_money(id, money - get_pcvar_num(pPrice));
fm_give_item(id, "weapon_hegrenade");
cs_set_user_bpammo(id, CSW_HEGRENADE, ++g_hasMolotov[id]);
client_print(id, print_chat, "Вы приобрели Молотова!");
return PLUGIN_HANDLED;
}
public event_BuyMenuCT(id) {
if (!get_pcvar_num(pEnabled) || !get_pcvar_num(pBuyMenu)) {
return PLUGIN_CONTINUE;
}
new Override = get_pcvar_num(pOverride);
new menu[1024];
new len = formatex(menu, 1023, "\yBuy Equipment\R$ Cost");
len += formatex(menu[len], 1023-len, "^n^n\w1. Kevlar Vest\R\y650");
len += formatex(menu[len], 1023-len, "^n\w2. Kevlar Vest & Helmet\R\y1000");
len += formatex(menu[len], 1023-len, "^n\w3. Flashbang\R\y200");
if (Override) {
len += formatex(menu[len], 1023-len, "^n\w4. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice));
} else {
len += formatex(menu[len], 1023-len, "^n\w4. HE Grenade\R\y300");
}
len += formatex(menu[len], 1023-len, "^n\w5. Smoke Grenade\R\y300");
len += formatex(menu[len], 1023-len, "^n\w6. NightVision Goggles\R\y1250");
len += formatex(menu[len], 1023-len, "^n\%c7. Defuse Kit\R\y200 ", g_bomb_map ? 'w' : 'd');
len += formatex(menu[len], 1023-len, "^n\w8. Tactical Shield\R\y2200");
if (!Override) {
len += formatex(menu[len], 1023-len, "^n\w9. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice));
}
len += formatex(menu[len], 1023-len, "^n^n\w0. Exit");
show_menu(id, read_data(1)|MENU_KEY_9, menu, -1, "#CT_BuyItem");
return PLUGIN_HANDLED;
}
public event_BuyMenuT(id) {
if (!get_pcvar_num(pEnabled) || !get_pcvar_num(pBuyMenu)) {
return PLUGIN_CONTINUE;
}
new Override = get_pcvar_num(pOverride);
new menu[1024];
new len = formatex(menu, 1023, "\yBuy Equipment\R$ Cost");
len += formatex(menu[len], 1023-len, "^n^n\w1. Kevlar Vest\R\y650");
len += formatex(menu[len], 1023-len, "^n\w2. Kevlar Vest & Helmet\R\y1000");
len += formatex(menu[len], 1023-len, "^n\w3. Flashbang\R\y200");
if (Override) {
len += formatex(menu[len], 1023-len, "^n\w4. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice));
} else {
len += formatex(menu[len], 1023-len, "^n\w4. HE Grenade\R\y300");
}
len += formatex(menu[len], 1023-len, "^n\w5. Smoke Grenade\R\y300");
len += formatex(menu[len], 1023-len, "^n\w6. NightVision Goggles\R\y1250");
if (!Override) {
len += formatex(menu[len], 1023-len, "^n\w7. Molotov Cocktail\R\y%d", get_pcvar_num(pPrice));
}
len += formatex(menu[len], 1023-len, "^n^n\w0. Exit");
show_menu(id, read_data(1)|MENU_KEY_7, menu, -1, "#T_BuyItem");
return PLUGIN_HANDLED;
}
public handle_BuyMenuCT(id, key) {
if (key == (get_pcvar_num(pOverride) ? 3 : 8)) {
handle_BuyMenu(id);
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
public handle_BuyMenuT(id, key) {
if (key == (get_pcvar_num(pOverride) ? 3 : 6)) {
handle_BuyMenu(id);
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
stock handle_BuyMenu(id) {
new money = cs_get_user_money(id);
if (money < get_pcvar_num(pPrice)) {
client_print(id, print_center, "You don't have enough $ to buy a Molotov Cocktail.");
return PLUGIN_HANDLED;
}
if (g_hasMolotov[id] == get_pcvar_num(pMaxMolotovs)) {
if (g_hasMolotov[id] == 1) {
client_print(id, print_center, "You already have a Molotov Cocktail.");
} else {
client_print(id, print_center, "You already have %d Molotov Cocktails.", g_hasMolotov[id]);
}
return PLUGIN_HANDLED;
} else if (!g_hasMolotov[id] && user_has_weapon(id, CSW_HEGRENADE)) {
client_print(id, print_center, "You already have a HE Grenade.");
return PLUGIN_HANDLED;
}
cs_set_user_money(id, money - get_pcvar_num(pPrice));
fm_give_item(id, "weapon_hegrenade");
cs_set_user_bpammo(id, CSW_HEGRENADE, ++g_hasMolotov[id]);
client_print(id, print_chat, "You got a Molotov Cocktail!");
return PLUGIN_HANDLED;
}
public grenade_throw(id, ent, wid) {
if (!get_pcvar_num(pEnabled) || !is_user_connected(id) || wid != CSW_HEGRENADE) {
return PLUGIN_CONTINUE;
}
if (!g_hasMolotov[id] && !get_pcvar_num(pOverride)) {
return PLUGIN_CONTINUE;
}
g_hasMolotov[id]--;
engfunc(EngFunc_SetModel, ent, "models/molotov/w_molotov.mdl");
set_pev(ent, pev_nextthink, 99999.0);
return PLUGIN_CONTINUE;
}
public grenade_explode(ent) {
new param[6], iOrigin[3];
new Float:fOrigin[3];
new owner = pev(ent, pev_owner);
new ent2 = engfunc( EngFunc_CreateNamedEntity, giszInfoTarget );
pev(ent, pev_origin, fOrigin);
#if defined MOLOTOV_DEBUG
new iOwnerAlive = is_user_alive(owner);
new iOwnerConnected = is_user_connected(owner);
new iEnt2Valid = pev_valid(ent2);
log_amx("[MC] grenade_explode ent(%d) owner(%d) ent2(%d) iOwnerAlive(%d) iOwnerConnected(%d) iEnt2Valid(%d)", ent, owner, ent2, iOwnerAlive, iOwnerConnected, iEnt2Valid);
#endif
param[0] = ent;
param[1] = ent2;
param[2] = owner;
param[3] = iOrigin[0] = floatround(fOrigin[0]);
param[4] = iOrigin[1] = floatround(fOrigin[1]);
param[5] = iOrigin[2] = floatround(fOrigin[2]);
emit_sound(ent, CHAN_AUTO, "molotov/molotov_fire.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
engfunc(EngFunc_SetModel, ent, "models/molotov/w_broke_molotov.mdl");
random_fire(iOrigin, ent2);
radius_damage(owner, fOrigin, get_pcvar_float(pMlDamage), get_pcvar_float(pMlRadius), DMG_BLAST);
new Float:FireTime = get_pcvar_float(pFireTime);
if (++g_Molotov_offset[owner] == MOLOTOV_HARD_LIMIT) {
g_Molotov_offset[owner] = 0;
}
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));
set_task(1.0, "fire_sound", MOLOTOV_TASKID_BASE2 + (MOLOTOV_TASKID_OFFSET * (owner - 1)) + g_Molotov_offset[owner], param, 6, "a", floatround(FireTime) - 1);
set_task(FireTime, "fire_stop", MOLOTOV_TASKID_BASE3 + (MOLOTOV_TASKID_OFFSET * (owner - 1)) + g_Molotov_offset[owner], param, 6);
return PLUGIN_CONTINUE;
}
public fire_sound(param[]) {
emit_sound(param[1], CHAN_AUTO, "molotov/molotov_fire.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
}
public fire_stop(param[]) {
g_g = 0;
if (pev_valid(param[0])) { engfunc(EngFunc_RemoveEntity, param[0]); }
if (pev_valid(param[1])) { engfunc(EngFunc_RemoveEntity, param[1]); }
if ((last_Molotov_ent = (param[0]))) {
last_Molotov_ent = 0;
}
}
public fire_damage(param[]) {
new iOrigin[3], Float:fOrigin[3];
iOrigin[0] = param[3];
iOrigin[1] = param[4];
iOrigin[2] = param[5];
random_fire(iOrigin, param[1]);
IVecFVec(iOrigin, fOrigin);
radius_damage(param[2], fOrigin, get_pcvar_float(pFireDmg), get_pcvar_float(pMlRadius), DMG_BURN, 0);
}
stock radius_damage(attacker, Float:origin[3], Float:damage, Float:range, dmgtype, calc = 1) {
new Float:pOrigin[3], Float:dist, Float:tmpdmg;
new i, ateam = get_user_team(attacker), iFF = get_pcvar_num(pFriendlyFire);
while (i++ < g_MaxPlayers) {
if (!is_user_alive(i)) {
continue;
}
if (!iFF && ateam == get_user_team(i)) {
continue;
}
pev(i, pev_origin, pOrigin);
dist = get_distance_f(origin, pOrigin);
if (dist > range) {
continue;
}
if (calc) {
tmpdmg = damage - (damage / range) * dist;
} else {
tmpdmg = damage;
}
if (pev(i, pev_health) < tmpdmg) {
kill(attacker, i);
} else {
fm_fakedamage(i, "molotov", tmpdmg, dmgtype);
}
}
while ((i = engfunc(EngFunc_FindEntityInSphere, i, origin, range))) { // warning 211: possibly unintended assignment
if (pev(i, pev_takedamage)) {
if (calc) {
pev(i, pev_origin, pOrigin);
tmpdmg = damage - (damage / range) * get_distance_f(origin, pOrigin);
} else {
tmpdmg = damage;
}
fm_fakedamage(i, "molotov", tmpdmg, dmgtype);
}
}
}
stock random_fire(Origin[3], ent) {
new range = get_pcvar_num(pMlRadius);
new iOrigin[3];
for (new i = 1; i <= 5; i++) {
g_g = 1;
iOrigin[0] = Origin[0] + random_num(-range, range);
iOrigin[1] = Origin[1] + random_num(-range, range);
iOrigin[2] = Origin[2];
iOrigin[2] = ground_z(iOrigin, ent);
while (get_distance(iOrigin, Origin) > range) {
g_g++;
#if defined MOLOTOV_DEBUG
//log_amx("[MC] random_fire ent(%d) i(%d) g_g(%d)", ent, i, g_g);
#endif
iOrigin[0] = Origin[0] + random_num(-range, range);
iOrigin[1] = Origin[1] + random_num(-range, range);
iOrigin[2] = Origin[2];
if (g_g >= ANTI_LAGG) {
iOrigin[2] = ground_z(iOrigin, ent, 1);
} else {
iOrigin[2] = ground_z(iOrigin, ent);
}
}
new rand = random_num(5, 15);
message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
write_byte(TE_SPRITE);
write_coord(iOrigin[0]);
write_coord(iOrigin[1]);
write_coord(iOrigin[2] + rand * 5);
write_short(firespr);
write_byte(rand);
write_byte(100);
message_end();
if (!(i % 4)) { // Smoke every 4th flame
message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
write_byte(TE_SMOKE);
write_coord(iOrigin[0]);
write_coord(iOrigin[1]);
write_coord(iOrigin[2] + 120);
write_short(smokespr[random_num(0, 1)]);
write_byte(random_num(10, 30));
write_byte(random_num(10, 20));
message_end();
}
}
}
stock kill(k, v) {
/* note: prefer 'cstrike' module natives for player team and deaths because
they operate with pvPrivateData offsets as the mod does.
In other words we use 'natural' CS 1.6 way to manipulate specific data. */
user_silentkill(v);
new killer_connected = is_user_connected(k);
message_begin(MSG_ALL, gmsgDeathMsg);
write_byte( killer_connected ? k : 0 /* the same as default game behaviour*/ );
write_byte(v);
write_byte(0);
write_string("molotov");
message_end();
cs_set_user_deaths( v, cs_get_user_deaths(v) + 1 ); // 'ScoreInfo' msg is sent automatically
if( !killer_connected )
return;
new kteam = _:cs_get_user_team(k);
new kfrags = get_user_frags(k);
if( kteam != _:cs_get_user_team(v) ) {
fm_set_user_frags( k, ++kfrags );
cs_set_user_money( k, cs_get_user_money(k) + 300 );
}
else { // is is a team kill
kfrags -= 2;
fm_set_user_frags( k, kfrags );
cs_set_user_money( k, cs_get_user_money(k) - 300 );
}
message_begin(MSG_ALL, gmsgScoreInfo);
write_byte(k);
write_short(kfrags);
write_short( cs_get_user_deaths(k) );
write_short(0);
write_short(kteam);
message_end();
}
stock ground_z(iOrigin[3], ent, skip = 0, iRecursion = 0) {
#if defined MOLOTOV_DEBUG
new iEntValid = pev_valid(ent);
if (iRecursion > 0) {
log_amx("[MC] ground_z ent(%d) iEntValid(%d) skip(%d) iRecursion(%d)", ent, iEntValid, skip, iRecursion);
}
#endif
iOrigin[2] += random_num(5, 80);
if (!pev_valid(ent)) { // Fix for: Run time error 10: native error (native "set_pev")
return iOrigin[2];
}
new Float:fOrigin[3];
IVecFVec(iOrigin, fOrigin);
set_pev(ent, pev_origin, fOrigin);
engfunc(EngFunc_DropToFloor, ent);
if (!skip && !engfunc(EngFunc_EntIsOnFloor, ent)) {
if (iRecursion >= ANTI_LAGG) {
skip = 1;
}
#if defined MOLOTOV_DEBUG
log_amx("[MC] ground_z ++iRecursion(%d)", ++iRecursion);
return ground_z(iOrigin, ent, skip, iRecursion);
#else
return ground_z(iOrigin, ent, skip, ++iRecursion);
#endif
}
pev(ent, pev_origin, fOrigin);
return floatround(fOrigin[2]);
}
stock reset_molotovs() {
new ent = g_MaxPlayers;
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "model", "models/molotov/w_molotov.mdl"))) {
engfunc(EngFunc_SetModel, ent, "models/w_hegrenade.mdl");
}
}
stock set_molotovs() {
new ent = g_MaxPlayers;
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "model", "models/w_hegrenade.mdl"))) {
engfunc(EngFunc_SetModel, ent, "models/molotov/w_molotov.mdl");
}
}
// This will run at event New Round if enabled
public show_molotov_menu(id) {
new menu[128];
formatex(menu, 127, "Buy Molotov Cocktail ($%d)?^n^n1. Yes^n2. No^n^n0. Exit", get_pcvar_num(pPrice));
// This shows the menu for 30 seconds, I tried first with get_cvar_num("mp_buytime")*60 , but it didn't work well
// when using 0.5 as mp_buytime. If you like, just change the time below
show_menu(id, MOLOTOV_MENU_KEYS, menu, 30);
return PLUGIN_HANDLED;
}
//Our menu function will get the player id and the key they pressed
public giveMolotov(id, key) {
//key will start at zero
switch(key) {
case 0: buy_molotov(id);
case 1: client_print(id, print_center, "You have chosen not to buy a Molotov cocktail");
default: client_print(id, print_center, "You have chosen to exit the Molotov menu");
}
}