/* Formatright © 2009, OT
Sound Block 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.
GNU General Public License as published by the Free Software Foundation.
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 Migraine; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* [Plugin Link]
*/
/* [Changelog]
- 8.0 - fixed crash bug, fixed high cpu usage bug, added also support for ent sounds and reloadsound
- 7.0 - made the plugin use spawnStaticSound, now this can fully block ESP
- 6.3 - soundhackkey not compatible with older soundkeys, added more sounds to block the soundhacks, extended the block to entities that would give info about the player.
- 6.2 - the plugin cannot be seen on game-monitor anymore (for surprize)
- 6.1 - Remade the function that gets the coords of the ground, more efficient, and faster, not laggy
- 6.0 - Well well, 100% CPU USAGE improvement, no more shot blockage
- 5.6 - Fixed the amxx crash bug when soundkey has been used
- 5.5 - Changed the way the command of creating soundkey works, added log to files, added more cvars for configuration, and miscelanous things
- 5.4 - Anti-Soundhack shot, pick-up and spawn
- 5.3 - Separated the channels from the shot mechanism (now we have the sound of the shot, the bullet particles and the weapon animation separated!)
- 5.2 - Fixed double jump/land sound, made the soundkey use less resources if the sounds that are used are default, removed PVS cvar (useless), new cvar wallblocker_footsteps
- 5.1 - PreHook fix, EmitAmbientSound function used, update key (more random and better when dealing with problems!)
- 5.0 - Added anti-soundhack based with key, made the ents follow the players much closer
- 4.8 - Less crash risk, new method of detecting transparent ents and making them transperent will not destroy ladded functionality anymore!!!
- 4.5 - texture check now isn't made that often (less crash risk!), added texture check autodisable cfg, added a new method to ignore entities that are transparent (100% efficient), reupdated the weapon headpoint
- 4.2 - added bitsum remember system, smooth check is made now by FRAME_CONSTANT (1/48), changed alive/dead recognision system (less resource use!)
- 4.1 - fixed plugin_init problem!
- 4.0 - all bugs fixed, added texture check , everything tweaked and tuned!
- 3.0 - removed Engine module (another method), improved smooth engine, removed , fixed flashing bug, target check now works both ways (if you are seen the player will be shown!)
- 2.5 - removed HamSandWich module (useless), improved smooth check, corpse remove bug fixed, optimized the code a little bit.
- 2.4 - bug fix release (weapon index out of bounds fix, reconnect bug fix (with CSDM), made the ent check not so sensitive (not so many blind-spots)
- 2.2 - bug fix release (index out of bounds & weapon confusion bug)
- 2.1 - removed a bugged feature (block_dead cvar), added smooth cvar
- 2.0 - more customizable, less cpu usage (50% TESTED!), weapons grenades check added, bug fixes
- 1.5 - removed some checks, optimized it a bit, added weapon head-point check
- 1.0 - initial release
*/
/* [Credits]
- joropito - for compiling engineX on linux
- hlstriker - for finding the way to detect semi-transparent textures!
- h010c - for tests and benchmarks, anti-soundhack tests and code samples
- joaquimandrade - for pointing out the plugin flaws, and for the Orpheu module
- Connor - some stocks
- Arkshine - for finding precise weapon head points, and for some sig files, spawnStaticSound
- Mnx Community - for letting me test this plugin on linux!
- turshija - for some small suggestions.
- .Owyn. - bug reports
- ShlumPF* - for small improvements (initial v1.0)
- eD & Niculae - for some tests
*/
#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fakemeta>
#include <engine>
#include <hamsandwich>
#include <orpheu>
#include <orpheu_advanced>
#include <orpheu_memory>
#include <orpheu_stocks>
#define MAX_PLAYERS 32
#define BUFFERSIZE 256
#define m_pPlayer 41
#define m_pNext 42
#define m_iId 43
// texture types
#define CHAR_TEX_CONCRETE 'C'
#define CHAR_TEX_METAL 'M'
#define CHAR_TEX_SNOW 'N'
#define CHAR_TEX_DIRT 'D'
#define CHAR_TEX_VENT 'V'
#define CHAR_TEX_GRATE 'G'
#define CHAR_TEX_TILE 'T'
#define CHAR_TEX_SLOSH 'S'
#define CHAR_TEX_WOOD 'W'
#define CHAR_TEX_COMPUTER 'P'
#define CHAR_TEX_GLASS 'Y'
#define CHAR_TEX_FLESH 'F'
// Step Types
#define STEP_CONCRETE 0 // default step sound
#define STEP_METAL 1 // metal floor
#define STEP_DIRT 2 // dirt, sand, rock
#define STEP_VENT 3 // ventillation duct
#define STEP_GRATE 4 // metal grating
#define STEP_TILE 5 // floor tiles
#define STEP_SLOSH 6 // shallow liquid puddle
#define STEP_WADE 7 // wading in liquid
#define STEP_LADDER 8 // climbing ladder
#define STEP_SNOW 9 // snow
// Footsteps generator constants
#define FOOTSTEP_DIST 14.0
#define SND_ZVELOCITY 0.0
#define SND_MOVEVELOCITY 136.0
#define OFFSET_MINTRACE 70.0
#define SND_MULCONST 0.1
#define SHOTGUNS_BITSUM ((1<<CSW_XM1014) | (1<<CSW_M3))
#define SMGS_BITSUM ((1<<CSW_MAC10) | (1<<CSW_UMP45) | (1<<CSW_MP5NAVY) | (1<<CSW_TMP) | (1<<CSW_P90))
#define RIFFLES_BITSUM ((1<<CSW_AUG) | (1<<CSW_GALIL) | (1<<CSW_FAMAS) | (1<<CSW_M249) | (1<<CSW_M4A1) | (1<<CSW_SG552) | (1<<CSW_AK47))
#define SNIPERS_BITSUM ((1<<CSW_SCOUT) | (1<<CSW_SG550) | (1<<CSW_AWP) | (1<<CSW_G3SG1))
#define PRIMARIES_BITSUM (SHOTGUNS_BITSUM|SMGS_BITSUM|RIFFLES_BITSUM|SNIPERS_BITSUM)
#define GUNS_BITSUM ((1<<CSW_P228) | (1<<CSW_ELITE) | (1<<CSW_FIVESEVEN) | (1<<CSW_USP) | (1<<CSW_GLOCK18) | (1<<CSW_DEAGLE))
#define NADES_BITSUM ((1<<CSW_HEGRENADE) | (1<<CSW_SMOKEGRENADE) | (1<<CSW_FLASHBANG))
#define MAX_ITEM_TYPES 6
new const m_rgpPlayerItems[MAX_ITEM_TYPES] = {367,368,369,370,371,372}
#define EXTRAOFFSET_WEAPONS 4
#define EXTRAOFFSET 5
enum FWrite
{
FW_NONE = 0,
FW_DELETESOURCE = (1<<0),
FW_CANOVERRIDE = (1<<1)
}
new gBS_Alive, gBS_GunsEvents, gBS_SpectatesFirstPerson
#define add_alive_property(%1) gBS_Alive |= (1<<%1)
#define del_alive_property(%1) gBS_Alive &= ~(1<<%1)
#define has_alive_property(%1) (gBS_Alive & (1<<%1))
#define add_spect_property(%1) gBS_SpectatesFirstPerson |= (1<<%1)
#define del_spect_property(%1) gBS_SpectatesFirstPerson &= ~(1<<%1)
#define has_spect_property(%1) (gBS_SpectatesFirstPerson & (1<<%1))
#define clamp_byte(%1) (clamp(%1, 0, 255))
#define clamp_short(%1) (clamp(%1, 0, 65535))
#define write_coord_f(%1) (engfunc(EngFunc_WriteCoord, %1))
#define null_vector (Float:{ 0.0, 0.0, 0.0 })
new gPCV_on_off, gPCV_footsteps, gPCV_shotover
new gI_MaxPlayers,gI_SoundSize
new gCLI_oldwaterlevel[MAX_PLAYERS + 1], gCLI_iStepLeft[MAX_PLAYERS + 1], gCLI_oldflags[MAX_PLAYERS + 1]
new bool:gB_DefaultSounds = false, bool:gB_loaded = true
new gDecal_shot1
new gSZ_SoundMod[128][60]
new gF_sndkey[300]
new gPSND_Indexes[10]
new Trie:gTRIE_SoundList, Trie:gTRIE_TraceRegs
new const gSZ_SoundList[105][] =
{
"items/9mmclip1.wav",
"items/ammopickup2.wav",
"items/gunpickup2.wav",
"items/kevlar.wav",
"common/wpn_select.wav",
"weapons/c4_plant.wav",
"weapons/c4_disarm.wav",
"weapons/reload1.wav",
"weapons/reload2.wav",
"weapons/reload3.wav",
"weapons/ric_metal-1.wav",
"weapons/ric_metal-2.wav",
"player/pl_die1.wav",
"player/pl_fallpain1.wav",
"player/pl_fallpain2.wav",
"player/pl_fallpain3.wav",
"player/pl_pain2.wav",
"player/pl_pain4.wav",
"player/pl_pain5.wav",
"player/pl_pain6.wav",
"player/pl_pain7.wav",
"player/pl_shell1.wav",
"player/pl_shot1.wav",
"player/sprayer.wav",
"player/bhit_flesh-1.wav",
"player/bhit_flesh-2.wav",
"player/bhit_flesh-3.wav",
"player/bhit_helmet-1.wav",
"player/bhit_kevlar-1.wav",
"player/headshot1.wav",
"player/headshot2.wav",
"player/headshot3.wav",
"player/pl_dirt1.wav",
"player/pl_dirt2.wav",
"player/pl_dirt3.wav",
"player/pl_dirt4.wav",
"player/pl_duct1.wav",
"player/pl_duct2.wav",
"player/pl_duct3.wav",
"player/pl_duct4.wav",
"player/pl_jump1.wav",
"player/pl_jump2.wav",
"player/pl_ladder1.wav",
"player/pl_ladder2.wav",
"player/pl_ladder3.wav",
"player/pl_ladder4.wav",
"player/pl_grate1.wav",
"player/pl_grate2.wav",
"player/pl_grate3.wav",
"player/pl_grate4.wav",
"player/pl_metal1.wav",
"player/pl_metal2.wav",
"player/pl_metal3.wav",
"player/pl_metal4.wav",
"player/pl_slosh1.wav",
"player/pl_slosh2.wav",
"player/pl_slosh3.wav",
"player/pl_slosh4.wav",
"player/pl_snow1.wav",
"player/pl_snow2.wav",
"player/pl_snow3.wav",
"player/pl_snow4.wav",
"player/pl_snow5.wav",
"player/pl_snow6.wav",
"player/pl_step1.wav",
"player/pl_step2.wav",
"player/pl_step3.wav",
"player/pl_step4.wav",
"player/pl_swim1.wav",
"player/pl_swim2.wav",
"player/pl_swim3.wav",
"player/pl_swim4.wav",
"player/pl_tile1.wav",
"player/pl_tile2.wav",
"player/pl_tile3.wav",
"player/pl_tile4.wav",
"player/pl_tile5.wav",
"player/pl_wade1.wav",
"player/pl_wade2.wav",
"player/pl_wade3.wav",
"player/pl_wade4.wav",
"weapons/boltdown.wav",
"weapons/boltpull1.wav",
"weapons/boltup.wav",
"weapons/clipin1.wav",
"weapons/clipout1.wav",
"weapons/de_clipin.wav",
"weapons/de_clipout.wav",
"weapons/de_deploy.wav",
"weapons/headshot2.wav",
"weapons/pinpull.wav",
"weapons/slideback1.wav",
"weapons/sliderelease1.wav",
"weapons/dryfire_pistol.wav",
"weapons/dryfire_rifle.wav",
"weapons/knife_deploy1.wav",
"weapons/knife_hit1.wav",
"weapons/knife_hit2.wav",
"weapons/knife_hit3.wav",
"weapons/knife_hit4.wav",
"weapons/knife_hitwall1.wav",
"weapons/knife_slash1.wav",
"weapons/knife_slash2.wav",
"weapons/knife_stab.wav",
"weapons/zoom.wav"
}
new const gSZ_GunsEvents[][] =
{
"events/awp.sc",
"events/g3sg1.sc",
"events/ak47.sc",
"events/scout.sc",
"events/m249.sc",
"events/m4a1.sc",
"events/sg552.sc",
"events/aug.sc",
"events/sg550.sc",
"events/m3.sc",
"events/xm1014.sc",
"events/usp.sc",
"events/mac10.sc",
"events/ump45.sc",
"events/fiveseven.sc",
"events/p90.sc",
"events/deagle.sc",
"events/p228.sc",
"events/glock18.sc",
"events/mp5n.sc",
"events/tmp.sc",
"events/elite_left.sc",
"events/elite_right.sc",
"events/galil.sc",
"events/famas.sc"
}
public plugin_precache()
{
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnPrecacheSound","PrecacheSound"), "pfw_PrecacheSound", OrpheuHookPost)
gTRIE_SoundList = TrieCreate()
gTRIE_TraceRegs = TrieCreate()
get_datadir(gF_sndkey, charsmax(gF_sndkey))
format(gF_sndkey, charsmax(gF_sndkey),"%s/%s", gF_sndkey, "wb_sndkey.cfg")
new bool:versionver = false
// Use the normal sounds if we do not have a key!
if (!file_exists(gF_sndkey))
{
server_print("[SND Block] Soundhack key not existent! Using default sounds!")
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gI_SoundSize = sizeof gSZ_SoundList
versionver = true
gB_loaded = false
gB_DefaultSounds = true
}
else
{
new pf = fopen(gF_sndkey, "r"), line[60]
server_print("[SND Block] Soundhack key reading!")
// Read key.
while (!feof(pf))
{
fgets(pf, line, charsmax(line))
if (line[0] == ';' || line[0] == '/')
continue
if (line[0] == 'v' && !versionver)
{
versionver = true
if ((line[1] == '6' && line[2] == '.' && line[3] == '3') || line[1] == '7' || line[1] == '8')
{
server_print("[SND Block] Soundhack key version correspondence, eveything ok!")
}
else
{
server_print("[SND Block] Soundhack key version load failure (Version does not correspond). Using default sounds!")
log_error(AMX_ERR_NONE, "[SND Block] Soundhack key version load failure (Version does not correspond). Using default sounds!")
gB_DefaultSounds = true
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gB_loaded = false
gI_SoundSize = sizeof gSZ_SoundList
break
}
continue
}
copy(gSZ_SoundMod[gI_SoundSize], 59, line)
// Get rid of the "newline" parts
replace(gSZ_SoundMod[gI_SoundSize], 59, "^n", "^0")
gI_SoundSize++;
}
fclose(pf)
}
if (gI_SoundSize != sizeof gSZ_SoundList)
{
gB_DefaultSounds = true
server_print("[SND Block] Soundhack key version load failure (Number of sounds does not correspond). Using default sounds!")
log_error(AMX_ERR_NONE, "[SND Block] Soundhack key version load failure (Number of sounds does not correspond). Using default sounds!")
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gB_loaded = false
}
if (!versionver)
{
gB_DefaultSounds = true
server_print("[SND Block] Soundhack key version load failure (Version read failure). Using default sounds!")
log_error(AMX_ERR_NONE, "[SND Block] Soundhack key version load failure (Version read failure). Using default sounds!")
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gB_loaded = false
}
if (gB_loaded)
{
new filepath[300], filepath2[300]
copy(filepath, charsmax(filepath), gSZ_SoundMod[0])
replace(filepath, charsmax(filepath), "/", " ")
parse(filepath, filepath, charsmax(filepath), filepath2, charsmax(filepath2))
format(filepath, charsmax(filepath), "sound/%s", filepath)
if (!dir_exists(filepath))
{
mkdir(filepath)
}
new bool:bSizeOk = true
new bool:bExists = true
for (new i=0;i<gI_SoundSize; i++)
{
format(filepath, charsmax(filepath), "sound/%s", gSZ_SoundList[i])
format(filepath2, charsmax(filepath), "sound/%s", gSZ_SoundMod[i])
if (!file_exists(filepath2))
{
if (!fcopy(filepath, filepath2))
{
bExists = false
break
}
}
else
{
if (!fcompare(filepath, filepath2))
{
bSizeOk = false
gB_loaded = false
break
}
}
}
if (!bExists)
{
server_print("[SND Block] Soundhack key version load failure (Unknown read\write error). Using default sounds!")
log_error(AMX_ERR_NONE, "[SND Block] Soundhack key version load failure (Unknown read\write error). Using default sounds!")
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gB_loaded = false
}
if (!bSizeOk)
{
server_print("[SND Block] Soundhack key version load failure (File size not maching). Using default sounds!")
log_error(AMX_ERR_NONE, "[SND Block] Soundhack key version load failure (File size not maching). Using default sounds!")
for (new i=0;i<sizeof gSZ_SoundList;i++)
{
copy(gSZ_SoundMod[i], 59, gSZ_SoundList[i])
}
gB_loaded = false
}
for (new i=0;i<gI_SoundSize && bSizeOk; i++)
{
precache_sound(gSZ_SoundMod[i])
}
if (bSizeOk)
server_print("[SND Block] Soundhack key loaded!")
}
register_forward(FM_Spawn, "pfw_Spawn", 1)
register_forward(FM_PrecacheEvent, "pfw_PrecacheEvent", 1)
gTRIE_TraceRegs = TrieCreate()
}
public pfw_PrecacheEvent(type, const name[])
{
for (new i = 0; i < sizeof gSZ_GunsEvents; ++i)
{
if (equal(gSZ_GunsEvents[i], name))
{
gBS_GunsEvents |= (1<<get_orig_retval())
return FMRES_HANDLED
}
}
return FMRES_IGNORED
}
public pfw_PrecacheSound(filename[])
{
if (TrieKeyExists(gTRIE_SoundList, filename))
return
TrieSetCell(gTRIE_SoundList, filename, OrpheuGetReturn())
}
public pfw_Spawn(ent)
{
if (!pev_valid(ent))
return
new classname[32]
pev(ent, pev_classname, classname, charsmax(classname))
if(!TrieKeyExists(gTRIE_TraceRegs, classname))
{
RegisterHam(Ham_TraceAttack, classname, "pfw_GlobalTraceAttack", 1)
TrieSetCell(gTRIE_TraceRegs, classname, true)
}
}
public plugin_init()
{
register_plugin("SND Block", "8.0", "OT")
gPCV_on_off = register_cvar("snb_enable", "1")
gPCV_footsteps = register_cvar("snb_footsteps", "1")
gPCV_shotover = register_cvar("snb_shotover", "1")
register_forward(FM_PlaybackEvent, "fw_PlaybackEvent")
register_forward(FM_PlayerPreThink, "fw_FreqThink" , 0)
register_forward(FM_PlayerPreThink, "fw_FreqThink" , 1)
register_forward(FM_PlayerPostThink, "fw_FreqThink" , 0)
register_forward(FM_PlayerPostThink, "fw_FreqThink" , 1)
gPSND_Indexes[STEP_CONCRETE] = getStringPos("player/pl_step1.wav")
gPSND_Indexes[STEP_METAL] = getStringPos("player/pl_metal1.wav")
gPSND_Indexes[STEP_DIRT] = getStringPos("player/pl_dirt1.wav")
gPSND_Indexes[STEP_VENT] = getStringPos("player/pl_duct1.wav")
gPSND_Indexes[STEP_GRATE] = getStringPos("player/pl_grate1.wav")
gPSND_Indexes[STEP_TILE] = getStringPos("player/pl_tile1.wav")
gPSND_Indexes[STEP_SLOSH] = getStringPos("player/pl_slosh1.wav")
gPSND_Indexes[STEP_WADE] = getStringPos("player/pl_wade1.wav")
gPSND_Indexes[STEP_LADDER] = getStringPos("player/pl_ladder1.wav")
gPSND_Indexes[STEP_SNOW] = getStringPos("player/pl_snow1.wav")
RegisterHam(Ham_Spawn, "player", "fw_alive_handle", 1)
RegisterHam(Ham_Killed, "player", "fw_alive_handle", 1)
register_srvcmd("amx_sndkeycfg", "cmd_sndkeycfg", ADMIN_IMMUNITY, "<command> <target>")
gDecal_shot1 = engfunc(EngFunc_DecalIndex, "{shot1")
register_event("TextMsg","event_specMode","b","2&#Spec_Mode")
gI_MaxPlayers = get_maxplayers()
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnEmitSound","EmitSound"), "fw_EmitSound")
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnEmitAmbientSound","EmitAmbientSound"), "fw_EmitAmbientSound")
OrpheuRegisterHook(OrpheuGetFunction("ReloadSound","CBasePlayerWeapon"), "fw_RloadSound")
}
public OrpheuHookReturn:fw_RloadSound(ent)
{
new owner = get_pdata_cbase(ent, m_pPlayer, 4)
if ((1<<get_pdata_int(ent, m_iId, 4)) & ((1<<CSW_M3) | (1<<CSW_XM1014)))
EmitSpecialSound(false, owner, (1<<get_pdata_int(ent, m_iId, 4)) & ((1<<CSW_M3) | (1<<CSW_XM1014)) ? "weapons/generic_shot_reload.wav" : "weapons/generic_reload.wav", VOL_NORM, 3.12, 0, PITCH_NORM)
return OrpheuSupercede
}
public event_specMode(id)
{
new specMode[12]
read_data(2,specMode,11)
if(specMode[10] == '4')
{
add_spect_property(id)
}
else
{
del_spect_property(id)
}
}
public fw_FreqThink(id)
{
if (!get_pcvar_num(gPCV_footsteps) || !get_pcvar_num(gPCV_on_off))
return FMRES_IGNORED
if (!has_alive_property(id))
return FMRES_IGNORED
new waterLevel = entity_get_int(id, EV_INT_waterlevel)
new iStepLeft = entity_get_int(id, EV_INT_iStepLeft)
new flags = entity_get_int(id, EV_INT_flags)
if (waterLevel > 1)
{
gCLI_oldwaterlevel[id] = waterLevel
gCLI_iStepLeft[id] = iStepLeft
gCLI_oldflags[id] = flags
return FMRES_IGNORED
}
if (waterLevel == 1 && !!gCLI_iStepLeft[id] == !iStepLeft && get_velocity(id, true) > SND_MOVEVELOCITY)
{
PM_PlayStepSound(id, STEP_SLOSH, 0.60)
gCLI_oldwaterlevel[id] = waterLevel
gCLI_iStepLeft[id] = iStepLeft
gCLI_oldflags[id] = flags
return FMRES_IGNORED
}
if (entity_get_int(id, EV_INT_movetype) == MOVETYPE_FLY && !!gCLI_iStepLeft[id] == !iStepLeft && get_velocity(id, false) > SND_MOVEVELOCITY)
{
PM_PlayStepSound(id, STEP_LADDER, 0.8)
gCLI_oldwaterlevel[id] = waterLevel
gCLI_iStepLeft[id] = iStepLeft
gCLI_oldflags[id] = flags
return FMRES_IGNORED
}
if ((!!gCLI_iStepLeft[id] == !iStepLeft && (flags & FL_ONGROUND) && get_velocity(id, true) > SND_MOVEVELOCITY) || (!(flags & FL_ONGROUND) && (gCLI_oldflags[id] & FL_ONGROUND) && get_zveleocity(id) > SND_ZVELOCITY))
{
new Float:start[3], Float:end[3], ent
gCLI_iStepLeft[id] = iStepLeft
ent = getFootStepCoords(id, start, end)
new texture[64]
if (!trace_texture(ent, start, end, texture, charsmax(texture)))
{
PM_PlayStepSound(id, STEP_CONCRETE, 0.75)
gCLI_oldwaterlevel[id] = waterLevel
gCLI_oldflags[id] = flags
return FMRES_IGNORED
}
PM_PlayStepSound(id, PM_MapTextureTypeStepType(dllfunc(DLLFunc_PM_FindTextureType, texture)), 0.75)
gCLI_oldwaterlevel[id] = waterLevel
gCLI_oldflags[id] = flags
return FMRES_IGNORED
}
else
{
gCLI_iStepLeft[id] = iStepLeft
gCLI_oldwaterlevel[id] = waterLevel
gCLI_oldflags[id] = flags
}
return FMRES_IGNORED
}
public pfw_GlobalTraceAttack(ent, attacker, Float:damage, Float:direction[3], tracehdl, bits)
{
if (!get_pcvar_num(gPCV_on_off) || !get_pcvar_num(gPCV_shotover))
return HAM_IGNORED
if (attacker > gI_MaxPlayers || gI_MaxPlayers < 1)
return HAM_IGNORED
if (get_user_weapon(attacker) == CSW_KNIFE)
return HAM_IGNORED
new Float:origin[3]
get_tr2(tracehdl, TR_vecEndPos, origin)
BulletHole(origin, attacker)
return HAM_IGNORED
}
public fw_PlaybackEvent(flags, invoker, eventid)
{
if (!get_pcvar_num(gPCV_on_off) || !get_pcvar_num(gPCV_shotover))
return FMRES_IGNORED
if (!(gBS_GunsEvents & (1<<eventid)) || !(1 <= invoker <= gI_MaxPlayers))
return FMRES_IGNORED
new weapon = get_user_weapon(invoker)
PlayShotSound(invoker, weapon)
new players[32], num, id
get_players(players, num, "b")
for (new i=0;i<num;i++)
{
id = players[i]
if (!has_spect_property(id))
continue
if (pev(id, pev_iuser2) != invoker)
continue
SendShotAnnimation(id, ham_get_user_weaponent(invoker, weapon))
}
return FMRES_SUPERCEDE
}
public OrpheuHookReturn:fw_EmitSound(ent, Float:origin[3], sample[], Float:volume, Float:attenuation, fFlags, pitch)
{
if (!get_pcvar_num(gPCV_on_off))
return OrpheuIgnored
if (!pev_valid(ent))
return OrpheuIgnored
if (ent > gI_MaxPlayers)
{
new classname[10]
pev(ent, pev_classname, classname, charsmax(classname))
if (contain(classname, "weapon_") != 0)
return OrpheuIgnored
if (pev(ent, pev_aiment) == 0)
return OrpheuIgnored
if (gB_DefaultSounds)
{
EmitSpecialSound(true, pev(ent, pev_aiment), sample, volume, attenuation, fFlags, pitch)
}
else
{
new position = getStringPos(sample)
EmitSpecialSound(true, pev(ent, pev_aiment), (position == -1) ? sample : gSZ_SoundList[position], volume, attenuation, fFlags, pitch)
}
return OrpheuSupercede
}
if (gB_DefaultSounds)
{
EmitSpecialSound(true, ent, sample, volume, attenuation, fFlags, pitch)
}
else
{
new position = getStringPos(sample)
EmitSpecialSound(true, ent, (position == -1) ? sample : gSZ_SoundList[position], volume, attenuation, fFlags, pitch)
}
return OrpheuSupercede
}
public OrpheuHookReturn:fw_EmitAmbientSound(ent, Float:origin[3], sample[], Float:volume, Float:attenuation, fFlags, pitch)
{
if (!get_pcvar_num(gPCV_on_off))
return OrpheuIgnored
if (!pev_valid(ent))
return OrpheuIgnored
if (ent > gI_MaxPlayers)
return OrpheuIgnored
OrpheuSetParam(1, 0)
return OrpheuIgnored
}
public cmd_sndkeycfg(id, level, cid)
{
if (!cmd_access(id, level, cid, 2))
{
server_print("Usage: amx_sndkeycfg help - this will show you how to use the command")
return PLUGIN_HANDLED
}
new arg[300]
read_argv(1, arg, charsmax(arg))
if (equali(arg, "help"))
{
server_print("Usage examples:")
server_print("amx_sndkeycfg help - this will show you how to use the command")
server_print("amx_sndkeycfg delete - this will delete the present soundkey (only if it was loaded)")
server_print("amx_sndkeycfg create - this will delete the present soundkey (only if it was loaded) and create a new one")
server_print("amx_sndkeycfg import <target> - this will import a soundkey from a file (will not override the present soundkey)")
server_print("amx_sndkeycfg overimport <target> - this will import a soundkey from a file and delete the present one (only if it was loaded)")
return PLUGIN_HANDLED
}
new filepath[300]
new string1[128][21]
new foldername[25] = "wb"
if (equali(arg, "create"))
{
if (!file_exists(gF_sndkey))
{
for (new i=2;i < charsmax(foldername); i++)
{
foldername[i] = randomchar(random(3))
}
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
// Here we create a random name for the new sound file
for (new j=0;j<20;j++)
{
string1[i][j] = randomchar(random(3))
}
// Recheck for duplicates
for (new j=0;j<i;j++)
{
if (equal(string1[i], string1[j]))
{
for (new j=0;j<20;j++)
{
string1[i][j] = randomchar(random(3))
}
}
}
// Add all that we need
format(gSZ_SoundMod[i], 59, "%s/%s.wav", foldername, string1[i])
}
format(filepath, charsmax(filepath), "sound/%s",foldername)
new pf = fopen(gF_sndkey, "w")
fprintf(pf, "; DO NOT DELETE THIS FILE! UNLESS YOU KNOW WHAT YOU ARE DOING!!!^n")
fprintf(pf, "v8.0^n")
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
if (i != sizeof gSZ_SoundList - 1)
{
fprintf(pf, "%s^n", gSZ_SoundMod[i])
}
else
{
fprintf(pf, "%s", gSZ_SoundMod[i])
}
}
fclose(pf)
server_print("[SND Block] Soundhack key created!")
}
else
{
if (!gB_loaded)
{
server_print("[SND Block] Soundhack key not loaded will not delete due to security measures!")
return PLUGIN_HANDLED
}
delete_file(gF_sndkey)
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
format(filepath, charsmax(filepath), "sound/%s", gSZ_SoundMod[i])
delete_file(filepath)
}
new filepath[300], filepath2[300]
copy(filepath, charsmax(filepath), gSZ_SoundMod[0])
replace(filepath, charsmax(filepath), "/", " ")
parse(filepath, filepath, charsmax(filepath), filepath2, charsmax(filepath2))
format(filepath, charsmax(filepath), "sound/%s", filepath)
rmdir(filepath)
for (new i=2;i < charsmax(foldername); i++)
{
foldername[i] = randomchar(random(3))
}
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
// Here we create a random name for the new sound file
for (new j=0;j<20;j++)
{
string1[i][j] = randomchar(random(3))
}
// Recheck for duplicates
for (new j=0;j<i;j++)
{
if (equal(string1[i], string1[j]))
{
for (new j=0;j<20;j++)
{
string1[i][j] = randomchar(random(3))
}
}
}
// Add all that we need
format(gSZ_SoundMod[i], 59, "%s/%s.wav", foldername, string1[i])
}
format(filepath, charsmax(filepath), "sound/%s",foldername)
new pf = fopen(gF_sndkey, "w")
fprintf(pf, "; DO NOT DELETE THIS FILE! UNLESS YOU KNOW WHAT YOU ARE DOING!!!^n")
fprintf(pf, "v8.0^n")
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
if (i != sizeof gSZ_SoundList - 1)
{
fprintf(pf, "%s^n", gSZ_SoundMod[i])
}
else
{
fprintf(pf, "%s", gSZ_SoundMod[i])
}
}
fclose(pf)
server_print("[SND Block] Soundhack key created!")
}
}
if (equali(arg, "delete"))
{
if (!file_exists(gF_sndkey))
{
server_print("[SND Block] No existent key! Cannot delete!")
return PLUGIN_HANDLED
}
if (!gB_loaded)
{
server_print("[SND Block] Soundhack key not loaded will not delete due to security measures!")
return PLUGIN_HANDLED
}
delete_file(gF_sndkey)
new filepath[300]
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
format(filepath, charsmax(filepath), "sound/%s", gSZ_SoundMod[i])
delete_file(filepath)
}
new filepath2[300]
copy(filepath, charsmax(filepath), gSZ_SoundMod[0])
replace(filepath, charsmax(filepath), "/", " ")
parse(filepath, filepath, charsmax(filepath), filepath2, charsmax(filepath2))
format(filepath, charsmax(filepath), "sound/%s", filepath)
rmdir(filepath)
server_print("[SND Block] Key deleted!")
// Restart the server so we can load the key!
server_cmd("restart")
return PLUGIN_HANDLED
}
if (equali(arg, "import"))
{
if (file_exists(gF_sndkey))
{
server_print("[SND Block] Cannot override! Use")
return PLUGIN_HANDLED
}
else
{
read_argv(2, arg, charsmax(arg))
if (!file_exists(arg))
{
server_print("[SND Block] Invaild path specified! %s", arg)
return PLUGIN_HANDLED
}
fcopy(arg, gF_sndkey)
}
}
if (equali(arg, "overimport"))
{
read_argv(2, arg, charsmax(arg))
if (!file_exists(arg))
{
server_print("[SND Block] Invaild path specified! %s", arg)
return PLUGIN_HANDLED
}
if (file_exists(gF_sndkey))
{
if (!gB_loaded)
{
server_print("[SND Block] Soundhack key not loaded will not delete due to security measures!")
return PLUGIN_HANDLED
}
delete_file(gF_sndkey)
new filepath[300]
for (new i=0;i< sizeof gSZ_SoundList;i++)
{
format(filepath, charsmax(filepath), "sound/%s", gSZ_SoundMod[i])
delete_file(filepath)
}
new filepath2[300]
copy(filepath, charsmax(filepath), gSZ_SoundMod[0])
replace(filepath, charsmax(filepath), "/", " ")
parse(filepath, filepath, charsmax(filepath), filepath2, charsmax(filepath2))
format(filepath, charsmax(filepath), "sound/%s", filepath)
rmdir(filepath)
}
fcopy(arg, gF_sndkey)
}
// Restart the server so we can load the key!
server_cmd("restart")
return PLUGIN_HANDLED
}
public client_connect(id)
{
del_alive_property(id)
}
public client_disconnect(id)
{
del_alive_property(id)
}
public fw_alive_handle(id)
{
if (!is_user_alive(id))
{
del_alive_property(id)
}
else
{
add_alive_property(id)
}
}
stock ham_get_user_weaponent(id, iCswId, iSlot = 0)
{
new iWeapon
if( !iSlot )
{
if( PRIMARIES_BITSUM & (1<<iCswId) )
{
iSlot = 1
}
else if( GUNS_BITSUM & (1<<iCswId) )
{
iSlot = 2
}
else if( iCswId == CSW_KNIFE )
{
iSlot = 3
}
else if( NADES_BITSUM & (1<<iCswId) )
{
iSlot = 4
}
else if( iCswId == CSW_C4 )
{
iSlot = 5
}
}
// get the last weapon that the player gained in this slot
iWeapon = get_pdata_cbase(id, m_rgpPlayerItems[iSlot], EXTRAOFFSET)
while( pev_valid(iWeapon) ) // >0 check should be enough, i let pev_valid for the tut
{
// Check if the weapon type (CSW_) is the one we are searching
if( get_pdata_int(iWeapon, m_iId, EXTRAOFFSET_WEAPONS) == iCswId )
{
// return the weapon entity index
return iWeapon
}
// if not, search if another weapon is linked to the previous one
iWeapon = get_pdata_cbase(iWeapon, m_pNext, EXTRAOFFSET_WEAPONS)
}
// return 0 on failure
return 0
}
stock fcompare(read_path[300], dest_path[300])
{
// Prepare for read
new fp_read = fopen(read_path, "rb")
// No file to read, errors!
if (!fp_read)
{
fclose(fp_read)
return -1
}
// Prepare for read
new fp_read2 = fopen(dest_path, "rb")
// No file to read, errors!
if (!fp_read2)
{
fclose(fp_read2)
return -1
}
// Set to the end!
fseek(fp_read, 0, SEEK_END);
fseek(fp_read2, 0, SEEK_END);
// Tell the file sizez, if equal that means that the size is the same!
if (ftell(fp_read) == ftell(fp_read2))
{
fclose(fp_read)
fclose(fp_read2)
return 1
}
fclose(fp_read)
fclose(fp_read2)
return 0
}
stock fcopy(read_path[300], dest_path[300], FWrite:flags = FW_NONE)
{
// Prepare for read
new fp_read = fopen(read_path, "rb")
// No file to read, errors!
if (!fp_read)
{
fclose(fp_read)
return 0
}
// If the native cannot override
if (file_exists(dest_path) && !(flags & FW_CANOVERRIDE))
{
return 0
}
// Prepare for write
new fp_write = fopen(dest_path, "wb")
// Used for copying
static buffer[BUFFERSIZE]
static readsize
// Find the size of the files
fseek(fp_read, 0, SEEK_END);
new fsize = ftell(fp_read);
fseek(fp_read, 0, SEEK_SET);
// Here we copy the info
for (new j = 0; j < fsize; j += BUFFERSIZE)
{
readsize = fread_blocks(fp_read, buffer, BUFFERSIZE, BLOCK_CHAR);
fwrite_blocks(fp_write, buffer, readsize, BLOCK_CHAR);
}
// Close the files
fclose(fp_read)
fclose(fp_write)
// Can delete source?
if (flags & FW_DELETESOURCE)
delete_file(read_path)
// Success
return 1
}
stock getStringPos(string[])
{
for (new i=0;i<94;i++)
{
if (equali(gSZ_SoundList[i],string))
return i
}
return -1
}
stock randomchar(i)
{
// 1 for big letters
// 2 for small ones
// The rest numbers
switch(i)
{
case 1:
{
return random_num('A', 'Z')
}
case 2:
{
return random_num('a', 'z')
}
default:
{
return random_num('0', '9')
}
}
return 'a'
}
stock PlayShotSound(id, weapon_id)
{
new weapon_ent = ham_get_user_weaponent(id,weapon_id)
switch(weapon_id)
{
case CSW_P228:
{
EmitSpecialSound(false, id, "weapons/p228-1.wav", VOL_NORM, 0.8, 0, 94 + random(15))
}
case CSW_SCOUT:
{
EmitSpecialSound(false, id, "weapons/scout_fire-1.wav", VOL_NORM, 1.6, 0, 94 + random(15))
}
case CSW_XM1014:
{
EmitSpecialSound(false, id, "weapons/xm1014-1.wav", VOL_NORM, 0.52, 0, 94 + random(15))
}
case CSW_MAC10:
{
EmitSpecialSound(false, id, "weapons/mac10-1.wav", VOL_NORM, 0.72, 0, 94 + random(15))
}
case CSW_AUG:
{
EmitSpecialSound(false, id, "weapons/aug-1.wav", VOL_NORM, 0.48, 0, 94 + random(15))
}
case CSW_ELITE:
{
EmitSpecialSound(false, id, "weapons/elite_fire.wav", VOL_NORM, 0.8, 0, 94 + random(15))
}
case CSW_FIVESEVEN:
{
EmitSpecialSound(false, id, "weapons/fiveseven-1.wav", VOL_NORM, 0.8, 0, 94 + random(15))
}
case CSW_UMP45:
{
EmitSpecialSound(false, id, "weapons/ump45-1.wav", VOL_NORM, 0.64, 0, 94 + random(15))
}
case CSW_SG550:
{
EmitSpecialSound(false, id, "weapons/sg550-1.wav", VOL_NORM, 0.4, 0, 94 + random(15))
}
case CSW_GALIL:
{
EmitSpecialSound(false, id, random(2) ? "weapons/galil-1.wav" : "weapons/galil-2.wav", VOL_NORM, 0.4, 0, 94 + random(15))
}
case CSW_FAMAS:
{
EmitSpecialSound(false, id, random(2) ? "weapons/famas-1.wav" : "weapons/famas-2.wav", VOL_NORM, 0.45, 0, 94 + random(15))
}
case CSW_USP:
{
if (cs_get_weapon_silen(weapon_ent))
{
EmitSpecialSound(false, id, random(2) ? "weapons/usp1.wav" : "weapons/usp2.wav", VOL_NORM, 2.0, 0, 94 + random(15))
}
else
{
EmitSpecialSound(false, id, "weapons/usp_unsil-1.wav", VOL_NORM, 0.8, 0, 87 + random(15))
}
}
case CSW_GLOCK18:
{
if (cs_get_weapon_burst(weapon_ent))
{
EmitSpecialSound(false, id, "weapons/glock18-1.wav", VOL_NORM, 0.8, 0, 94 + random(15))
}
else
{
EmitSpecialSound(false, id, "weapons/glock18-2.wav", VOL_NORM, 0.8, 0, 94 + random(15))
}
}
case CSW_AWP:
{
EmitSpecialSound(false, id, "weapons/awp1.wav", VOL_NORM, 0.28, 0, 94 + random(15))
}
case CSW_MP5NAVY:
{
EmitSpecialSound(false, id, random(2) ? "weapons/mp5-1.wav" : "weapons/mp5-2.wav", VOL_NORM, 0.64, 0, 94 + random(15))
}
case CSW_M249:
{
EmitSpecialSound(false, id, random(2) ? "weapons/m249-1.wav" : "weapons/m249-2.wav", VOL_NORM, 0.52, 0, 94 + random(15))
}
case CSW_M3:
{
EmitSpecialSound(false, id, "weapons/m3-1.wav", VOL_NORM, 0.48, 0, 94 + random(15))
}
case CSW_M4A1:
{
if (cs_get_weapon_silen(weapon_ent))
{
EmitSpecialSound(false, id, "weapons/m4a1-1.wav", VOL_NORM, 1.4, 0, 94 + random(15))
}
else
{
EmitSpecialSound(false, id, random(2) ? "weapons/m4a1_unsil-1.wav" : "weapons/m4a1_unsil-2.wav", VOL_NORM, 0.52, 0, 94 + random(15))
}
}
case CSW_TMP:
{
EmitSpecialSound(false, id, random(2) ? "weapons/tmp-1.wav" : "weapons/tmp-2.wav", VOL_NORM, 1.6, 0, 94 + random(15))
}
case CSW_G3SG1:
{
EmitSpecialSound(false, id, "weapons/g3sg1-1.wav", VOL_NORM, 0.4, 0, 94 + random(15))
}
case CSW_SG552:
{
EmitSpecialSound(false, id, random(2) ? "weapons/sg552-1.wav" : "weapons/sg552-2.wav", VOL_NORM, 0.4, 0, 94 + random(15))
}
case CSW_AK47:
{
EmitSpecialSound(false, id, random(2) ? "weapons/ak47-1.wav" : "weapons/ak47-2.wav", VOL_NORM, 0.4, 0, 94 + random(15))
}
case CSW_P90:
{
EmitSpecialSound(false, id, "weapons/p90-1.wav", VOL_NORM, 0.64, 0, 94 + random(15))
}
case CSW_DEAGLE:
{
EmitSpecialSound(false, id, random(2) ? "weapons/deagle-1.wav" : "weapons/deagle-2.wav", VOL_NORM, 0.6, 0, 94 + random(15))
}
}
}
stock EmitSpecialSound(bool:playonent, ent, sample[], Float:fvol, Float:attn, flags, pitch)
{
if (!TrieKeyExists(gTRIE_SoundList, sample))
{
log_amx("[WallBlocker] [EmitSpecialSound] Error: Sample unregistered")
return
}
new soundIndex
if (!TrieGetCell(gTRIE_SoundList, sample, soundIndex))
{
log_amx("[WallBlocker] [EmitSpecialSound] Error: TrieGetCell error")
return
}
new Float:origin[3]
pev(ent, pev_origin, origin)
new players[32], num
get_players(players, num)
new Float:distance_to_send = (attn == ATTN_NONE) ? 1000000.0 : (1600 / attn)
for (new i=0;i<num;i++)
{
if (entity_range(ent, players[i]) > distance_to_send)
continue
if (players[i] == ent)
{
if (playonent)
spawnStaticSound(ent, ent, null_vector, soundIndex, fvol, attn, pitch, flags)
continue
}
spawnStaticSound(players[i], 0, origin, soundIndex, fvol, attn, pitch, flags)
}
}
stock getFootStepCoords(id, Float:fstart[3], Float:fend[3])
{
new Float:start[5][3], Float:end[5][3], Float:diff[5][3], Float:angle[3], Float:fwd[3], Float:right[3], ent[5], grndent, bool:halftests = false
entity_get_vector(id, EV_VEC_v_angle, angle)
angle_vector(angle, ANGLEVECTOR_FORWARD, fwd)
fwd[2] = 0.0
angle_vector(angle, ANGLEVECTOR_RIGHT, right)
if (xs_vec_len(fwd) != 0.0)
xs_vec_mul_scalar(fwd, FOOTSTEP_DIST/xs_vec_len(fwd), fwd)
else
halftests = true
xs_vec_mul_scalar(right, FOOTSTEP_DIST/xs_vec_len(right), right)
// Get Normal start and end origins
entity_get_vector(id, EV_VEC_origin, start[0])
end[0] = start[0]
end[0][2] -= OFFSET_MINTRACE
if (halftests)
{
xs_vec_add(start[0], right, start[1])
xs_vec_sub(start[0], right, start[2])
grndent = entity_get_edict(id, EV_ENT_groundentity)
for (new i=0;i<3;i++)
{
ent[i] = trace_line(-1, start[i], end[i], diff[i])
if (ent[i] == grndent)
{
fstart = start[i]
fend = end[i]
return ent[i]
}
if (!grndent)
{
if (!xs_vec_equal(diff[i], end[i]))
{
fstart = start[i]
fend = end[i]
return 0
}
}
}
fstart = start[2]
fend = end[2]
return ent[2] <= 0 ? 0 : ent[2]
}
xs_vec_add(start[0], fwd, start[1])
xs_vec_add(start[1], right, start[1])
xs_vec_add(start[0], fwd, start[2])
xs_vec_sub(start[2], right, start[2])
xs_vec_sub(start[0], fwd, start[3])
xs_vec_add(start[3], right, start[3])
xs_vec_sub(start[0], fwd, start[4])
xs_vec_sub(start[4], right, start[4])
xs_vec_add(end[0], fwd, end[1])
xs_vec_add(end[1], right, end[1])
xs_vec_add(end[0], fwd, end[2])
xs_vec_sub(end[2], right, end[2])
xs_vec_sub(end[0], fwd, end[3])
xs_vec_add(end[3], right, end[3])
xs_vec_sub(end[0], fwd, end[4])
xs_vec_sub(end[4], right, end[4])
grndent = entity_get_edict(id, EV_ENT_groundentity)
for (new i=0;i<5;i++)
{
ent[i] = trace_line(-1, start[i], end[i], diff[i])
if (ent[i] == grndent)
{
fstart = start[i]
fend = end[i]
return ent[i]
}
if (!grndent)
{
if (!xs_vec_equal(diff[i], end[i]))
{
fstart = start[i]
fend = end[i]
return 0
}
}
}
fstart = start[4]
fend = end[4]
return ent[4] <= 0 ? 0 : ent[4]
}
stock spawnStaticSound(const sendto, const index, const Float:origin[3], const soundIndex, const Float:vol, const Float:atten, const pitch, const flags)
{
message_begin(sendto ? MSG_ONE : MSG_ALL, SVC_SPAWNSTATICSOUND, .player = sendto);
{
write_coord_f(origin[0]);
write_coord_f(origin[1]);
write_coord_f(origin[2]);
write_short(soundIndex);
write_byte(clamp_byte(floatround(vol * 255)))
write_byte(clamp_byte(floatround(atten * 64)))
write_short(index)
write_byte(pitch)
write_byte(flags)
}
message_end()
}
stock BulletHole(Float: origin[3], id)
{
new players[32], num, player
get_players(players, num)
for (new i=0;i<num;i++)
{
player = players[i]
if (id == player)
continue
engfunc(EngFunc_MessageBegin, MSG_ONE, SVC_TEMPENTITY, null_vector, player)
write_byte(TE_GUNSHOTDECAL)
engfunc(EngFunc_WriteCoord, origin[0])
engfunc(EngFunc_WriteCoord, origin[1])
engfunc(EngFunc_WriteCoord, origin[2])
write_short(0)
write_byte(gDecal_shot1 - random(5))
message_end()
if (random(100) < 10)
{
engfunc(EngFunc_MessageBegin, MSG_ONE, SVC_TEMPENTITY, null_vector, player)
write_byte(TE_SPARKS)
engfunc(EngFunc_WriteCoord, origin[0])
engfunc(EngFunc_WriteCoord, origin[1])
engfunc(EngFunc_WriteCoord, origin[2])
message_end()
}
}
return 1
}
stock Float:get_velocity(ent, bool:use2d)
{
new Float:vel[3]
entity_get_vector(ent, EV_VEC_velocity, vel)
if (use2d)
vel[2] = 0.0
return xs_vec_len(vel)
}
stock Float:get_zveleocity(ent)
{
new Float:vel[3]
entity_get_vector(ent, EV_VEC_velocity, vel)
return vel[2]
}
stock PM_PlayStepSound(id, step, Float:fvol)
{
new irand = random(2) + (entity_get_int(id, EV_INT_iStepLeft) * 2)
switch (step)
{
case STEP_METAL:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_METAL] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_DIRT:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_DIRT] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_VENT:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_VENT] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_GRATE:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_GRATE] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_TILE:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_TILE] + ((random(101) < 90) ? getRemixedValues(irand) : 4)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_SLOSH:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_SLOSH] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_WADE:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_WADE] + irand], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_LADDER:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_LADDER] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
case STEP_SNOW:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_SNOW] + random(6)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
default:
{
EmitSpecialSound( true, id, gSZ_SoundMod[gPSND_Indexes[STEP_CONCRETE] + getRemixedValues(irand)], fvol, ATTN_NORM, 0, PITCH_NORM )
}
}
return 1
}
stock getRemixedValues(value)
{
switch (value)
{
case 1: return 2
case 2: return 1
case 3: return 3
default: return 0
}
return 0
}
stock PM_MapTextureTypeStepType(TextureType)
{
switch (TextureType)
{
case CHAR_TEX_METAL: return STEP_METAL
case CHAR_TEX_DIRT: return STEP_DIRT
case CHAR_TEX_VENT: return STEP_VENT
case CHAR_TEX_GRATE: return STEP_GRATE
case CHAR_TEX_TILE: return STEP_TILE
case CHAR_TEX_SLOSH: return STEP_SLOSH
case CHAR_TEX_SNOW: return STEP_SNOW
default: return STEP_CONCRETE
}
return STEP_CONCRETE
}
stock SendShotAnnimation(id, weapon_ent)
{
new ammo = cs_get_weapon_ammo(weapon_ent)
switch (cs_get_weapon_id(weapon_ent))
{
case CSW_AWP:
{
SendWeaponAnim(id, random_num(1,3))
}
case CSW_SCOUT,CSW_XM1014,CSW_SG550,CSW_M3,CSW_M249,CSW_G3SG1:
{
SendWeaponAnim(id, random_num(1,2))
}
case CSW_MAC10,CSW_AUG,CSW_UMP45,CSW_GALIL,CSW_FAMAS,CSW_MP5NAVY,CSW_TMP,CSW_SG552,CSW_AK47,CSW_P90:
{
SendWeaponAnim(id, random_num(3,5))
}
case CSW_P228:
{
if (ammo != 0)
SendWeaponAnim(id, random_num(1,3))
else
SendWeaponAnim(id, 4)
}
case CSW_FIVESEVEN, CSW_DEAGLE:
{
if (ammo != 0)
SendWeaponAnim(id, random_num(1,2))
else
SendWeaponAnim(id, 3)
}
case CSW_GLOCK18:
{
if (ammo != 0)
SendWeaponAnim(id, random_num(3,5))
else
SendWeaponAnim(id, 6)
}
case CSW_M4A1:
{
if (cs_get_weapon_silen(weapon_ent))
SendWeaponAnim(id, random_num(1,3))
else
SendWeaponAnim(id, random_num(8,10))
}
case CSW_USP:
{
if (ammo == 0)
{
if (cs_get_weapon_silen(weapon_ent))
SendWeaponAnim(id, 4)
else
SendWeaponAnim(id, 12)
}
else
{
if (cs_get_weapon_silen(weapon_ent))
SendWeaponAnim(id, random_num(1,3))
else
SendWeaponAnim(id, random_num(9,11))
}
}
case CSW_ELITE:
{
if (ammo % 2 == 1)
{
if (ammo != 1)
SendWeaponAnim(id, random_num(2, 6))
else
SendWeaponAnim(id, 7)
}
if (ammo % 2 == 0)
{
if (ammo != 0)
SendWeaponAnim(id, random_num(8, 12))
else
SendWeaponAnim(id, 13)
}
}
}
return 0
}
stock SendWeaponAnim(id, iAnim)
{
set_pev(id, pev_weaponanim, iAnim)
message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, _, id)
write_byte(iAnim)
write_byte(pev(id,pev_body))
message_end()
}
stock xs_vec_add(const Float:in1[], const Float:in2[], Float:out[])
{
out[0] = in1[0] + in2[0];
out[1] = in1[1] + in2[1];
out[2] = in1[2] + in2[2];
}
stock xs_vec_sub(const Float:in1[], const Float:in2[], Float:out[])
{
out[0] = in1[0] - in2[0];
out[1] = in1[1] - in2[1];
out[2] = in1[2] - in2[2];
}
stock xs_vec_mul_scalar(const Float:vec[], Float:scalar, Float:out[])
{
out[0] = vec[0] * scalar;
out[1] = vec[1] * scalar;
out[2] = vec[2] * scalar;
}
stock Float:xs_vec_len(const Float:vec[3])
{
return floatsqroot(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
}
stock Float:xs_vec_dot(const Float:vec[], const Float:vec2[])
{
return (vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2])
}
stock bool:xs_vec_equal(const Float:vec1[], const Float:vec2[])
{
return (vec1[0] == vec2[0]) && (vec1[1] == vec2[1]) && (vec1[2] == vec2[2]);
}