Загрузка данных
#include < amxmisc >
#include < fakemeta >
#include < hamsandwich >
#include < json >
#include < reapi >
#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
#include < bitmask >
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" }
};
new m_cImmutableCvars[ sizeof( IMMUTABLE_CVARS ) ];
enum ( += 100 )
{
TASKID_WARMUP,
TASKID_LAUNCHGAME
};
enum _: ClassData
{
ClassName[ 32 ],
Float: ClassHealth,
Float: ClassSpeed,
Float: ClassGravity,
ClassModel[ 64 ],
ClassClaw[ 64 ]
};
new Array: m_arrClassesVec = Invalid_Array,
m_iNumClasses;
new m_iMenuPosition[ MAX_CLIENTS + 1 ];
new Array: m_arrSpawnPoints = Invalid_Array,
m_iLastSpawn;
// Plugin's hash maps.
new Trie: m_trUselessEntities = Invalid_Trie,
Trie: m_trTextMessage = Invalid_Trie,
Trie: m_trSendAudio = Invalid_Trie;
// Plugin's vars.
new bool: m_bWarmup = true;
// Plugin's cvars.
new m_pCvar_FreezeTime,
m_pCvar_RoundTime,
m_pCvar_OverHumansWin;
// Plugin's forwards.
new m_fwdSpawn;
// Client's vars.
new m_varClass[ MAX_CLIENTS + 1 ];
// Client's bits.
new m_bitZombie;
public plugin_precache( )
{
register_plugin( "Biohazard", "0.0.1", "oxsi. x Vision" );
m_arrClassesVec = ArrayCreate( ClassData );
m_arrSpawnPoints = ArrayCreate( 1, 0 );
m_trTextMessage = TrieCreate( );
for ( new i = 0; i < sizeof( TEXT_MESSAGE ); i++ )
TrieSetCell( m_trTextMessage, TEXT_MESSAGE[ i ], 0 );
m_trSendAudio = TrieCreate( );
for ( new i = 0; i < sizeof( SEND_AUDIO ); i++ )
TrieSetCell( m_trSendAudio, SEND_AUDIO[ i ], 0 );
for ( new i = 0; i < sizeof( ZOMBIE_SCREAM ); i++ )
precache_sound( ZOMBIE_SCREAM[ i ] );
for ( new i = 0; 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, 60.0 / 60.0 );
}
if ( !Read_JsonField( "biohazard" ) )
set_fail_state( "Failed read '%s' file." );
}
public plugin_init( )
{
m_pCvar_OverHumansWin = register_cvar( "bio_over_humans_win", "1" );
register_clcmd( "say /class", "@Open_ClassesMenu" );
register_clcmd( "say_team /class", "@Open_ClassesMenu" );
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" );
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_TakeDamage, "@CBasePlayer_TakeDamage_Pre" );
RegisterHookChain( RG_CBasePlayer_ResetMaxSpeed, "@CBasePlayer_ResetMaxSpeed_Pre" );
@Forcing_LevelInitialize( );
}
public plugin_end( )
{
if ( m_trUselessEntities != Invalid_Trie )
{
TrieDestroy( m_trUselessEntities );
m_trUselessEntities = Invalid_Trie;
}
if ( m_trTextMessage != Invalid_Trie )
{
TrieDestroy( m_trTextMessage );
m_trTextMessage = Invalid_Trie;
}
if ( m_trSendAudio != Invalid_Trie )
{
TrieDestroy( m_trSendAudio );
m_trSendAudio = Invalid_Trie;
}
if ( m_arrClassesVec != Invalid_Array )
{
ArrayDestroy( m_arrClassesVec );
m_arrClassesVec = Invalid_Array;
}
}
public client_putinserver( id )
{
m_varClass[ id ] = 0;
}
public client_disconnected( id )
{
m_varClass[ id ] = 0;
}
@Open_ClassesMenu( id )
{
if ( !m_iNumClasses )
{
client_print( id, print_chat, "Классы зомби не найдены!" );
return PLUGIN_HANDLED;
}
return @Display_ClassesMenu( id, m_iMenuPosition[ id ] = 0 );
}
@Display_ClassesMenu( id, pos )
{
if ( pos < 0 )
return PLUGIN_HANDLED;
new start;
if ( ( start = pos * 7 ) > m_iNumClasses )
start = m_iNumClasses;
start = start - ( start % 7 );
pos = start / 7;
new end;
if ( ( end = start + 7 ) > m_iNumClasses )
end = m_iNumClasses;
new menu[ 512 ], classData[ ClassData ], page = ( m_iNumClasses / 7 + ( ( m_iNumClasses % 7 ) ? 1 : 0 ) ), key = ( 1 << 9 ), k,
len = add( menu, charsmax( menu ), fmt( "\yClasses %d/%d^n^n", pos + 1, page ) );
while ( start < end )
{
ArrayGetArray( m_arrClassesVec, start, classData );
if ( m_varClass[ id ] != start )
key |= ( 1 << k );
if ( m_varClass[ id ] == start )
len += add( menu, charsmax( menu ) - len, fmt( "\y%d. \d%s^n", ++k, classData[ ClassName ] ) );
else
len += add( menu, charsmax( menu ) - len, fmt( "\y%d. \w%s^n", ++k, classData[ ClassName ] ) );
start++;
}
if ( pos )
key |= ( 1 << 7 );
if ( end < m_iNumClasses )
key |= ( 1 << 8 );
len += add( menu, charsmax( menu ) - len, fmt( "^n\y8. %sНазад", pos ? "\w" : "\d" ) );
len += add( menu, charsmax( menu ) - len, fmt( "^n\y9. %sВперёд", end < m_iNumClasses ? "\w" : "\d" ) );
add( menu, charsmax( menu ), "^n\y0. \wВыход" );
return show_menu( id, key, menu, -1, "@Display_ClassesMenu" );
}
@Handle_ClassesMenu( id, key )
{
switch ( key )
{
case 7: @Display_ClassesMenu( id, --m_iMenuPosition[ id ] );
case 8: @Display_ClassesMenu( id, ++m_iMenuPosition[ id ] );
case 9: return PLUGIN_HANDLED;
default:
{
new class = m_iMenuPosition[ id ] * 7 + key;
if ( class >= m_iNumClasses )
return PLUGIN_HANDLED;
m_varClass[ id ] = class;
new classData[ ClassData ];
ArrayGetArray( m_arrClassesVec, class, classData );
client_print( id, print_chat, "Вы выбрали класс %s %d", classData[ ClassName ], m_varClass[ id ] );
}
}
return PLUGIN_CONTINUE;
}
@Hook_ForcingCvarChange( pcvar, old_value[ ], new_value[ ] )
{
for ( new i = 0; i < sizeof( IMMUTABLE_CVARS ); i++ )
{
if ( m_cImmutableCvars[ i ] != pcvar )
continue;
if ( equal( new_value, IMMUTABLE_CVARS[ i ][ 1 ] ) )
continue;
set_pcvar_string( pcvar, IMMUTABLE_CVARS[ i ][ 1 ] );
break;
}
}
@Message_TextMsg( msg_id, msg_dest, receiver )
{
new text[ 32 ], value;
get_msg_arg_string( 2, text, charsmax( text ) );
if ( TrieGetCell( m_trTextMessage, text, value ) )
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
@Message_SendAudio( msg_id, msg_dest, receiver )
{
new text[ 32 ], value;
get_msg_arg_string( 2, text, charsmax( text ) );
if ( TrieGetCell( m_trSendAudio, text, value ) )
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
@Task_Warmup( task )
{
if ( !get_member_game( m_bRoundTerminating ) )
{
new timeLeft = floatround( ( float( get_member_game( m_iRoundTimeSecs ) ) - get_gametime( ) + Float: get_member_game( m_fRoundStartTimeReal ) ) );
if ( timeLeft == 4 )
client_cmd( 0, "spk ^"hgrunt/three.wav^"" );
else if ( timeLeft == 3 )
client_cmd( 0, "spk ^"hgrunt/two.wav^"" );
else if ( timeLeft == 2 )
client_cmd( 0, "spk ^"hgrunt/one.wav^"" );
if ( timeLeft < 1 ) rg_round_end( 3.0, WINSTATUS_DRAW, ROUND_GAME_COMMENCE, .trigger = true );
}
}
@SV_ActivateServer_Post( )
{
if ( m_fwdSpawn )
{
unregister_forward( FM_Spawn, m_fwdSpawn );
m_fwdSpawn = 0;
TrieDestroy( m_trUselessEntities );
m_trUselessEntities = Invalid_Trie;
}
}
@RoundEnd_Pre( WinStatus: status, ScenarioEventEndRound: event, Float: delay )
{
if ( m_bWarmup )
{
SetHookChainArg( 2, ATYPE_INTEGER, ROUND_GAME_COMMENCE );
SetHookChainArg( 3, ATYPE_FLOAT, 3.0 );
return;
}
if ( !get_member_game( m_bGameStarted ) )
return;
if ( status == WINSTATUS_NONE )
status = WINSTATUS_DRAW;
if ( status == WINSTATUS_DRAW )
{
if ( get_pcvar_bool( m_pCvar_OverHumansWin ) )
status = WINSTATUS_CTS;
}
SetHookChainArg( 1, ATYPE_INTEGER, status );
}
@RoundEnd_Post( WinStatus: status, ScenarioEventEndRound: event, Float: delay )
{
if ( m_bWarmup )
return;
switch ( status )
{
case WINSTATUS_CTS:
{
client_print( 0, print_center, "Humans won!" );
client_cmd( 0, " spk ^"ambience/3dmstart.wav^"" );
}
case WINSTATUS_TERRORISTS:
{
client_print( 0, print_center, "Zombies won!" );
client_cmd( 0, "spk ^"ambience/the_horror1.wav^"" );
}
case WINSTATUS_DRAW:
{
client_print( 0, print_center, "No one won!" );
client_cmd( 0, "spk ^"ambience/3dmstart.wav^"" );
}
}
}
@CSGameRules_RestartRound_Pre( )
{
if ( m_bWarmup )
{
m_bWarmup = false;
remove_task( TASKID_WARMUP );
}
set_pcvar_num( m_pCvar_FreezeTime, 15 );
set_pcvar_float( m_pCvar_RoundTime, 60.0 / 60.0 );
}
@CSGameRules_RestartRound_Post( )
{
if ( !m_bWarmup )
set_member_game( m_bGameStarted, true );
@Forcing_LevelInitialize( );
}
@CSGameRules_CheckWinConditions_Pre( )
{
if ( m_bWarmup )
return HC_SUPERCEDE;
return HC_CONTINUE;
}
@CSGameRules_FPlayerCanTakeDamage_Pre( id, attacker )
{
if ( get_member_game( m_bRoundTerminating ) )
{
SetHookChainReturn( ATYPE_INTEGER, false );
return HC_SUPERCEDE;
}
if ( m_bWarmup )
{
SetHookChainReturn( ATYPE_INTEGER, false );
return HC_SUPERCEDE;
}
return HC_CONTINUE;
}
@CSGameRules_OnRoundFreezeEnd_Pre( )
{
if ( !get_member_game( m_bGameStarted ) )
return;
new Array: alives = ArrayCreate( 1, 0 );
for ( new i = 1; i <= MaxClients; i++ )
{
if ( !is_user_alive( i ) )
continue;
ArrayPushCell( alives, i );
}
new num = ArraySize( alives );
if ( num >= 2 )
{
new need_zombies = floatround( float( num ) * 0.20, floatround_ceil );
new id, pos;
while ( need_zombies-- )
{
pos = random( ArraySize( alives ) );
id = ArrayGetCell( alives, pos );
ArrayDeleteItem( alives, pos );
@ZombieAttributes( id, id );
}
}
ArrayDestroy( alives );
}
@CSGameRules_GetPlayerSpawnSpot_Pre( id )
{
if ( TEAM_TERRORIST > get_member( id, m_iTeam ) > TEAM_CT )
return HC_CONTINUE;
new spot = @Select_SpawnPoint( id );
if ( is_nullent( spot ) )
return HC_CONTINUE;
new Float: vecOrigin[ 3 ], Float: vecAngles[ 3 ];
get_entvar( spot, var_origin, vecOrigin );
get_entvar( spot, var_angles, vecAngles );
vecOrigin[ 2 ] += 1.0;
set_entvar( id, var_origin, vecOrigin );
set_entvar( id, var_v_angle, NULL_VECTOR );
set_entvar( id, var_velocity, NULL_VECTOR );
set_entvar( id, var_angles, vecAngles );
set_entvar( id, var_punchangle, NULL_VECTOR );
set_entvar( id, var_fixangle, 1 );
SetHookChainReturn( ATYPE_INTEGER, spot );
return HC_SUPERCEDE;
}
@CBasePlayer_Spawn_Pre( id )
{
if ( get_member( id, m_bJustConnected ) )
return;
if ( TEAM_TERRORIST > get_member( id, m_iTeam ) > TEAM_CT )
return;
if ( get_member_game( m_bGameStarted ) && !get_member_game( m_bFreezePeriod ) )
@ZombieAttributes( id, id );
else
@HuamnAttributes( id, id );
}
@CBasePlayer_Spawn_Post( id )
{
if ( get_member( id, m_bJustConnected ) )
{
set_member( id, m_fNextSuicideTime, 999999999.0 );
return;
}
if ( TEAM_TERRORIST > get_member( id, m_iTeam ) > TEAM_CT )
return;
if ( get_member_game( m_bFreezePeriod ) )
set_member( id, m_bCanShootOverride, true );
}
@CBasePlayer_HasRestrictItem_Pre( id )
{
if ( get_member( id, m_iTeam ) != TEAM_TERRORIST )
return HC_CONTINUE;
SetHookChainReturn( ATYPE_BOOL, true );
return HC_SUPERCEDE;
}
@CBasePlayer_TakeDamage_Pre( victim, inflictor, attacker, Float: damage, damage_type )
{
if ( victim == attacker || !is_user_connected( attacker ) )
return;
if ( !rg_is_player_can_takedamage( victim, attacker ) )
return;
if ( !BIT_VALID( m_bitZombie, BIT_PLAYER( attacker ) ) )
return;
new activeItem = get_member( attacker, m_pActiveItem );
if ( is_nullent( activeItem ) )
return;
if ( get_member( activeItem, m_iId ) != WEAPON_KNIFE )
return;
@ZombieAttributes( victim, attacker );
SetHookChainArg( 4, ATYPE_FLOAT, 0.0 );
}
@CBasePlayer_ResetMaxSpeed_Pre( id )
{
if ( !is_user_alive( id ) )
return HC_CONTINUE;
if ( BIT_VALID( m_bitZombie, BIT_PLAYER( id ) ) )
{
new classData[ ClassData ];
ArrayGetArray( m_arrClassesVec, m_varClass[ id ], classData );
set_entvar( id, var_maxspeed, classData[ ClassSpeed ] );
return HC_SUPERCEDE;
}
new activeItem = get_member( id, m_pActiveItem ), Float: speed;
if ( !is_nullent( activeItem ) )
ExecuteHamB( Ham_CS_Item_GetMaxSpeed, activeItem, speed );
else
speed = 240.0;
set_entvar( id, var_maxspeed, speed );
return HC_SUPERCEDE;
}
@FM_Spawn_Pre( entity )
{
new className[ 32 ];
get_entvar( entity, var_classname, className, charsmax( className ) );
if ( TrieKeyExists( m_trUselessEntities, className ) )
{
forward_return( FMV_CELL, NULLENT );
return FMRES_SUPERCEDE;
}
return FMRES_IGNORED;
}
@ZombieAttributes( id, attacker )
{
BIT_ADD( m_bitZombie, BIT_PLAYER( id ) );
new classData[ ClassData ];
ArrayGetArray( m_arrClassesVec, m_varClass[ id ], classData );
set_entvar( id, var_health, classData[ ClassHealth ] );
set_entvar( id, var_gravity, classData[ ClassGravity ] );
set_entvar( id, var_armorvalue, 0.0 );
set_member( id, m_iKevlar, ARMOR_NONE );
rg_set_user_model( id, classData[ ClassModel ] );
rg_remove_all_items( id );
rg_give_item( id, "weapon_knife" );
set_entvar( id, var_viewmodel, classData[ ClassClaw ] );
set_entvar( id, var_weaponmodel, NULL_STRING );
rh_emit_sound2( id, 0, CHAN_VOICE, ZOMBIE_SCREAM[ random( sizeof( ZOMBIE_SCREAM ) ) ] );
if ( attacker )
{
@UTIL_DeathMsg( attacker, id, 0, "infection" );
@UTIL_ScoreAttrib( id, 0 );
rg_set_user_team( id, TEAM_TERRORIST );
ExecuteHamB( Ham_AddPoints, id, 0, true );
ExecuteHamB( Ham_AddPoints, attacker, 1, true );
set_member( id, m_iDeaths, get_member( id, m_iDeaths ) + 1 );
}
else
{
@UTIL_DeathMsg( id, id, 0, "infection" );
@UTIL_ScoreAttrib( id, 0 );
rg_set_user_team( id, TEAM_TERRORIST );
}
if ( get_member_game( m_bGameStarted ) && !get_member_game( m_bFreezePeriod ) )
RequestFrame( "@RequestFrame_CheckChangeClassWinConditions" );
}
@HuamnAttributes( id, attacker )
{
rg_set_user_team( id, TEAM_CT );
BIT_SUB( m_bitZombie, BIT_PLAYER( id ) );
set_entvar( id, var_health, 100.0 );
set_entvar( id, var_gravity, 1.0 );
rg_reset_user_model( id );
set_entvar( id, var_viewmodel, "models/v_knife.mdl" );
set_entvar( id, var_weaponmodel, "models/p_knife.mdl" );
rg_remove_all_items( id );
rg_give_item( id, "weapon_knife" );
rg_give_item( id, "weapon_g3sg1" );
rg_set_user_bpammo( id, WEAPON_G3SG1, 200 );
if ( get_member_game( m_bGameStarted ) && !get_member_game( m_bFreezePeriod ) )
RequestFrame( "@RequestFrame_CheckChangeClassWinConditions" );
}
@RequestFrame_CheckChangeClassWinConditions( )
{
if ( get_member_game( m_iRoundWinStatus ) != WINSTATUS_NONE )
return;
new alive_t, dead_t,
alive_ct, dead_ct;
rg_initialize_player_counts( alive_t, alive_ct, dead_t, dead_ct );
if ( alive_t + alive_ct + dead_t + dead_ct >= 2 )
{
if ( !alive_t )
rg_round_end( 3.0, WINSTATUS_CTS, ROUND_CTS_WIN, .trigger = true );
else if ( !alive_ct )
rg_round_end( 3.0, WINSTATUS_TERRORISTS, ROUND_TERRORISTS_WIN, .trigger = true );
}
}
@Select_SpawnPoint( id )
{
new spot, lastSpot = m_iLastSpawn, numPoints = ArraySize( m_arrSpawnPoints ), Float: vecOrigin[ 3 ];
do
{
if ( ++lastSpot >= numPoints )
lastSpot = 0;
spot = ArrayGetCell( m_arrSpawnPoints, lastSpot );
if ( is_nullent( spot ) )
continue;
get_entvar( spot, var_origin, vecOrigin );
if ( !IsHullVacant( id, vecOrigin, HULL_HUMAN ) )
continue;
break;
}
while ( lastSpot != m_iLastSpawn );
if ( is_nullent( spot ) )
return 0;
m_iLastSpawn = lastSpot;
return spot;
}
@Forcing_LevelInitialize( )
{
if ( !ArraySize( m_arrSpawnPoints ) )
{
new entity = NULLENT;
while ( ( entity = rg_find_ent_by_class( entity, "info_player_start", true ) ) )
ArrayPushCell( m_arrSpawnPoints, entity );
while ( ( entity = rg_find_ent_by_class( entity, "info_player_deathmatch", true ) ) )
ArrayPushCell( m_arrSpawnPoints, entity );
}
new numPoints = ArraySize( m_arrSpawnPoints );
set_member_game( m_iSpawnPointCount_Terrorist, numPoints );
set_member_game( m_iSpawnPointCount_CT, numPoints );
set_member_game( m_bLevelInitialized, true );
}
bool: IsHullVacant( id, Float: vecOrigin[ 3 ], hull )
{
engfunc( EngFunc_TraceHull, vecOrigin, vecOrigin, 0, hull, id, 0 );
if ( get_tr2( 0, TR_StartSolid ) || get_tr2( 0, TR_AllSolid ) || !get_tr2( 0, TR_InOpen ) )
return false;
return true;
}
@UTIL_DeathMsg( killer, victim, headshot, const weapon[ ] )
{
message_begin( MSG_ALL, get_user_msgid( "DeathMsg" ) );
write_byte( killer );
write_byte( victim );
write_byte( headshot );
write_string( weapon );
message_end( );
}
@UTIL_ScoreAttrib( id, flags )
{
message_begin( MSG_ALL, get_user_msgid( "ScoreAttrib" ) );
write_byte( id );
write_byte( flags );
message_end( );
}
static stock bool: Read_JsonField( const fileName[ ] )
{
new cfgsDir[ PLATFORM_MAX_PATH ];
get_localinfo( "amxx_configsdir", cfgsDir, charsmax( cfgsDir ) );
add( cfgsDir, charsmax( cfgsDir ), "/biohazard" );
if ( !dir_exists( cfgsDir ) )
{
set_fail_state( "Directory '%s' not found.", cfgsDir );
return false;
}
strcat( cfgsDir, fmt( "/%s.json", fileName ), charsmax( cfgsDir ) );
if ( !file_exists( cfgsDir ) )
{
set_fail_state( "File '%s' not found.", cfgsDir );
return false;
}
new JSON: jsonParse = json_parse( cfgsDir, true );
if ( jsonParse == Invalid_JSON )
{
set_fail_state( "Parsing file '%s' error." );
return false;
}
new JSON: jsonValue = json_object_get_value( jsonParse, "useless_entities" );
if ( json_is_array( jsonValue ) )
{
m_trUselessEntities = TrieCreate( );
new temp[ 32 ];
for ( new i = 0; i < json_array_get_count( jsonValue ); i++ )
{
json_array_get_string( jsonValue, i, temp, charsmax( temp ) );
TrieSetCell( m_trUselessEntities, temp, 1 );
}
json_free( jsonValue );
if ( TrieGetSize( m_trUselessEntities ) )
m_fwdSpawn = register_forward( FM_Spawn, "@FM_Spawn_Pre" );
else
{
TrieDestroy( m_trUselessEntities );
m_trUselessEntities = Invalid_Trie;
}
}
new JSON: jsonClasses = json_object_get_value( jsonParse, "classes" );
if ( json_is_array( jsonClasses ) )
{
new tempClass[ ClassData ], JSON: jsonItem;
for ( new i = 0; i < json_array_get_count( jsonClasses ); i++ )
{
jsonItem = json_array_get_value( jsonClasses, i );
json_object_get_string( jsonItem, "name", tempClass[ ClassName ], charsmax( tempClass[ ClassName ] ) );
tempClass[ ClassHealth ] = _: json_object_get_real( jsonItem, "health" );
tempClass[ ClassSpeed ] = _: json_object_get_real( jsonItem, "speed" );
tempClass[ ClassGravity ] = _: json_object_get_real( jsonItem, "gravity" );
json_object_get_string( jsonItem, "model", tempClass[ ClassModel ], charsmax( tempClass[ ClassModel ] ) );
precache_model( fmt( "models/player/%s/%s.mdl", tempClass[ ClassModel ], tempClass[ ClassModel ] ) );
json_object_get_string( jsonItem, "claw", tempClass[ ClassClaw ], charsmax( tempClass[ ClassClaw ] ) );
precache_model( tempClass[ ClassClaw ] );
ArrayPushArray( m_arrClassesVec, tempClass );
json_free( jsonItem );
}
m_iNumClasses = ArraySize( m_arrClassesVec );
json_free( jsonClasses );
}
json_free( jsonParse );
return true;
}