Заранее спасибо за помощь !
- Код: Выделить всё
#include <amxmodx> // AMX Mod X 1.71+ required, check your addons/metamod/plugins.ini
#include <fakemeta> // fakemeta module required, check your configs/modules.ini
#include <xs> // this is not a module!
// plugin's main information
#define PLUGIN_NAME "Dropped Bomb Defuse"
#define PLUGIN_VERSION "0.3.1"
#define PLUGIN_AUTHOR "VEN"
// OPTIONS BELOW
// comment to disable force team win on dropped bomb defuse
#define FORCE_TEAM_WIN
// comment to disable check for bomb maps
#define BOMB_MAP_CHECK
// multiplier * dbd_time == defuse time with a defkit
#define DEFKIT_TIME_MULTIPLIER 0.5
// comment to not ignore the above multiplier when dbd_defkit_required CVAR is 1
#define IGNORE_MULTIPLIER
// defuser frag bonus, comment or set to 0 to disable this feature
#define DEFUSER_FRAG_BONUS 1
// max. allowed distance from a CT to a dropped bomb
#define MAX_DISTANCE 70
// max. allowed angle difference between CT's view vector and bomb position
#define MAX_VIEWANGLE_DIFF 35
// name of the CVAR which controls dropped bomb defuse time
#define CVAR_TIME_NAME "dbd_time"
// default value of the "dbd_time" CVAR
#define CVAR_TIME_DEF "25"
// name of the CVAR which controls defkit requirement
#define CVAR_DEFKIT_NAME "dbd_defkit_required"
// default value of the "dbd_defkit_required" CVAR
#define CVAR_DEFKIT_DEF "0"
// requirement center text message
new g_requirement[] = "The defuser kit is required!"
// uncomment to disable automatic 32/64bit processor detection
// possible values are <0: 32bit | 1: 64bit>
//#define PROCESSOR_TYPE 0
// OPTIONS ABOVE
// private data deaths offset
#define OFFSET_DEATHS_32BIT 444
#define OFFSET_DEATHS_64BIT 493
// deaths offset linux difference
#define OFFSET_DEATHS_LINUXDIFF 5
// determination of actual offsets
#if !defined PROCESSOR_TYPE // is automatic 32/64bit processor detection?
#if cellbits == 32 // is the size of a cell are 32 bits?
// then considering processor as 32bit
#define OFFSET_DEATHS OFFSET_DEATHS_32BIT
#else // in other case considering the size of a cell as 64 bits
// and then considering processor as 64bit
#define OFFSET_DEATHS OFFSET_DEATHS_64BIT
#endif
#else // processor type specified by PROCESSOR_TYPE define
#if PROCESSOR_TYPE == 0 // 32bit processor defined
#define OFFSET_DEATHS OFFSET_DEATHS_32BIT
#else // considering that 64bit processor defined
#define OFFSET_DEATHS OFFSET_DEATHS_64BIT
#endif
#endif
#define CS_GET_USER_DEATHS_(%1) get_pdata_int(%1, OFFSET_DEATHS, OFFSET_DEATHS_LINUXDIFF)
// checks whether force team win is enabled and if so includes a native
#if defined FORCE_TEAM_WIN
#include <ftw> // ftw.inc, includes cs_force_team_win native, uses "Force Team Win"
#endif
#define TASK_INTERVAL 0.2
#define TASK_INDEX 349576
#define IN_USE (1<<5)
#define SOLID_NOT 0
#define EF_NODRAW 128
new CsTeams:CS_TEAM_CT = CsTeams:2
new g_wpn_denyselect[] = "common/wpn_denyselect.wav"
new g_wpn_select[] = "common/wpn_select.wav"
new g_classname[] = "classname"
new g_weapon_c4[] = "weapon_c4"
new g_disarm[] = "weapons/c4_disarm.wav"
new g_disarmed[] = "weapons/c4_disarmed.wav"
new g_defused_audio[] = "%!MRAD_BOMBDEF"
new g_defused_text[] = "#Bomb_Defused"
new g_pcvar_time
new g_pcvar_defkit
new g_msgid_bartime
new g_msgid_scoreinfo
new g_msgid_bombpickup
new g_msgid_audio
new g_msgid_text
new g_maxplayers
new g_defuser
new Float:g_time_left
#define MAX_PLAYERS 32
new bool:g_has_defuser[MAX_PLAYERS + 1]
public plugin_init() {
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
g_pcvar_time = register_cvar(CVAR_TIME_NAME, CVAR_TIME_DEF)
g_pcvar_defkit = register_cvar(CVAR_DEFKIT_NAME, CVAR_DEFKIT_DEF)
#if defined BOMB_MAP_CHECK
if (!engfunc(EngFunc_FindEntityByString, -1, g_classname, "func_bomb_target"))
return
#endif
register_event("StatusIcon", "event_deficon", "b", "2=defuser")
register_event("DeathMsg", "event_death", "a")
register_forward(FM_EmitSound, "forward_emit_sound")
g_msgid_bartime = get_user_msgid("BarTime")
g_msgid_scoreinfo = get_user_msgid("ScoreInfo")
g_msgid_bombpickup = get_user_msgid("BombPickup")
g_msgid_audio = get_user_msgid("SendAudio")
g_msgid_text = get_user_msgid("TextMsg")
g_maxplayers = get_maxplayers()
}
/* *************************************************** Base **************************************************** */
public event_deficon(id) {
g_has_defuser[id] = bool:read_data(1)
}
public event_death() {
new id = read_data(2)
if (g_defuser == id && task_exists(TASK_INDEX)) {
remove_task(TASK_INDEX)
msg_bartime(id, 0)
}
}
public client_disconnect(id) {
if (task_exists(TASK_INDEX) && g_defuser == id)
remove_task(TASK_INDEX)
}
public forward_emit_sound(id, channel, sound[]) {
if (!id || !equali(sound, g_wpn_denyselect) || !is_user_alive(id) || !(pev(id, pev_button) & IN_USE) || get_user_team(id) != _:CS_TEAM_CT)
return FMRES_IGNORED
new itime = get_pcvar_num(g_pcvar_time)
if (!itime || !can_disarm(id))
return FMRES_IGNORED
if (task_exists(TASK_INDEX)) {
if (id != g_defuser)
emit_sound(id, CHAN_ITEM, g_wpn_select, 0.4, ATTN_NORM, 0, PITCH_NORM)
return FMRES_SUPERCEDE
}
new bool:dk_required = bool:get_pcvar_num(g_pcvar_defkit)
if (g_has_defuser[id]) {
#if defined IGNORE_MULTIPLIER
if (dk_required)
g_time_left = float(itime)
else {
g_time_left = itime * DEFKIT_TIME_MULTIPLIER
itime = floatround(g_time_left)
}
#else
g_time_left = itime * DEFKIT_TIME_MULTIPLIER
itime = floatround(g_time_left)
#endif
}
else {
if (dk_required) {
client_print(id, print_center, g_requirement)
return FMRES_IGNORED
}
g_time_left = float(itime)
}
g_defuser = id
msg_bartime(id, itime)
emit_sound(id, CHAN_ITEM, g_disarm, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
set_task(TASK_INTERVAL, "task_check", TASK_INDEX, _, _, "a", floatround(g_time_left / TASK_INTERVAL))
return FMRES_SUPERCEDE
}
public task_check() {
g_time_left -= TASK_INTERVAL
new bomb = can_disarm(g_defuser)
if (!bomb || !(pev(g_defuser, pev_button) & IN_USE)) {
msg_bartime(g_defuser, 0)
remove_task(TASK_INDEX)
}
else if (g_time_left < TASK_INTERVAL) {
remove_task(TASK_INDEX)
msg_bartime(g_defuser, 0)
emit_sound(g_defuser, CHAN_WEAPON, g_disarmed, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
#if defined DEFUSER_FRAG_BONUS
#if DEFUSER_FRAG_BONUS
new Float:frags
pev(g_defuser, pev_frags, frags)
frags += DEFUSER_FRAG_BONUS
set_pev(g_defuser, pev_frags, frags)
message_begin(MSG_ALL, g_msgid_scoreinfo)
write_byte(g_defuser)
write_short(floatround(frags))
write_short(CS_GET_USER_DEATHS_(g_defuser))
write_short(0)
write_short(get_user_team(g_defuser))
message_end()
#endif
#endif
set_pev(bomb, pev_solid, SOLID_NOT)
set_pev(bomb, pev_effects, EF_NODRAW)
message_begin(MSG_ALL, g_msgid_bombpickup)
message_end()
#if defined FORCE_TEAM_WIN
cs_force_team_win(CS_TEAM_CT)
#endif
message_begin(MSG_BROADCAST, g_msgid_audio)
write_byte(0)
write_string(g_defused_audio)
write_short(100)
message_end()
message_begin(MSG_ALL, g_msgid_text)
write_byte(print_center)
write_string(g_defused_text)
message_end()
}
}
can_disarm(id) {
new c4 = engfunc(EngFunc_FindEntityByString, -1, g_classname, g_weapon_c4)
if (!c4)
return 0
new bomb = pev(c4, pev_owner)
if (bomb <= g_maxplayers || !pev(bomb, pev_solid))
return 0
new Float:origin[3], Float:bombpos[3]
pev(id, pev_origin, origin)
pev(bomb, pev_origin, bombpos)
if (get_distance_f(origin, bombpos) > MAX_DISTANCE || !fm_is_visible(id, bombpos) || get_view_angle_diff(id, bombpos) > MAX_VIEWANGLE_DIFF)
return 0
return bomb
}
msg_bartime(index, scale) {
message_begin(MSG_ONE, g_msgid_bartime, _, index)
write_short(scale)
message_end()
}
/* ************************************************** Stocks *************************************************** */
// checks whether no obstacles between eyes and given point
stock bool:fm_is_visible(index, const Float:point[3]) {
new Float:origin[3], Float:view_ofs[3], Float:eyespos[3]
pev(index, pev_origin, origin)
pev(index, pev_view_ofs, view_ofs)
xs_vec_add(origin, view_ofs, eyespos)
engfunc(EngFunc_TraceLine, eyespos, point, 0, index)
new Float:fraction
global_get(glb_trace_fraction, fraction)
if (fraction == 1.0)
return true
return false
}
// returns a float degree angle between view vector and given point
stock Float:get_view_angle_diff(index, Float:vec_c[3]) {
new Float:vec_a[3], Float:vec_b[3], viewend[3]
new Float:origin[3], Float:view_ofs[3]
pev(index, pev_origin, origin)
pev(index, pev_view_ofs, view_ofs)
xs_vec_add(origin, view_ofs, vec_a)
get_user_origin(index, viewend, 3)
vec_b[0] = float(viewend[0])
vec_b[1] = float(viewend[1])
vec_b[2] = float(viewend[2])
new Float:a = get_distance_f(vec_b, vec_c)
new Float:b = get_distance_f(vec_a, vec_c)
new Float:c = get_distance_f(vec_a, vec_b)
return floatacos((b*b + c*c - a*a) / (2 * b * c), _:degrees)
}
/* **************************************************** EOF **************************************************** */