Как правильно сделать когда человек бросает святую гранату, при условии что зомби попали под ее взрыв, у человека воспроизводился определенный звук, пробовал сам сделать, вот только получается что когда рядом находится два и более зомби у человека воспроизводится сразу несколько звуков... Как сделать даже если рядом несколько целей, попавших под взрыв гранаты у человека воспроизводился всего один звук а не воспроизводился несколько раз в не зависимости от того, сколько зомби попало под взрыв гранаты?
Код:
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <zombieplague>
#include <xs>
#define MAX_CLIENTS 32
#define DMG_GRENADE (1<<24)
#define TASKID_HOLYBOMB_BURN 3900
#define linux_diff_weapon 4
#define linux_diff_player 5
#define m_pPlayer 41
#define m_LastHitGroup 75
new const WEAPON_REFERENCE[] = "weapon_smokegrenade";
new const WEAPON_DEFAULT_WORLD_MODEL[] = "models/w_smokegrenade.mdl";
const WEAPON_DEFAULT_CSW = CSW_SMOKEGRENADE;
new const WEAPON_AMMO_TYPE[] = "SmokeGrenade";
const WEAPON_SPECIAL_CODE = 6666;
new const WEAPON_VIEW_MODEL[] = "models/x/v_holybomb.mdl";
new const WEAPON_PLAYER_MODEL[] = "models/x/p_holybomb.mdl";
new const WEAPON_WORLD_MODEL[] = "models/x/w_holybomb.mdl";
const WEAPON_WORLD_MODEL_BODY = 0;
new const WEAPON_EXPLODE_SOUND[] = "weapons/holywater_explosion.wav";
new const WEAPON_EXPLODE_SPRITE[] = "sprites/x/holybomb_exp.spr";
new const WEAPON_BURN_SPRITE[] = "sprites/x/holybomb_burn.spr"
const Float: WEAPON_GRENADE_RADIUS = 150.0; // Радиус взрыва, в котором заденет всех врагов
const Float: WEAPON_GRENADE_DAMAGE = 700.0; // Урон при взрыве
const WEAPON_GRENADE_DMGTYPE = DMG_GRENADE; // Тип урона при взрыве
const Float: GRENADE_BURN_DELAY = 1.0; // С каким промежутком времени будет проходить урон
const Float: GRENADE_BURN_DAMAGE = 200.0; // Кол-во урона за 1 сек
const GRENADE_BURN_DURATION = 10; // Длительность горения
new const WEAPON_WEAPONLIST_DIR[] = "x/weapon_holybomb";
new const iWeaponList[] =
{
//11, 2, -1, -1, 3, 2, 25, 24 // weapon_flashbang
//12, 1, -1, -1, 3, 1, 4, 24 // weapon_hegrenade
13, 1, -1, -1, 3, 3, 9, 24 // weapon_smokegrenade
};
new gl_iItemID,
gl_iszModelIndex_Burn,
gl_iszModelIndex_Smoke,
gl_iszModelIndex_Explode,
gl_iUserHasHolyBomb[MAX_CLIENTS + 1],
gl_iUserBurningDuration[MAX_CLIENTS + 1],
gl_iMsgID_WeaponList,
gl_iMsgId_DeathMsg;
public plugin_init()
{
register_plugin("[ZP] Grenade: Holy Bomb", "1.0 | 2019", "xUnicorn (t3rkecorejz)");
register_forward(FM_SetModel, "FM_Hook_SetModel_Pre", false);
RegisterHam(Ham_Think, "grenade", "CGrenade__Think_Pre", false);
RegisterHam(Ham_Touch, "grenade", "CGrenade__Touch_Pre", false);
RegisterHam(Ham_Item_Deploy, WEAPON_REFERENCE, "CGrenade__Deploy_Post", true);
RegisterHam(Ham_Item_AddToPlayer, WEAPON_REFERENCE, "CGrenade__AddToPlayer_Post", true);
gl_iItemID = zp_register_extra_item("Holy Bomb", 10, ZP_TEAM_HUMAN);
gl_iMsgID_WeaponList = get_user_msgid("WeaponList");
gl_iMsgId_DeathMsg = get_user_msgid("DeathMsg");
}
public plugin_precache()
{
register_clcmd(WEAPON_WEAPONLIST_DIR, "Command_HookWeapon");
// Models
engfunc(EngFunc_PrecacheModel, WEAPON_VIEW_MODEL);
engfunc(EngFunc_PrecacheModel, WEAPON_PLAYER_MODEL);
engfunc(EngFunc_PrecacheModel, WEAPON_WORLD_MODEL);
// Sounds
engfunc(EngFunc_PrecacheSound, WEAPON_EXPLODE_SOUND);
UTIL_PrecacheSoundsFromModel(WEAPON_VIEW_MODEL);
// Other
UTIL_PrecacheSpritesFromTxt(WEAPON_WEAPONLIST_DIR);
// Model Index
gl_iszModelIndex_Burn = engfunc(EngFunc_PrecacheModel, WEAPON_BURN_SPRITE);
gl_iszModelIndex_Smoke = engfunc(EngFunc_PrecacheModel, "sprites/black_smoke3.spr");
gl_iszModelIndex_Explode = engfunc(EngFunc_PrecacheModel, WEAPON_EXPLODE_SPRITE);
}
public Command_HookWeapon(iPlayer)
{
engclient_cmd(iPlayer, WEAPON_REFERENCE);
return PLUGIN_HANDLED;
}
public Command_GiveWeapon(iPlayer)
{
if(user_has_weapon(iPlayer, WEAPON_DEFAULT_CSW))
{
gl_iUserHasHolyBomb[iPlayer]++;
ExecuteHamB(Ham_GiveAmmo, iPlayer, 1, WEAPON_AMMO_TYPE, 5);
emit_sound(iPlayer, CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
}
else
{
gl_iUserHasHolyBomb[iPlayer] = 1;
UTIL_GiveNamedItem(iPlayer, WEAPON_REFERENCE);
emit_sound(iPlayer, CHAN_ITEM, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
gl_iUserHasHolyBomb[iPlayer]++;
ExecuteHamB(Ham_GiveAmmo, iPlayer, 1, WEAPON_AMMO_TYPE, 5);
}
}
// [ Zombie Plague ]
public zp_extra_item_selected(iPlayer, iItemID)
{
if(iItemID == gl_iItemID)
Command_GiveWeapon(iPlayer);
}
public zp_user_infected_post(iPlayer)
{
if(!is_user_connected(iPlayer)) return;
if(gl_iUserHasHolyBomb[iPlayer]) gl_iUserHasHolyBomb[iPlayer] = 0;
}
// [ Fakemeta ]
public FM_Hook_SetModel_Pre(iEntity, const szModel[])
{
if(!pev_valid(iEntity)) return FMRES_IGNORED;
new Float: flDamageTime; pev(iEntity, pev_dmgtime, flDamageTime);
if(flDamageTime == 0.0) return FMRES_IGNORED;
new iOwner = pev(iEntity, pev_owner);
if(equal(szModel, WEAPON_DEFAULT_WORLD_MODEL))
{
if(gl_iUserHasHolyBomb[iOwner])
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
write_byte(TE_KILLBEAM);
write_short(iEntity);
message_end();
set_pev(iEntity, pev_body, WEAPON_WORLD_MODEL_BODY);
set_pev(iEntity, pev_flTimeStepSound, WEAPON_SPECIAL_CODE);
set_pev(iEntity, pev_sequence, random_num(1, 2));
set_pev(iEntity, pev_animtime, get_gametime());
set_pev(iEntity, pev_framerate, 1.0);
engfunc(EngFunc_SetModel, iEntity, WEAPON_WORLD_MODEL);
gl_iUserHasHolyBomb[iOwner] -= 1;
return FMRES_SUPERCEDE;
}
}
return FMRES_IGNORED;
}
// [ HamSandwich ]
public CGrenade__Think_Pre(iEntity)
{
if(!pev_valid(iEntity)) return HAM_IGNORED;
static Float: flDamageTime; pev(iEntity, pev_dmgtime, flDamageTime);
if(flDamageTime > get_gametime()) return HAM_IGNORED;
if(pev(iEntity, pev_flTimeStepSound) == WEAPON_SPECIAL_CODE)
{
new iOwner = pev(iEntity, pev_owner);
emit_sound(iEntity, CHAN_WEAPON, WEAPON_EXPLODE_SOUND, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
new Float: vecOrigin[3]; pev(iEntity, pev_origin, vecOrigin);
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_EXPLOSION);
engfunc(EngFunc_WriteCoord, vecOrigin[0]);
engfunc(EngFunc_WriteCoord, vecOrigin[1]);
engfunc(EngFunc_WriteCoord, vecOrigin[2] + 20.0);
write_short(gl_iszModelIndex_Explode);
write_byte(20); // Scale
write_byte(32); // Framerate
write_byte(TE_EXPLFLAG_NODLIGHTS|TE_EXPLFLAG_NOSOUND|TE_EXPLFLAG_NOPARTICLES);
message_end();
new iVictim = FM_NULLENT;
while((iVictim = engfunc(EngFunc_FindEntityInSphere, iVictim, vecOrigin, WEAPON_GRENADE_RADIUS)) > 0)
{
if(!is_user_alive(iVictim)) continue;
if(!zp_get_user_zombie(iVictim)) continue;
if(!is_wall_between_points(iOwner, iVictim)) continue;
if(is_user_alive(iVictim))
set_pdata_int(iVictim, m_LastHitGroup, HIT_GENERIC, linux_diff_player);
ExecuteHamB(Ham_TakeDamage, iVictim, iEntity, iOwner, WEAPON_GRENADE_DAMAGE, WEAPON_GRENADE_DMGTYPE);
new iParams[2]; iParams[0] = iOwner;
gl_iUserBurningDuration[iVictim] += GRENADE_BURN_DURATION;
if(!task_exists(iVictim + TASKID_HOLYBOMB_BURN))
set_task(GRENADE_BURN_DELAY, "CTask__Burn_HolyBomb", iVictim + TASKID_HOLYBOMB_BURN, iParams, sizeof iParams);
}
set_pev(iEntity, pev_flags, FL_KILLME);
return HAM_SUPERCEDE;
}
return HAM_IGNORED;
}
public CGrenade__Touch_Pre(iEntity)
{
if(!pev_valid(iEntity)) return HAM_IGNORED;
if(pev(iEntity, pev_flTimeStepSound) == WEAPON_SPECIAL_CODE)
{
new Float: vecOrigin[3]; pev(iEntity, pev_origin, vecOrigin);
if(engfunc(EngFunc_PointContents, vecOrigin) == CONTENTS_WATER)
{
set_pev(iEntity, pev_flags, FL_KILLME);
return HAM_IGNORED;
}
set_pev(iEntity, pev_dmgtime, get_gametime());
}
return HAM_IGNORED;
}
public CGrenade__Deploy_Post(iItem)
{
static iPlayer; iPlayer = get_pdata_cbase(iItem, m_pPlayer, linux_diff_weapon);
if(!gl_iUserHasHolyBomb[iPlayer]) return HAM_IGNORED;
if(zp_get_user_zombie(iPlayer)) return HAM_IGNORED;
set_pev(iPlayer, pev_viewmodel2, WEAPON_VIEW_MODEL);
set_pev(iPlayer, pev_weaponmodel2, WEAPON_PLAYER_MODEL);
return HAM_IGNORED;
}
public CGrenade__AddToPlayer_Post(iItem, iPlayer) UTIL_WeaponList(iPlayer, gl_iUserHasHolyBomb[iPlayer]);
// [ Tasks ]
public CTask__Burn_HolyBomb(szArgs[1], iTask)
{
new iOwner = szArgs[0];
new iVictim = iTask - TASKID_HOLYBOMB_BURN;
new iFlags = pev(iVictim, pev_flags);
new Float: vecOrigin[3]; pev(iVictim, pev_origin, vecOrigin);
if(!is_user_alive(iVictim) || !is_user_connected(iOwner) || iOwner == iVictim || zp_get_user_zombie(iOwner) || iFlags & FL_INWATER || gl_iUserBurningDuration[iVictim] < 1)
{
engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecOrigin, 0);
write_byte(TE_SMOKE);
engfunc(EngFunc_WriteCoord, vecOrigin[0]);
engfunc(EngFunc_WriteCoord, vecOrigin[1]);
engfunc(EngFunc_WriteCoord, vecOrigin[2] - 50.0);
write_short(gl_iszModelIndex_Smoke);
write_byte(random_num(15, 20)); // Scale
write_byte(random_num(10, 20)); // Framerate
message_end();
remove_task(iTask);
return;
}
new flHealth = pev(iVictim, pev_health);
if(flHealth - GRENADE_BURN_DAMAGE > 0.0)
{
if(is_user_alive(iVictim))
set_pdata_int(iVictim, m_LastHitGroup, HIT_GENERIC, linux_diff_player);
ExecuteHamB(Ham_TakeDamage, iVictim, iOwner, iOwner, GRENADE_BURN_DAMAGE, WEAPON_GRENADE_DMGTYPE);
}
else
{
set_pdata_int(iVictim, m_LastHitGroup, HIT_GENERIC, linux_diff_player);
set_msg_block(gl_iMsgId_DeathMsg, BLOCK_SET);
ExecuteHamB(Ham_Killed, iVictim, iOwner, 0);
set_msg_block(gl_iMsgId_DeathMsg, BLOCK_NOT);
message_begin(MSG_ALL, gl_iMsgId_DeathMsg);
write_byte(iOwner);
write_byte(iVictim);
write_byte(0);
write_string("grenade");
message_end();
engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecOrigin, 0);
write_byte(TE_SMOKE);
engfunc(EngFunc_WriteCoord, vecOrigin[0]);
engfunc(EngFunc_WriteCoord, vecOrigin[1]);
engfunc(EngFunc_WriteCoord, vecOrigin[2] - 50.0);
write_short(gl_iszModelIndex_Smoke);
write_byte(random_num(15, 20)); // Scale
write_byte(random_num(10, 20)); // Framerate
message_end();
remove_task(iTask);
return;
}
engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecOrigin, 0);
write_byte(TE_SPRITE);
engfunc(EngFunc_WriteCoord, vecOrigin[0] + random_float(-5.0, 5.0));
engfunc(EngFunc_WriteCoord, vecOrigin[1] + random_float(-5.0, 5.0));
engfunc(EngFunc_WriteCoord, vecOrigin[2] + random_float(-10.0, 10.0));
write_short(gl_iszModelIndex_Burn);
write_byte(random_num(5, 7)); // Scale
write_byte(200); // Alpha
message_end();
gl_iUserBurningDuration[iVictim]--;
set_task(GRENADE_BURN_DELAY, "CTask__Burn_HolyBomb", iTask, szArgs, sizeof szArgs);
}
// [ Stocks ]
stock is_wall_between_points(iPlayer, iEntity)
{
if(!is_user_alive(iEntity))
return 0;
new iTrace = create_tr2();
new Float: flStart[3], Float: flEnd[3], Float: flEndPos[3];
pev(iPlayer, pev_origin, flStart);
pev(iEntity, pev_origin, flEnd);
engfunc(EngFunc_TraceLine, flStart, flEnd, IGNORE_MONSTERS, iPlayer, iTrace);
get_tr2(iTrace, TR_vecEndPos, flEndPos);
free_tr2(iTrace);
return xs_vec_equal(flEnd, flEndPos);
}
stock UTIL_GiveNamedItem(iPlayer, const szItem[])
{
new iEntity = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, szItem));
if(!pev_valid(iEntity)) return 0;
ExecuteHam(Ham_Spawn, iEntity);
if(!ExecuteHamB(Ham_AddPlayerItem, iPlayer, iEntity))
{
set_pev(iEntity, pev_flags, pev(iEntity, pev_flags) | FL_KILLME);
return 0;
}
ExecuteHamB(Ham_Item_AttachToPlayer, iEntity, iPlayer);
return iEntity;
}
stock UTIL_PrecacheSoundsFromModel(const szModelPath[])
{
new iFile;
if((iFile = fopen(szModelPath, "rt")))
{
new szSoundPath[64];
new iNumSeq, iSeqIndex;
new iEvent, iNumEvents, iEventIndex;
fseek(iFile, 164, SEEK_SET);
fread(iFile, iNumSeq, BLOCK_INT);
fread(iFile, iSeqIndex, BLOCK_INT);
for(new k, i = 0; i < iNumSeq; i++)
{
fseek(iFile, iSeqIndex + 48 + 176 * i, SEEK_SET);
fread(iFile, iNumEvents, BLOCK_INT);
fread(iFile, iEventIndex, BLOCK_INT);
fseek(iFile, iEventIndex + 176 * i, SEEK_SET);
for(k = 0; k < iNumEvents; k++)
{
fseek(iFile, iEventIndex + 4 + 76 * k, SEEK_SET);
fread(iFile, iEvent, BLOCK_INT);
fseek(iFile, 4, SEEK_CUR);
if(iEvent != 5004)
continue;
fread_blocks(iFile, szSoundPath, 64, BLOCK_CHAR);
if(strlen(szSoundPath))
{
strtolower(szSoundPath);
engfunc(EngFunc_PrecacheSound, szSoundPath);
}
}
}
}
fclose(iFile);
}
stock UTIL_PrecacheSpritesFromTxt(const szWeaponList[])
{
new szTxtDir[64], szSprDir[64];
new szFileData[128], szSprName[48], temp[1];
format(szTxtDir, charsmax(szTxtDir), "sprites/%s.txt", szWeaponList);
engfunc(EngFunc_PrecacheGeneric, szTxtDir);
new iFile = fopen(szTxtDir, "rb");
while(iFile && !feof(iFile))
{
fgets(iFile, szFileData, charsmax(szFileData));
trim(szFileData);
if(!strlen(szFileData))
continue;
new pos = containi(szFileData, "640");
if(pos == -1)
continue;
format(szFileData, charsmax(szFileData), "%s", szFileData[pos+3]);
trim(szFileData);
strtok(szFileData, szSprName, charsmax(szSprName), temp, charsmax(temp), ' ', 1);
trim(szSprName);
format(szSprDir, charsmax(szSprDir), "sprites/%s.spr", szSprName);
engfunc(EngFunc_PrecacheGeneric, szSprDir);
}
if(iFile) fclose(iFile);
}
stock UTIL_WeaponList(iPlayer, iEnabled)
{
message_begin(MSG_ONE, gl_iMsgID_WeaponList, _, iPlayer);
write_string(iEnabled ? WEAPON_WEAPONLIST_DIR : WEAPON_REFERENCE);
write_byte(iWeaponList[0]);
write_byte(iWeaponList[1]);
write_byte(iWeaponList[2]);
write_byte(iWeaponList[3]);
write_byte(iWeaponList[4]);
write_byte(iWeaponList[5]);
write_byte(iWeaponList[6]);
write_byte(iWeaponList[7]);
message_end();
}