Загрузка данных
#include <amxmisc>
#include <fakemeta>
#include <hamsandwich>
#include <json>
#include <reapi>
#include <bitmask>
native bio_get_user_money(id);
native bio_set_user_money(id, amount, bool:flash = true);
#if AMXX_VERSION_NUM < 190
#assert Outdated version of AMX Mod X (AMXX_VERSION_NUM), please update in order to use this plugin properly.
#endif
#pragma semicolon 1
new const TEXT_MESSAGE[][] =
{
"#Game_Commencing",
"#Cstrike_Tutor_Round_Over",
"#Round_Draw",
"#Game_will_restart_in",
"#CTs_Win",
"#Terrorists_Win"
};
new const SEND_AUDIO[][] =
{
"%!MRAD_rounddraw",
"%!MRAD_terwin",
"%!MRAD_ctwin"
};
new const ZOMBIE_SCREAM[][] =
{
"biohazard/scream1.wav",
"biohazard/scream2.wav",
"biohazard/scream3.wav"
};
new const IMMUTABLE_CVARS[][][] =
{
{"mp_limitteams", "0"},
{"mp_autoteambalance", "0"},
{"mp_round_infinite", "b"},
{"mp_roundover", "1"},
{"mp_auto_join_team", "1"},
{"humans_join_team", "CT"},
{"mp_autokick", "0"}
};
new m_cImmutableCvars[sizeof IMMUTABLE_CVARS];
enum
{
TASKID_WARMUP
};
enum _:ClassData
{
ClassName[32],
Float:ClassHealth,
Float:ClassSpeed,
Float:ClassGravity,
ClassModel[64],
ClassClaw[64]
};
new Array:m_arrClassesVec = Invalid_Array;
enum _:SpawnData
{
Float:SpawnOrigin[3],
Float:SpawnAngles[3]
};
new Array:m_arrSpawnPointsVec = Invalid_Array;
new Array:m_arrDefaultSpawnPointsVec = Invalid_Array;
new m_szMapName[64];
new m_szSpawnFile[PLATFORM_MAX_PATH];
new m_iNumClasses;
new m_iNumSpawnPoints;
new m_iMenuPosition[MAX_CLIENTS + 1];
new m_iLastSpawn;
new Trie:m_trUselessEntities = Invalid_Trie;
new Trie:m_trTextMessage = Invalid_Trie;
new Trie:m_trSendAudio = Invalid_Trie;
new bool:m_bWarmup = true;
new bool:m_bZombieRespawnAllowed;
new m_pCvar_FreezeTime;
new m_pCvar_RoundTime;
new m_pCvar_OverHumansWin;
new m_pCvar_ZombieRespawnTime;
new m_pCvar_ZombieRespawnMinDistance;
new m_pCvar_ZombieRespawnLimit;
new m_pCvar_ZombieRespawnChanceDecay;
new m_pCvar_MoneyAsJoin;
new m_pCvar_MoneyDamageRatio;
new m_pCvar_MoneyInfection;
new m_pCvar_MoneyKill;
new m_pCvar_ZombieRegenAmount;
new m_pCvar_ZombieRegenInterval;
new m_pCvar_ZombieRegenDelay;
new m_fwdSpawn;
new m_varClass[MAX_CLIENTS + 1];
new m_iZombieRespawn[MAX_CLIENTS + 1];
new m_iMoney[MAX_CLIENTS + 1];
new Float:m_flZombieRegenTime[MAX_CLIENTS + 1];
new Float:m_flZombieLastDamage[MAX_CLIENTS + 1];
new m_bitZombie;
new m_bitZombieRespawn;
public plugin_precache()
{
register_plugin("Biohazard", "0.0.1", "oxsi. x Vision");
m_arrClassesVec = ArrayCreate(ClassData);
m_trTextMessage = TrieCreate();
for (new i; i < sizeof TEXT_MESSAGE; i++)
TrieSetCell(m_trTextMessage, TEXT_MESSAGE[i], 0);
m_trSendAudio = TrieCreate();
for (new i; i < sizeof SEND_AUDIO; i++)
TrieSetCell(m_trSendAudio, SEND_AUDIO[i], 0);
for (new i; i < sizeof ZOMBIE_SCREAM; i++)
precache_sound(ZOMBIE_SCREAM[i]);
for (new i; i < sizeof IMMUTABLE_CVARS; i++)
{
m_cImmutableCvars[i] = get_cvar_pointer(IMMUTABLE_CVARS[i][0]);
set_pcvar_string(
m_cImmutableCvars[i],
IMMUTABLE_CVARS[i][1]
);
hook_cvar_change(
m_cImmutableCvars[i],
"@Hook_ForcingCvarChange"
);
}
m_pCvar_FreezeTime = get_cvar_pointer("mp_freezetime");
m_pCvar_RoundTime = get_cvar_pointer("mp_roundtime");
set_pcvar_flags(
m_pCvar_FreezeTime,
get_pcvar_flags(m_pCvar_FreezeTime) | FCVAR_UNLOGGED
);
set_pcvar_flags(
m_pCvar_RoundTime,
get_pcvar_flags(m_pCvar_RoundTime) | FCVAR_UNLOGGED
);
if (m_bWarmup)
{
set_pcvar_num(m_pCvar_FreezeTime, 0);
set_pcvar_float(m_pCvar_RoundTime, 20.0 / 60.0);
set_task_ex(
1.0,
"@Task_Warmup",
TASKID_WARMUP,
.flags = SetTask_Repeat
);
}
else
{
set_pcvar_num(m_pCvar_FreezeTime, 15);
set_pcvar_float(m_pCvar_RoundTime, 180.0 / 60.0);
}
if (!Read_JsonField("biohazard"))
set_fail_state("Failed to read biohazard config.");
}
public plugin_init()
{
m_pCvar_OverHumansWin =
register_cvar("bio_over_humans_win", "1");
m_pCvar_ZombieRespawnTime =
register_cvar("bio_zombie_respawn", "3.0");
m_pCvar_ZombieRespawnMinDistance =
register_cvar("bio_zombie_respawn_min_distance", "1200.0");
m_pCvar_ZombieRespawnLimit =
register_cvar("bio_zombie_respawn_limit", "3");
m_pCvar_ZombieRespawnChanceDecay =
register_cvar("bio_zombie_chance_decay", "25.0");
m_pCvar_MoneyAsJoin =
register_cvar("bio_money_join", "350");
m_pCvar_MoneyDamageRatio =
register_cvar("bio_money_damage_ratio", "0.26");
m_pCvar_MoneyInfection =
register_cvar("bio_money_infection", "100");
m_pCvar_MoneyKill =
register_cvar("bio_money_kill", "100");
m_pCvar_ZombieRegenAmount =
register_cvar("bio_zombie_regen_amount", "1.0");
m_pCvar_ZombieRegenInterval =
register_cvar("bio_zombie_regen_interval", "0.15");
m_pCvar_ZombieRegenDelay =
register_cvar("bio_zombie_regen_delay", "2.48");
register_clcmd("say /class", "@Open_ClassesMenu");
register_clcmd("say_team /class", "@Open_ClassesMenu");
register_clcmd("infect", "cmd_infect");
register_clcmd("antidote", "cmd_antidote");
register_menucmd(
register_menuid("@Display_ClassesMenu"),
(
1 << 0 |
1 << 1 |
1 << 2 |
1 << 3 |
1 << 4 |
1 << 5 |
1 << 6 |
1 << 7 |
1 << 8 |
1 << 9
),
"@Handle_ClassesMenu"
);
register_message(
get_user_msgid("TextMsg"),
"@Message_TextMsg"
);
register_message(
get_user_msgid("SendAudio"),
"@Message_SendAudio"
);
register_message(
get_user_msgid("Money"),
"@Message_Money"
);
RegisterHookChain(
RH_SV_ActivateServer,
"@SV_ActivateServer_Post",
true
);
RegisterHookChain(
RG_RoundEnd,
"@RoundEnd_Pre"
);
RegisterHookChain(
RG_RoundEnd,
"@RoundEnd_Post",
true
);
RegisterHookChain(
RG_CSGameRules_RestartRound,
"@CSGameRules_RestartRound_Pre"
);
RegisterHookChain(
RG_CSGameRules_RestartRound,
"@CSGameRules_RestartRound_Post",
true
);
RegisterHookChain(
RG_CSGameRules_CheckWinConditions,
"@CSGameRules_CheckWinConditions_Pre"
);
RegisterHookChain(
RG_CSGameRules_FPlayerCanTakeDamage,
"@CSGameRules_FPlayerCanTakeDamage_Pre"
);
RegisterHookChain(
RG_CSGameRules_OnRoundFreezeEnd,
"@CSGameRules_OnRoundFreezeEnd_Pre"
);
RegisterHookChain(
RG_CSGameRules_GetPlayerSpawnSpot,
"@CSGameRules_GetPlayerSpawnSpot_Pre"
);
RegisterHookChain(
RG_CBasePlayer_Spawn,
"@CBasePlayer_Spawn_Pre"
);
RegisterHookChain(
RG_CBasePlayer_Spawn,
"@CBasePlayer_Spawn_Post",
true
);
RegisterHookChain(
RG_CBasePlayer_HasRestrictItem,
"@CBasePlayer_HasRestrictItem_Pre"
);
RegisterHookChain(
RG_CBasePlayer_AddAccount,
"@CBasePlayer_AddAccount_Pre"
);
RegisterHookChain(
RG_CBasePlayer_TakeDamage,
"@CBasePlayer_TakeDamage_Pre"
);
RegisterHookChain(
RG_CBasePlayer_ResetMaxSpeed,
"@CBasePlayer_ResetMaxSpeed_Pre"
);
RegisterHookChain(
RG_CBasePlayer_Killed,
"@CBasePlayer_Killed_Post",
true
);
RegisterHookChain(
RG_CBasePlayer_PreThink,
"@CBasePlayer_PreThink_Pre"
);
}
public plugin_cfg()
{
m_arrSpawnPointsVec = ArrayCreate(SpawnData);
m_arrDefaultSpawnPointsVec = ArrayCreate(1);
get_mapname(
m_szMapName,
charsmax(m_szMapName)
);
get_localinfo(
"amxx_configsdir",
m_szSpawnFile,
charsmax(m_szSpawnFile)
);
add(
m_szSpawnFile,
charsmax(m_szSpawnFile),
"/biohazard/spawns.json"
);
/*
* Загружаем стандартные spawn entity.
*/
@Load_DefaultSpawnPoints();
/*
* Загружаем custom spawn points
* только для текущей карты.
*/
Load_SpawnPoints();
/*
* После загрузки spawn points
* обновляем количество spawn points
* в GameRules.
*/
@Forcing_LevelInitialize();
}
public plugin_natives()
{
register_native(
"bio_get_user_money",
"@native_get_user_money"
);
register_native(
"bio_set_user_money",
"@native_set_user_money"
);
}
public plugin_end()
{
if (m_trUselessEntities != Invalid_Trie)
TrieDestroy(m_trUselessEntities);
if (m_trTextMessage != Invalid_Trie)
TrieDestroy(m_trTextMessage);
if (m_trSendAudio != Invalid_Trie)
TrieDestroy(m_trSendAudio);
if (m_arrClassesVec != Invalid_Array)
ArrayDestroy(m_arrClassesVec);
if (m_arrSpawnPointsVec != Invalid_Array)
ArrayDestroy(m_arrSpawnPointsVec);
if (m_arrDefaultSpawnPointsVec != Invalid_Array)
ArrayDestroy(m_arrDefaultSpawnPointsVec);
}
public client_putinserver(id)
{
m_varClass[id] = 0;
}
public client_disconnected(id)
{
m_varClass[id] = 0;
m_iZombieRespawn[id] = 0;
m_iMoney[id] = 0;
m_flZombieRegenTime[id] = 0.0;
m_flZombieLastDamage[id] = 0.0;
BIT_SUB(m_bitZombie, id);
BIT_SUB(m_bitZombieRespawn, id);
}
public cmd_infect(id)
{
@ZombieAttributes(id, 0);
}
public cmd_antidote(id)
{
@HumanAttributes(id);
}
@Open_ClassesMenu(id)
{
if (!m_iNumClasses)
{
client_print(
id,
print_chat,
"Zombie classes not found!"
);
return PLUGIN_HANDLED;
}
m_iMenuPosition[id] = 0;
return @Display_ClassesMenu(id, 0);
}
@Display_ClassesMenu(id, pos)
{
if (pos < 0)
return PLUGIN_HANDLED;
new start = pos * 7;
if (start > m_iNumClasses)
start = m_iNumClasses;
start -= start % 7;
pos = start / 7;
new end = start + 7;
if (end > m_iNumClasses)
end = m_iNumClasses;
new page =
(m_iNumClasses / 7) +
(m_iNumClasses % 7 ? 1 : 0);
new key = 1 << 9;
new menu[512];
new data[ClassData];
new len = formatex(
menu,
charsmax(menu),
"\yClasses %d/%d^n^n",
pos + 1,
page
);
new item;
while (start < end)
{
ArrayGetArray(
m_arrClassesVec,
start,
data
);
if (m_varClass[id] != start)
key |= 1 << item;
len += formatex(
menu[len],
charsmax(menu) - len,
"\