|
|
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
|
// |
|
|
// Purpose: |
|
|
// |
|
|
//============================================================================= |
|
|
|
|
|
#include "cbase.h" |
|
|
#include "tf_shareddefs.h" |
|
|
#include "KeyValues.h" |
|
|
#include "takedamageinfo.h" |
|
|
#include "tf_gamerules.h" |
|
|
#include "filesystem.h" |
|
|
#include "tf_matchmaking_shared.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Teams. |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *g_aTeamNames[TF_TEAM_COUNT] = |
|
|
{ |
|
|
"Unassigned", |
|
|
"Spectator", |
|
|
"Red", |
|
|
"Blue" |
|
|
}; |
|
|
|
|
|
color32 g_aTeamColors[TF_TEAM_COUNT] = |
|
|
{ |
|
|
{ 0, 0, 0, 0 }, |
|
|
{ 0, 0, 0, 0 }, |
|
|
{ 255, 0, 0, 0 }, |
|
|
{ 0, 0, 255, 0 } |
|
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Classes. |
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
const char *g_aPlayerClassNames[TF_CLASS_MENU_BUTTONS] = |
|
|
{ |
|
|
"#TF_Class_Name_Undefined", |
|
|
"#TF_Class_Name_Scout", |
|
|
"#TF_Class_Name_Sniper", |
|
|
"#TF_Class_Name_Soldier", |
|
|
"#TF_Class_Name_Demoman", |
|
|
"#TF_Class_Name_Medic", |
|
|
"#TF_Class_Name_HWGuy", |
|
|
"#TF_Class_Name_Pyro", |
|
|
"#TF_Class_Name_Spy", |
|
|
"#TF_Class_Name_Engineer", |
|
|
"#TF_Class_Name_Civilian", |
|
|
"", |
|
|
"#TF_Random" |
|
|
}; |
|
|
|
|
|
const char *g_aPlayerClassNames_NonLocalized[TF_CLASS_MENU_BUTTONS] = |
|
|
{ |
|
|
"Undefined", |
|
|
"Scout", |
|
|
"Sniper", |
|
|
"Soldier", |
|
|
"Demoman", |
|
|
"Medic", |
|
|
"Heavy", |
|
|
"Pyro", |
|
|
"Spy", |
|
|
"Engineer", |
|
|
"Civilian", |
|
|
"", |
|
|
"Random" |
|
|
}; |
|
|
|
|
|
const char *g_aRawPlayerClassNamesShort[TF_CLASS_MENU_BUTTONS] = |
|
|
{ |
|
|
"undefined", |
|
|
"scout", |
|
|
"sniper", |
|
|
"soldier", |
|
|
"demo", // short |
|
|
"medic", |
|
|
"heavy",// short |
|
|
"pyro", |
|
|
"spy", |
|
|
"engineer", |
|
|
"civilian", |
|
|
"", |
|
|
"random" |
|
|
}; |
|
|
|
|
|
const char *g_aRawPlayerClassNames[TF_CLASS_MENU_BUTTONS] = |
|
|
{ |
|
|
"undefined", |
|
|
"scout", |
|
|
"sniper", |
|
|
"soldier", |
|
|
"demoman", |
|
|
"medic", |
|
|
"heavyweapons", |
|
|
"pyro", |
|
|
"spy", |
|
|
"engineer", |
|
|
"civilian", |
|
|
"", |
|
|
"random" |
|
|
}; |
|
|
|
|
|
const char g_szBotModels[][ MAX_PATH ] = |
|
|
{ |
|
|
"", //TF_CLASS_UNDEFINED |
|
|
|
|
|
"models/bots/scout/bot_scout.mdl", |
|
|
"models/bots/sniper/bot_sniper.mdl", |
|
|
"models/bots/soldier/bot_soldier.mdl", |
|
|
"models/bots/demo/bot_demo.mdl", |
|
|
"models/bots/medic/bot_medic.mdl", |
|
|
"models/bots/heavy/bot_heavy.mdl", |
|
|
"models/bots/pyro/bot_pyro.mdl", |
|
|
"models/bots/spy/bot_spy.mdl", |
|
|
"models/bots/engineer/bot_engineer.mdl", |
|
|
}; |
|
|
|
|
|
const char g_szPlayerRobotModels[][MAX_PATH] = |
|
|
{ |
|
|
"", //TF_CLASS_UNDEFINED |
|
|
|
|
|
"models/bots/scout/bot_scout_human_anim.mdl", |
|
|
"models/bots/sniper/bot_sniper_human_anim.mdl", |
|
|
"models/bots/soldier/bot_soldier_human_anim.mdl", |
|
|
"models/bots/demo/bot_demo_human_anim.mdl", |
|
|
"models/bots/medic/bot_medic_human_anims.mdl", |
|
|
"models/bots/heavy/bot_heavy_human_anims.mdl", |
|
|
"models/bots/pyro/bot_pyro_human_anim.mdl", |
|
|
"models/bots/spy/bot_spy_human_anims.mdl", |
|
|
"models/bots/engineer/bot_engineer_human_anim.mdl", |
|
|
}; |
|
|
|
|
|
const char g_szBotBossModels[][ MAX_PATH ] = |
|
|
{ |
|
|
"", //TF_CLASS_UNDEFINED |
|
|
|
|
|
"models/bots/scout_boss/bot_scout_boss.mdl", |
|
|
"models/bots/sniper/bot_sniper.mdl", |
|
|
"models/bots/soldier_boss/bot_soldier_boss.mdl", |
|
|
"models/bots/demo_boss/bot_demo_boss.mdl", |
|
|
"models/bots/medic/bot_medic.mdl", |
|
|
"models/bots/heavy_boss/bot_heavy_boss.mdl", |
|
|
"models/bots/pyro_boss/bot_pyro_boss.mdl", |
|
|
"models/bots/spy/bot_spy.mdl", |
|
|
"models/bots/engineer/bot_engineer.mdl", |
|
|
}; |
|
|
|
|
|
const char g_szBotBossSentryBusterModel[ MAX_PATH ] = "models/bots/demo/bot_sentry_buster.mdl"; |
|
|
|
|
|
// Rome 2 promo models |
|
|
const char g_szRomePromoItems_Hat[][ MAX_PATH ] = |
|
|
{ |
|
|
"", //TF_CLASS_UNDEFINED |
|
|
|
|
|
"tw_scoutbot_hat", |
|
|
"tw_sniperbot_helmet", |
|
|
"tw_soldierbot_helmet", |
|
|
"tw_demobot_helmet", |
|
|
"tw_medibot_hat", |
|
|
"tw_heavybot_helmet", |
|
|
"tw_pyrobot_helmet", |
|
|
"tw_spybot_hood", |
|
|
"tw_engineerbot_helmet", |
|
|
}; |
|
|
|
|
|
const char g_szRomePromoItems_Misc[][ MAX_PATH ] = |
|
|
{ |
|
|
"", //TF_CLASS_UNDEFINED |
|
|
|
|
|
"tw_scoutbot_armor", |
|
|
"tw_sniperbot_armor", |
|
|
"tw_soldierbot_armor", |
|
|
"tw_demobot_armor", |
|
|
"tw_medibot_chariot", |
|
|
"tw_heavybot_armor", |
|
|
"tw_pyrobot_armor", |
|
|
"tw_spybot_armor", |
|
|
"tw_engineerbot_armor", |
|
|
}; |
|
|
|
|
|
const char *g_pszBreadModels[] = |
|
|
{ |
|
|
"models/weapons/c_models/c_bread/c_bread_baguette.mdl", // Spy |
|
|
"models/weapons/c_models/c_bread/c_bread_burnt.mdl", // Pyro |
|
|
"models/weapons/c_models/c_bread/c_bread_cinnamon.mdl", // Demo? |
|
|
"models/weapons/c_models/c_bread/c_bread_cornbread.mdl", // Engineer |
|
|
"models/weapons/c_models/c_bread/c_bread_crumpet.mdl", // Sniper? |
|
|
"models/weapons/c_models/c_bread/c_bread_plainloaf.mdl", // Scout |
|
|
"models/weapons/c_models/c_bread/c_bread_pretzel.mdl", // Medic |
|
|
"models/weapons/c_models/c_bread/c_bread_ration.mdl", // Soldier |
|
|
"models/weapons/c_models/c_bread/c_bread_russianblack.mdl", // Heavy? |
|
|
}; |
|
|
|
|
|
int GetClassIndexFromString( const char *pClassName, int nLastClassIndex/*=TF_LAST_NORMAL_CLASS*/ ) |
|
|
{ |
|
|
for ( int i = TF_FIRST_NORMAL_CLASS; i <= nLastClassIndex; ++i ) |
|
|
{ |
|
|
// compare first N characters to allow matching both "heavy" and "heavyweapons" |
|
|
int classnameLength = V_strlen( g_aPlayerClassNames_NonLocalized[i] ); |
|
|
|
|
|
if ( V_strlen( pClassName ) < classnameLength ) |
|
|
continue; |
|
|
|
|
|
if ( !V_strnicmp( g_aPlayerClassNames_NonLocalized[i], pClassName, classnameLength ) ) |
|
|
{ |
|
|
return i; |
|
|
} |
|
|
} |
|
|
|
|
|
return TF_CLASS_UNDEFINED; |
|
|
} |
|
|
|
|
|
int iRemapIndexToClass[TF_CLASS_MENU_BUTTONS] = |
|
|
{ |
|
|
0, |
|
|
TF_CLASS_SCOUT, |
|
|
TF_CLASS_SOLDIER, |
|
|
TF_CLASS_PYRO, |
|
|
TF_CLASS_DEMOMAN, |
|
|
TF_CLASS_HEAVYWEAPONS, |
|
|
TF_CLASS_ENGINEER, |
|
|
TF_CLASS_MEDIC, |
|
|
TF_CLASS_SNIPER, |
|
|
TF_CLASS_SPY, |
|
|
0, |
|
|
0, |
|
|
TF_CLASS_RANDOM |
|
|
}; |
|
|
|
|
|
int GetRemappedMenuIndexForClass( int iClass ) |
|
|
{ |
|
|
int iIndex = 0; |
|
|
|
|
|
for ( int i = 0 ; i < TF_CLASS_MENU_BUTTONS ; i++ ) |
|
|
{ |
|
|
if ( iRemapIndexToClass[i] == iClass ) |
|
|
{ |
|
|
iIndex = i; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
return iIndex; |
|
|
} |
|
|
|
|
|
ETFCond condition_to_attribute_translation[] = |
|
|
{ |
|
|
TF_COND_BURNING, // 1 (1<<0) |
|
|
TF_COND_AIMING, // 2 (1<<1) |
|
|
TF_COND_ZOOMED, // 4 (1<<2) |
|
|
TF_COND_DISGUISING, // 8 (...) |
|
|
TF_COND_DISGUISED, // 16 |
|
|
TF_COND_STEALTHED, // 32 |
|
|
TF_COND_INVULNERABLE, // 64 |
|
|
TF_COND_TELEPORTED, // 128 |
|
|
TF_COND_TAUNTING, // 256 |
|
|
TF_COND_INVULNERABLE_WEARINGOFF, // 512 |
|
|
TF_COND_STEALTHED_BLINK, // 1024 |
|
|
TF_COND_SELECTED_TO_TELEPORT, // 2048 |
|
|
TF_COND_CRITBOOSTED, // 4096 |
|
|
TF_COND_TMPDAMAGEBONUS, // 8192 |
|
|
TF_COND_FEIGN_DEATH, // 16384 |
|
|
TF_COND_PHASE, // 32768 |
|
|
TF_COND_STUNNED, // 65536 |
|
|
TF_COND_HEALTH_BUFF, // 131072 |
|
|
TF_COND_HEALTH_OVERHEALED, // 262144 |
|
|
TF_COND_URINE, // 524288 |
|
|
TF_COND_ENERGY_BUFF, // 1048576 |
|
|
|
|
|
TF_COND_LAST // sentinel value checked against when iterating |
|
|
}; |
|
|
|
|
|
ETFCond g_aDebuffConditions[] = |
|
|
{ |
|
|
TF_COND_BURNING, |
|
|
TF_COND_URINE, |
|
|
TF_COND_BLEEDING, |
|
|
TF_COND_MAD_MILK, |
|
|
TF_COND_LAST |
|
|
}; |
|
|
|
|
|
bool ConditionExpiresFast( ETFCond eCond ) |
|
|
{ |
|
|
return eCond == TF_COND_BURNING |
|
|
|| eCond == TF_COND_URINE |
|
|
|| eCond == TF_COND_BLEEDING |
|
|
|| eCond == TF_COND_MAD_MILK; |
|
|
} |
|
|
|
|
|
static const char *g_aConditionNames[] = |
|
|
{ |
|
|
"TF_COND_AIMING", // Sniper aiming, Heavy minigun. |
|
|
"TF_COND_ZOOMED", |
|
|
"TF_COND_DISGUISING", |
|
|
"TF_COND_DISGUISED", |
|
|
"TF_COND_STEALTHED", // Spy specific |
|
|
"TF_COND_INVULNERABLE", |
|
|
"TF_COND_TELEPORTED", |
|
|
"TF_COND_TAUNTING", |
|
|
"TF_COND_INVULNERABLE_WEARINGOFF", |
|
|
"TF_COND_STEALTHED_BLINK", |
|
|
"TF_COND_SELECTED_TO_TELEPORT", |
|
|
"TF_COND_CRITBOOSTED", // DO NOT RE-USE THIS -- THIS IS FOR KRITZKRIEG AND REVENGE CRITS ONLY |
|
|
"TF_COND_TMPDAMAGEBONUS", |
|
|
"TF_COND_FEIGN_DEATH", |
|
|
"TF_COND_PHASE", |
|
|
"TF_COND_STUNNED", // Any type of stun. Check iStunFlags for more info. |
|
|
"TF_COND_OFFENSEBUFF", |
|
|
"TF_COND_SHIELD_CHARGE", |
|
|
"TF_COND_DEMO_BUFF", |
|
|
"TF_COND_ENERGY_BUFF", |
|
|
"TF_COND_RADIUSHEAL", |
|
|
"TF_COND_HEALTH_BUFF", |
|
|
"TF_COND_BURNING", |
|
|
"TF_COND_HEALTH_OVERHEALED", |
|
|
"TF_COND_URINE", |
|
|
"TF_COND_BLEEDING", |
|
|
"TF_COND_DEFENSEBUFF", // 35% defense! No crit damage. |
|
|
"TF_COND_MAD_MILK", |
|
|
"TF_COND_MEGAHEAL", |
|
|
"TF_COND_REGENONDAMAGEBUFF", |
|
|
"TF_COND_MARKEDFORDEATH", |
|
|
"TF_COND_NOHEALINGDAMAGEBUFF", |
|
|
"TF_COND_SPEED_BOOST", // = 32 |
|
|
"TF_COND_CRITBOOSTED_PUMPKIN", // Brandon hates bits |
|
|
"TF_COND_CRITBOOSTED_USER_BUFF", |
|
|
"TF_COND_CRITBOOSTED_DEMO_CHARGE", |
|
|
"TF_COND_SODAPOPPER_HYPE", |
|
|
"TF_COND_CRITBOOSTED_FIRST_BLOOD", // arena mode first blood |
|
|
"TF_COND_CRITBOOSTED_BONUS_TIME", |
|
|
"TF_COND_CRITBOOSTED_CTF_CAPTURE", |
|
|
"TF_COND_CRITBOOSTED_ON_KILL", // =40. KGB, etc. |
|
|
"TF_COND_CANNOT_SWITCH_FROM_MELEE", |
|
|
"TF_COND_DEFENSEBUFF_NO_CRIT_BLOCK", // 35% defense! Still damaged by crits. |
|
|
"TF_COND_REPROGRAMMED", // Bots only |
|
|
"TF_COND_CRITBOOSTED_RAGE_BUFF", |
|
|
"TF_COND_DEFENSEBUFF_HIGH", // 75% defense! Still damaged by crits. |
|
|
"TF_COND_SNIPERCHARGE_RAGE_BUFF", // Sniper Rage - Charge time speed up |
|
|
"TF_COND_DISGUISE_WEARINGOFF", // Applied for half-second post-disguise |
|
|
"TF_COND_MARKEDFORDEATH_SILENT", // Sans sound |
|
|
"TF_COND_DISGUISED_AS_DISPENSER", |
|
|
"TF_COND_SAPPED", // =50. Bots only |
|
|
"TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED", |
|
|
"TF_COND_INVULNERABLE_USER_BUFF", |
|
|
"TF_COND_HALLOWEEN_BOMB_HEAD", |
|
|
"TF_COND_HALLOWEEN_THRILLER", |
|
|
"TF_COND_RADIUSHEAL_ON_DAMAGE", |
|
|
"TF_COND_CRITBOOSTED_CARD_EFFECT", |
|
|
"TF_COND_INVULNERABLE_CARD_EFFECT", |
|
|
"TF_COND_MEDIGUN_UBER_BULLET_RESIST", |
|
|
"TF_COND_MEDIGUN_UBER_BLAST_RESIST", |
|
|
"TF_COND_MEDIGUN_UBER_FIRE_RESIST", // =60 |
|
|
"TF_COND_MEDIGUN_SMALL_BULLET_RESIST", |
|
|
"TF_COND_MEDIGUN_SMALL_BLAST_RESIST", |
|
|
"TF_COND_MEDIGUN_SMALL_FIRE_RESIST", |
|
|
"TF_COND_STEALTHED_USER_BUFF", // Any class can have this |
|
|
"TF_COND_MEDIGUN_DEBUFF", |
|
|
"TF_COND_STEALTHED_USER_BUFF_FADING", |
|
|
"TF_COND_BULLET_IMMUNE", |
|
|
"TF_COND_BLAST_IMMUNE", |
|
|
"TF_COND_FIRE_IMMUNE", |
|
|
"TF_COND_PREVENT_DEATH", // =70 |
|
|
"TF_COND_MVM_BOT_STUN_RADIOWAVE", // Bots only |
|
|
"TF_COND_HALLOWEEN_SPEED_BOOST", |
|
|
"TF_COND_HALLOWEEN_QUICK_HEAL", |
|
|
"TF_COND_HALLOWEEN_GIANT", |
|
|
"TF_COND_HALLOWEEN_TINY", |
|
|
"TF_COND_HALLOWEEN_IN_HELL", |
|
|
"TF_COND_HALLOWEEN_GHOST_MODE", // =77 |
|
|
"TF_COND_MINICRITBOOSTED_ON_KILL", |
|
|
"TF_COND_OBSCURED_SMOKE", |
|
|
"TF_COND_PARACHUTE_DEPLOYED", // =80 |
|
|
"TF_COND_BLASTJUMPING", |
|
|
"TF_COND_HALLOWEEN_KART", |
|
|
"TF_COND_HALLOWEEN_KART_DASH", |
|
|
"TF_COND_BALLOON_HEAD", // =84 larger head, lower-gravity-feeling jumps |
|
|
"TF_COND_MELEE_ONLY", // =85 melee only |
|
|
"TF_COND_SWIMMING_CURSE", // player movement become swimming movement |
|
|
"TF_COND_FREEZE_INPUT", // freezes player input |
|
|
"TF_COND_HALLOWEEN_KART_CAGE", // attach cage model to player while in kart |
|
|
"TF_COND_DONOTUSE_0", |
|
|
"TF_COND_RUNE_STRENGTH", |
|
|
"TF_COND_RUNE_HASTE", |
|
|
"TF_COND_RUNE_REGEN", |
|
|
"TF_COND_RUNE_RESIST", |
|
|
"TF_COND_RUNE_VAMPIRE", |
|
|
"TF_COND_RUNE_REFLECT", |
|
|
"TF_COND_RUNE_PRECISION", |
|
|
"TF_COND_RUNE_AGILITY", |
|
|
"TF_COND_GRAPPLINGHOOK", |
|
|
"TF_COND_GRAPPLINGHOOK_SAFEFALL", |
|
|
"TF_COND_GRAPPLINGHOOK_LATCHED", |
|
|
"TF_COND_GRAPPLINGHOOK_BLEEDING", |
|
|
"TF_COND_AFTERBURN_IMMUNE", |
|
|
"TF_COND_RUNE_KNOCKOUT", |
|
|
"TF_COND_RUNE_IMBALANCE", |
|
|
"TF_COND_CRITBOOSTED_RUNE_TEMP", |
|
|
"TF_COND_PASSTIME_INTERCEPTION", |
|
|
"TF_COND_SWIMMING_NO_EFFECTS", // =107_DNOC_FT |
|
|
"TF_COND_PURGATORY", |
|
|
"TF_COND_RUNE_KING", |
|
|
"TF_COND_RUNE_PLAGUE", |
|
|
"TF_COND_RUNE_SUPERNOVA", |
|
|
"TF_COND_PLAGUE", |
|
|
"TF_COND_KING_BUFFED", |
|
|
"TF_COND_TEAM_GLOWS", // used to show team glows to living players |
|
|
"TF_COND_KNOCKED_INTO_AIR", |
|
|
"TF_COND_COMPETITIVE_WINNER", |
|
|
"TF_COND_COMPETITIVE_LOSER", |
|
|
"TF_COND_HEALING_DEBUFF", |
|
|
"TF_COND_PASSTIME_PENALTY_DEBUFF", |
|
|
"TF_COND_GRAPPLED_TO_PLAYER", |
|
|
"TF_COND_GRAPPLED_BY_PLAYER", |
|
|
|
|
|
// |
|
|
// ADD NEW ITEMS HERE TO AVOID BREAKING DEMOS |
|
|
// |
|
|
|
|
|
// ******** Keep this block last! ******** |
|
|
// Keep experimental conditions below and graduate out of it before shipping |
|
|
#ifdef STAGING_ONLY |
|
|
"TF_COND_NO_COMBAT_SPEED_BOOST", // STAGING_ENGY |
|
|
"TF_COND_TRANQ_SPY_BOOST", // STAGING_SPY |
|
|
"TF_COND_TRANQ_MARKED", |
|
|
// "TF_COND_SPACE_GRAVITY", |
|
|
// "TF_COND_SELF_CONC", |
|
|
"TF_COND_ROCKETPACK", |
|
|
"TF_COND_STEALTHED_PHASE", |
|
|
"TF_COND_CLIP_OVERLOAD", |
|
|
"TF_COND_SPY_CLASS_STEAL", |
|
|
#endif // STAGING_ONLY |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_aConditionNames ) == TF_COND_LAST ); |
|
|
|
|
|
const char *GetTFConditionName( ETFCond eCond ) |
|
|
{ |
|
|
if ( ( eCond >= ARRAYSIZE( g_aConditionNames ) ) || ( eCond < 0 ) ) |
|
|
return NULL; |
|
|
|
|
|
return g_aConditionNames[eCond]; |
|
|
} |
|
|
|
|
|
|
|
|
ETFCond GetTFConditionFromName( const char *pszCondName ) |
|
|
{ |
|
|
for( uint i=0; i<TF_COND_LAST; i++ ) |
|
|
{ |
|
|
ETFCond eCond = (ETFCond)i; |
|
|
if ( !V_stricmp( GetTFConditionName( eCond ), pszCondName ) ) |
|
|
return eCond; |
|
|
} |
|
|
|
|
|
Assert( !!"Invalid Condition Name" ); |
|
|
return TF_COND_INVALID; |
|
|
} |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Gametypes. |
|
|
//----------------------------------------------------------------------------- |
|
|
static const char *s_aGameTypeNames[] = |
|
|
{ |
|
|
"Undefined", |
|
|
"#Gametype_CTF", |
|
|
"#Gametype_CP", |
|
|
"#Gametype_Escort", |
|
|
"#Gametype_Arena", |
|
|
"#Gametype_MVM", |
|
|
"#Gametype_RobotDestruction", |
|
|
"#GameType_Passtime", |
|
|
"#GameType_PlayerDestruction", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( TF_GAMETYPE_COUNT == ARRAYSIZE( s_aGameTypeNames ) ); |
|
|
|
|
|
const char *GetGameTypeName( ETFGameType gameType ) |
|
|
{ |
|
|
return s_aGameTypeNames[ gameType ]; |
|
|
} |
|
|
|
|
|
static const char *s_aEnumGameTypeName[] = |
|
|
{ |
|
|
"TF_GAMETYPE_UNDEFINED", |
|
|
"TF_GAMETYPE_CTF", |
|
|
"TF_GAMETYPE_CP", |
|
|
"TF_GAMETYPE_ESCORT", |
|
|
"TF_GAMETYPE_ARENA", |
|
|
"TF_GAMETYPE_MVM", |
|
|
"TF_GAMETYPE_RD", |
|
|
"TF_GAMETYPE_PASSTIME", |
|
|
"TF_GAMETYPE_PD" |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( TF_GAMETYPE_COUNT == ARRAYSIZE( s_aEnumGameTypeName ) ); |
|
|
|
|
|
const char *GetEnumGameTypeName( ETFGameType gameType ) |
|
|
{ |
|
|
return s_aEnumGameTypeName[ gameType ]; |
|
|
} |
|
|
|
|
|
ETFGameType GetGameTypeFromName( const char *pszGameType ) |
|
|
{ |
|
|
for ( int i=0; i<TF_GAMETYPE_COUNT; ++i ) |
|
|
{ |
|
|
if ( FStrEq( pszGameType, s_aEnumGameTypeName[i] ) ) |
|
|
return ETFGameType(i); |
|
|
} |
|
|
|
|
|
return TF_GAMETYPE_UNDEFINED; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Ammo. |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *g_aAmmoNames[] = |
|
|
{ |
|
|
"DUMMY AMMO", |
|
|
"TF_AMMO_PRIMARY", |
|
|
"TF_AMMO_SECONDARY", |
|
|
"TF_AMMO_METAL", |
|
|
"TF_AMMO_GRENADES1", |
|
|
"TF_AMMO_GRENADES2", |
|
|
"TF_AMMO_GRENADES3" |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_aAmmoNames ) == TF_AMMO_COUNT ); |
|
|
|
|
|
const char *GetAmmoName( int iAmmoType ) |
|
|
{ |
|
|
ETFAmmoType eAmmoType = (ETFAmmoType)iAmmoType; |
|
|
return g_aAmmoNames[ eAmmoType ]; |
|
|
} |
|
|
|
|
|
const char *g_aCTFEventNames[] = |
|
|
{ |
|
|
"", |
|
|
"TF_FLAGEVENT_PICKUP", |
|
|
"TF_FLAGEVENT_CAPTURE", |
|
|
"TF_FLAGEVENT_DEFEND", |
|
|
"TF_FLAGEVENT_DROPPED", |
|
|
"TF_FLAGEVENT_RETURNED", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_aCTFEventNames ) == TF_NUM_FLAG_EVENTS ); |
|
|
|
|
|
const char *GetCTFEventName( ETFFlagEventTypes iEventType ) |
|
|
{ |
|
|
return g_aCTFEventNames[ iEventType ]; |
|
|
} |
|
|
|
|
|
ETFFlagEventTypes GetCTFEventTypeFromName( const char *pszName ) |
|
|
{ |
|
|
for( int i=TF_FLAGEVENT_PICKUP; i < TF_NUM_FLAG_EVENTS; ++i ) |
|
|
{ |
|
|
if ( FStrEq( pszName, GetCTFEventName( (ETFFlagEventTypes)i ) ) ) |
|
|
{ |
|
|
return (ETFFlagEventTypes)i; |
|
|
} |
|
|
} |
|
|
|
|
|
Assert( false ); |
|
|
return TF_NUM_FLAG_EVENTS; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char *GetRDScoreMethodName( RDScoreMethod_t iScoreMethod ) |
|
|
{ |
|
|
static const char *aRDScoreMethodNames[] = |
|
|
{ |
|
|
"SCORE_UNDEFINED", // -1 |
|
|
"SCORE_REACTOR_CAPTURED", // 0 |
|
|
"SCORE_CORES_COLLECTED", |
|
|
"SCORE_REACTOR_RETURNED", |
|
|
"SCORE_REACTOR_STEAL", |
|
|
|
|
|
"NUM_SCORE_TYPES" |
|
|
}; |
|
|
|
|
|
return aRDScoreMethodNames[ iScoreMethod + 1 ]; |
|
|
} |
|
|
|
|
|
RDScoreMethod_t GetRDScoreMethodFromName( const char *pszName ) |
|
|
{ |
|
|
for( int i=SCORE_UNDEFINED; i < NUM_SCORE_TYPES; ++i ) |
|
|
{ |
|
|
if ( FStrEq( pszName, GetRDScoreMethodName( (RDScoreMethod_t)i ) ) ) |
|
|
{ |
|
|
return (RDScoreMethod_t)i; |
|
|
} |
|
|
} |
|
|
|
|
|
Assert( false ); |
|
|
return SCORE_UNDEFINED; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Weapons. |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *g_aWeaponNames[] = |
|
|
{ |
|
|
"TF_WEAPON_NONE", |
|
|
"TF_WEAPON_BAT", |
|
|
"TF_WEAPON_BAT_WOOD", |
|
|
"TF_WEAPON_BOTTLE", |
|
|
"TF_WEAPON_FIREAXE", |
|
|
"TF_WEAPON_CLUB", |
|
|
"TF_WEAPON_CROWBAR", |
|
|
"TF_WEAPON_KNIFE", |
|
|
"TF_WEAPON_FISTS", |
|
|
"TF_WEAPON_SHOVEL", |
|
|
"TF_WEAPON_WRENCH", |
|
|
"TF_WEAPON_BONESAW", |
|
|
"TF_WEAPON_SHOTGUN_PRIMARY", |
|
|
"TF_WEAPON_SHOTGUN_SOLDIER", |
|
|
"TF_WEAPON_SHOTGUN_HWG", |
|
|
"TF_WEAPON_SHOTGUN_PYRO", |
|
|
"TF_WEAPON_SCATTERGUN", |
|
|
"TF_WEAPON_SNIPERRIFLE", |
|
|
"TF_WEAPON_MINIGUN", |
|
|
"TF_WEAPON_SMG", |
|
|
"TF_WEAPON_SYRINGEGUN_MEDIC", |
|
|
"TF_WEAPON_TRANQ", |
|
|
"TF_WEAPON_ROCKETLAUNCHER", |
|
|
"TF_WEAPON_GRENADELAUNCHER", |
|
|
"TF_WEAPON_PIPEBOMBLAUNCHER", |
|
|
"TF_WEAPON_FLAMETHROWER", |
|
|
"TF_WEAPON_GRENADE_NORMAL", |
|
|
"TF_WEAPON_GRENADE_CONCUSSION", |
|
|
"TF_WEAPON_GRENADE_NAIL", |
|
|
"TF_WEAPON_GRENADE_MIRV", |
|
|
"TF_WEAPON_GRENADE_MIRV_DEMOMAN", |
|
|
"TF_WEAPON_GRENADE_NAPALM", |
|
|
"TF_WEAPON_GRENADE_GAS", |
|
|
"TF_WEAPON_GRENADE_EMP", |
|
|
"TF_WEAPON_GRENADE_CALTROP", |
|
|
"TF_WEAPON_GRENADE_PIPEBOMB", |
|
|
"TF_WEAPON_GRENADE_SMOKE_BOMB", |
|
|
"TF_WEAPON_GRENADE_HEAL", |
|
|
"TF_WEAPON_GRENADE_STUNBALL", |
|
|
"TF_WEAPON_GRENADE_JAR", |
|
|
"TF_WEAPON_GRENADE_JAR_MILK", |
|
|
"TF_WEAPON_PISTOL", |
|
|
"TF_WEAPON_PISTOL_SCOUT", |
|
|
"TF_WEAPON_REVOLVER", |
|
|
"TF_WEAPON_NAILGUN", |
|
|
"TF_WEAPON_PDA", |
|
|
"TF_WEAPON_PDA_ENGINEER_BUILD", |
|
|
"TF_WEAPON_PDA_ENGINEER_DESTROY", |
|
|
"TF_WEAPON_PDA_SPY", |
|
|
"TF_WEAPON_BUILDER", |
|
|
"TF_WEAPON_MEDIGUN", |
|
|
"TF_WEAPON_GRENADE_MIRVBOMB", |
|
|
"TF_WEAPON_FLAMETHROWER_ROCKET", |
|
|
"TF_WEAPON_GRENADE_DEMOMAN", |
|
|
"TF_WEAPON_SENTRY_BULLET", |
|
|
"TF_WEAPON_SENTRY_ROCKET", |
|
|
"TF_WEAPON_DISPENSER", |
|
|
"TF_WEAPON_INVIS", |
|
|
"TF_WEAPON_FLAREGUN", |
|
|
"TF_WEAPON_LUNCHBOX", |
|
|
"TF_WEAPON_JAR", |
|
|
"TF_WEAPON_COMPOUND_BOW", |
|
|
"TF_WEAPON_BUFF_ITEM", |
|
|
"TF_WEAPON_PUMPKIN_BOMB", |
|
|
"TF_WEAPON_SWORD", |
|
|
"TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT", |
|
|
"TF_WEAPON_LIFELINE", |
|
|
"TF_WEAPON_LASER_POINTER", |
|
|
"TF_WEAPON_DISPENSER_GUN", |
|
|
"TF_WEAPON_SENTRY_REVENGE", |
|
|
"TF_WEAPON_JAR_MILK", |
|
|
"TF_WEAPON_HANDGUN_SCOUT_PRIMARY", |
|
|
"TF_WEAPON_BAT_FISH", |
|
|
"TF_WEAPON_CROSSBOW", |
|
|
"TF_WEAPON_STICKBOMB", |
|
|
"TF_WEAPON_HANDGUN_SCOUT_SECONDARY", |
|
|
"TF_WEAPON_SODA_POPPER", |
|
|
"TF_WEAPON_SNIPERRIFLE_DECAP", |
|
|
"TF_WEAPON_RAYGUN", |
|
|
"TF_WEAPON_PARTICLE_CANNON", |
|
|
"TF_WEAPON_MECHANICAL_ARM", |
|
|
"TF_WEAPON_DRG_POMSON", |
|
|
"TF_WEAPON_BAT_GIFTWRAP", |
|
|
"TF_WEAPON_GRENADE_ORNAMENT_BALL", |
|
|
"TF_WEAPON_FLAREGUN_REVENGE", |
|
|
"TF_WEAPON_PEP_BRAWLER_BLASTER", |
|
|
"TF_WEAPON_CLEAVER", |
|
|
"TF_WEAPON_GRENADE_CLEAVER", |
|
|
"TF_WEAPON_STICKY_BALL_LAUNCHER", |
|
|
"TF_WEAPON_GRENADE_STICKY_BALL", |
|
|
"TF_WEAPON_SHOTGUN_BUILDING_RESCUE", |
|
|
"TF_WEAPON_CANNON", |
|
|
"TF_WEAPON_THROWABLE", |
|
|
"TF_WEAPON_GRENADE_THROWABLE", |
|
|
"TF_WEAPON_PDA_SPY_BUILD", |
|
|
"TF_WEAPON_GRENADE_WATERBALLOON", |
|
|
"TF_WEAPON_HARVESTER_SAW", |
|
|
"TF_WEAPON_SPELLBOOK", |
|
|
"TF_WEAPON_SPELLBOOK_PROJECTILE", |
|
|
"TF_WEAPON_SNIPERRIFLE_CLASSIC", |
|
|
"TF_WEAPON_PARACHUTE", |
|
|
"TF_WEAPON_GRAPPLINGHOOK", |
|
|
"TF_WEAPON_PASSTIME_GUN", |
|
|
#ifdef STAGING_ONLY |
|
|
"TF_WEAPON_SNIPERRIFLE_REVOLVER", |
|
|
#endif |
|
|
"TF_WEAPON_CHARGED_SMG", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_aWeaponNames ) == TF_WEAPON_COUNT ); |
|
|
|
|
|
int g_aWeaponDamageTypes[] = |
|
|
{ |
|
|
DMG_GENERIC, // TF_WEAPON_NONE |
|
|
DMG_CLUB, // TF_WEAPON_BAT, |
|
|
DMG_CLUB, // TF_WEAPON_BAT_WOOD, |
|
|
DMG_CLUB, // TF_WEAPON_BOTTLE, |
|
|
DMG_CLUB, // TF_WEAPON_FIREAXE, |
|
|
DMG_CLUB, // TF_WEAPON_CLUB, |
|
|
DMG_CLUB, // TF_WEAPON_CROWBAR, |
|
|
DMG_SLASH, // TF_WEAPON_KNIFE, |
|
|
DMG_CLUB, // TF_WEAPON_FISTS, |
|
|
DMG_CLUB, // TF_WEAPON_SHOVEL, |
|
|
DMG_CLUB, // TF_WEAPON_WRENCH, |
|
|
DMG_SLASH, // TF_WEAPON_BONESAW, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_PRIMARY, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_SOLDIER, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_HWG, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_PYRO, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SCATTERGUN, |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_MINIGUN, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_SMG, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_SYRINGEGUN_MEDIC, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE | DMG_PARALYZE, // TF_WEAPON_TRANQ, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_ROCKETLAUNCHER, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_GRENADELAUNCHER, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_PIPEBOMBLAUNCHER, |
|
|
DMG_IGNITE | DMG_PREVENT_PHYSICS_FORCE | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_FLAMETHROWER, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_NORMAL, |
|
|
DMG_SONIC | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_CONCUSSION, |
|
|
DMG_BULLET | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_NAIL, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_MIRV, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_MIRV_DEMOMAN, |
|
|
DMG_BURN | DMG_RADIUS_MAX, // TF_WEAPON_GRENADE_NAPALM, |
|
|
DMG_POISON | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_GAS, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_GRENADE_EMP, |
|
|
DMG_GENERIC, // TF_WEAPON_GRENADE_CALTROP, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_GRENADE_PIPEBOMB, |
|
|
DMG_GENERIC, // TF_WEAPON_GRENADE_SMOKE_BOMB, |
|
|
DMG_GENERIC, // TF_WEAPON_GRENADE_HEAL |
|
|
DMG_CLUB, // TF_WEAPON_GRENADE_STUNBALL |
|
|
DMG_CLUB, // TF_WEAPON_GRENADE_JAR |
|
|
DMG_CLUB, // TF_WEAPON_GRENADE_JAR_MILK |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_PISTOL, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_PISTOL_SCOUT, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_REVOLVER, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_NAILGUN, |
|
|
DMG_BULLET, // TF_WEAPON_PDA, |
|
|
DMG_BULLET, // TF_WEAPON_PDA_ENGINEER_BUILD, |
|
|
DMG_BULLET, // TF_WEAPON_PDA_ENGINEER_DESTROY, |
|
|
DMG_BULLET, // TF_WEAPON_PDA_SPY, |
|
|
DMG_BULLET, // TF_WEAPON_BUILDER |
|
|
DMG_BULLET, // TF_WEAPON_MEDIGUN |
|
|
DMG_BLAST, // TF_WEAPON_GRENADE_MIRVBOMB |
|
|
DMG_BLAST | DMG_IGNITE | DMG_RADIUS_MAX, // TF_WEAPON_FLAMETHROWER_ROCKET |
|
|
DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_DEMOMAN |
|
|
DMG_BULLET, // TF_WEAPON_SENTRY_BULLET |
|
|
DMG_BLAST, // TF_WEAPON_SENTRY_ROCKET |
|
|
DMG_GENERIC, // TF_WEAPON_DISPENSER |
|
|
DMG_GENERIC, // TF_WEAPON_INVIS |
|
|
DMG_BULLET | DMG_IGNITE, // TF_WEAPON_FLAREGUN |
|
|
DMG_GENERIC, // TF_WEAPON_LUNCHBOX |
|
|
DMG_GENERIC, // TF_WEAPON_JAR |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_COMPOUND_BOW |
|
|
DMG_GENERIC, // TF_WEAPON_BUFF_ITEM |
|
|
DMG_CLUB, // TF_WEAPON_PUMPKIN_BOMB |
|
|
DMG_CLUB, // TF_WEAPON_SWORD |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT, |
|
|
DMG_CLUB, // TF_WEAPON_LIFELINE |
|
|
DMG_CLUB, // TF_WEAPON_LASER_POINTER |
|
|
DMG_BULLET, // TF_WEAPON_DISPENSER_GUN |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SENTRY_REVENGE |
|
|
DMG_GENERIC, // TF_WEAPON_JAR_MILK |
|
|
DMG_BUCKSHOT | DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_HANDGUN_SCOUT_PRIMARY |
|
|
DMG_CLUB, // TF_WEAPON_BAT_FISH |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, |
|
|
DMG_CLUB, // TF_WEAPON_STICKBOMB |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_HANDGUN_SCOUT_SECONDARY |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SODA_POPPER, |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_DECAP, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_RAYGUN, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_PARTICLE_CANNON, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_MECHANICAL_ARM, |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_DRG_POMSON, |
|
|
DMG_CLUB, // TF_WEAPON_BAT_GIFTWRAP, |
|
|
DMG_CLUB, // TF_WEAPON_GRENADE_ORNAMENT_BALL |
|
|
DMG_BULLET | DMG_IGNITE, // TF_WEAPON_FLAREGUN_REVENGE, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_PEP_BRAWLER_BLASTER, |
|
|
DMG_GENERIC, // TF_WEAPON_CLEAVER |
|
|
DMG_SLASH, // TF_WEAPON_GRENADE_CLEAVER |
|
|
DMG_GENERIC, // TF_WEAPON_STICKY_BALL_LAUNCHER, |
|
|
DMG_GENERIC, // TF_WEAPON_GRENADE_STICKY_BALL, |
|
|
DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_BUILDING_RESCUE, |
|
|
DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_CANNON |
|
|
DMG_BULLET, // TF_WEAPON_THROWABLE |
|
|
DMG_BULLET, // TF_WEAPON_GRENADE_THROWABLE |
|
|
DMG_BULLET, // TF_WEAPON_PDA_SPY_BUILD |
|
|
DMG_BULLET, // TF_WEAPON_GRENADE_WATERBALLOON |
|
|
DMG_SLASH, // TF_WEAPON_HARVESTER_SAW |
|
|
DMG_GENERIC, // TF_WEAPON_SPELLBOOK |
|
|
DMG_GENERIC, // TF_WEAPON_SPELLBOOK_PROJECTILE |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_CLASSIC, |
|
|
DMG_GENERIC, // TF_WEAPON_PARACHUTE, |
|
|
DMG_GENERIC, // TF_WEAPON_GRAPPLINGHOOK, |
|
|
DMG_GENERIC, // TF_WEAPON_PASSTIME_GUN |
|
|
#ifdef STAGING_ONLY |
|
|
DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_REVOLVER, |
|
|
#endif |
|
|
DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_CHARGED_SMG, |
|
|
}; |
|
|
|
|
|
const char *g_szSpecialDamageNames[] = |
|
|
{ |
|
|
"", |
|
|
"TF_DMG_CUSTOM_HEADSHOT", |
|
|
"TF_DMG_CUSTOM_BACKSTAB", |
|
|
"TF_DMG_CUSTOM_BURNING", |
|
|
"TF_DMG_WRENCH_FIX", |
|
|
"TF_DMG_CUSTOM_MINIGUN", |
|
|
"TF_DMG_CUSTOM_SUICIDE", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_HADOUKEN", |
|
|
"TF_DMG_CUSTOM_BURNING_FLARE", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_HIGH_NOON", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_GRAND_SLAM", |
|
|
"TF_DMG_CUSTOM_PENETRATE_MY_TEAM", |
|
|
"TF_DMG_CUSTOM_PENETRATE_ALL_PLAYERS", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_FENCING", |
|
|
"TF_DMG_CUSTOM_PENETRATE_NONBURNING_TEAMMATE", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_ARROW_STAB", |
|
|
"TF_DMG_CUSTOM_TELEFRAG", |
|
|
"TF_DMG_CUSTOM_BURNING_ARROW", |
|
|
"TF_DMG_CUSTOM_FLYINGBURN", |
|
|
"TF_DMG_CUSTOM_PUMPKIN_BOMB", |
|
|
"TF_DMG_CUSTOM_DECAPITATION", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_GRENADE", |
|
|
"TF_DMG_CUSTOM_BASEBALL", |
|
|
"TF_DMG_CUSTOM_CHARGE_IMPACT", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_BARBARIAN_SWING", |
|
|
"TF_DMG_CUSTOM_AIR_STICKY_BURST", |
|
|
"TF_DMG_CUSTOM_DEFENSIVE_STICKY", |
|
|
"TF_DMG_CUSTOM_PICKAXE", |
|
|
"TF_DMG_CUSTOM_ROCKET_DIRECTHIT", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_UBERSLICE", |
|
|
"TF_DMG_CUSTOM_PLAYER_SENTRY", |
|
|
"TF_DMG_CUSTOM_STANDARD_STICKY", |
|
|
"TF_DMG_CUSTOM_SHOTGUN_REVENGE_CRIT", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_ENGINEER_GUITAR_SMASH", |
|
|
"TF_DMG_CUSTOM_BLEEDING", |
|
|
"TF_DMG_CUSTOM_GOLD_WRENCH", |
|
|
"TF_DMG_CUSTOM_CARRIED_BUILDING", |
|
|
"TF_DMG_CUSTOM_COMBO_PUNCH", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_ENGINEER_ARM_KILL", |
|
|
"TF_DMG_CUSTOM_FISH_KILL", |
|
|
"TF_DMG_CUSTOM_TRIGGER_HURT", |
|
|
"TF_DMG_CUSTOM_DECAPITATION_BOSS", |
|
|
"TF_DMG_CUSTOM_STICKBOMB_EXPLOSION", |
|
|
"TF_DMG_CUSTOM_AEGIS_ROUND", |
|
|
"TF_DMG_CUSTOM_FLARE_EXPLOSION", |
|
|
"TF_DMG_CUSTOM_BOOTS_STOMP", |
|
|
"TF_DMG_CUSTOM_PLASMA", |
|
|
"TF_DMG_CUSTOM_PLASMA_CHARGED", |
|
|
"TF_DMG_CUSTOM_PLASMA_GIB", |
|
|
"TF_DMG_CUSTOM_PRACTICE_STICKY", |
|
|
"TF_DMG_CUSTOM_EYEBALL_ROCKET", |
|
|
"TF_DMG_CUSTOM_HEADSHOT_DECAPITATION", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_ARMAGEDDON", |
|
|
"TF_DMG_CUSTOM_FLARE_PELLET", |
|
|
"TF_DMG_CUSTOM_CLEAVER", |
|
|
"TF_DMG_CUSTOM_CLEAVER_CRIT", |
|
|
"TF_DMG_CUSTOM_SAPPER_RECORDER_DEATH", |
|
|
"TF_DMG_CUSTOM_MERASMUS_PLAYER_BOMB", |
|
|
"TF_DMG_CUSTOM_MERASMUS_GRENADE", |
|
|
"TF_DMG_CUSTOM_MERASMUS_ZAP", |
|
|
"TF_DMG_CUSTOM_MERASMUS_DECAPITATION", |
|
|
"TF_DMG_CUSTOM_CANNONBALL_PUSH", |
|
|
"TF_DMG_CUSTOM_TAUNTATK_ALLCLASS_GUITAR_RIFF", |
|
|
"TF_DMG_CUSTOM_THROWABLE", |
|
|
"TF_DMG_CUSTOM_THROWABLE_KILL", |
|
|
"TF_DMG_CUSTOM_SPELL_TELEPORT", |
|
|
"TF_DMG_CUSTOM_SPELL_SKELETON", |
|
|
"TF_DMG_CUSTOM_SPELL_MIRV", |
|
|
"TF_DMG_CUSTOM_SPELL_METEOR", |
|
|
"TF_DMG_CUSTOM_SPELL_LIGHTNING", |
|
|
"TF_DMG_CUSTOM_SPELL_FIREBALL", |
|
|
"TF_DMG_CUSTOM_SPELL_MONOCULUS", |
|
|
"TF_DMG_CUSTOM_SPELL_BLASTJUMP", |
|
|
"TF_DMG_CUSTOM_SPELL_BATS", |
|
|
"TF_DMG_CUSTOM_SPELL_TINY", |
|
|
"TF_DMG_CUSTOM_KART", |
|
|
"TF_DMG_CUSTOM_GIANT_HAMMER", |
|
|
"TF_DMG_CUSTOM_RUNE_REFLECT", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szSpecialDamageNames ) == TF_DMG_CUSTOM_END ); |
|
|
|
|
|
const char *GetCustomDamageName( ETFDmgCustom eDmgCustom ) |
|
|
{ |
|
|
if ( ( eDmgCustom >= ARRAYSIZE( g_szSpecialDamageNames ) ) || ( eDmgCustom < 0 ) ) |
|
|
return NULL; |
|
|
|
|
|
return g_szSpecialDamageNames[eDmgCustom]; |
|
|
} |
|
|
|
|
|
ETFDmgCustom GetCustomDamageFromName( const char *pszCustomDmgName ) |
|
|
{ |
|
|
for( uint i=0; i<TF_DMG_CUSTOM_END; i++ ) |
|
|
{ |
|
|
ETFDmgCustom eDmgCustom = (ETFDmgCustom)i; |
|
|
if ( !V_stricmp( GetCustomDamageName( eDmgCustom ), pszCustomDmgName ) ) |
|
|
return eDmgCustom; |
|
|
} |
|
|
|
|
|
Assert( !!"Invalid Custom Damage Name" ); |
|
|
return TF_DMG_CUSTOM_NONE; |
|
|
} |
|
|
|
|
|
const char *g_szProjectileNames[] = |
|
|
{ |
|
|
"", |
|
|
"projectile_bullet", |
|
|
"projectile_rocket", |
|
|
"projectile_pipe", |
|
|
"projectile_pipe_remote", |
|
|
"projectile_syringe", |
|
|
"projectile_flare", |
|
|
"projectile_jar", |
|
|
"projectile_arrow", |
|
|
"projectile_flame_rocket", |
|
|
"projectile_jar_milk", |
|
|
"projectile_healing_bolt", |
|
|
"projectile_energy_ball", |
|
|
"projectile_energy_ring", |
|
|
"projectile_pipe_remote_practice", |
|
|
"projectile_cleaver", |
|
|
"projectile_sticky_ball", |
|
|
"projectile_cannonball", |
|
|
"projectile_building_repair_bolt", |
|
|
"projectile_festive_arrow", |
|
|
"projectile_throwable", |
|
|
"projectile_spellfireball", |
|
|
"projectile_festive_urine", |
|
|
"projectile_festive_healing_bolt", |
|
|
"projectfile_breadmonster_jarate", |
|
|
"projectfile_breadmonster_madmilk", |
|
|
|
|
|
"projectile_grapplinghook", |
|
|
"projectile_sentry_rocket", |
|
|
"projectile_bread_monster", |
|
|
|
|
|
#ifdef STAGING_ONLY |
|
|
// Staging |
|
|
"projectile_tranq", |
|
|
"projectile_sniperbullet", |
|
|
"projectile_throwing_knife", |
|
|
"projectile_grenade_concussion", |
|
|
"projectile_grenade_teleport", |
|
|
"projectile_jarate_bolt", |
|
|
#endif |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szProjectileNames ) == TF_NUM_PROJECTILES ); |
|
|
|
|
|
// these map to the projectiles named in g_szProjectileNames |
|
|
int g_iProjectileWeapons[] = |
|
|
{ |
|
|
TF_WEAPON_NONE, |
|
|
TF_WEAPON_PISTOL, |
|
|
TF_WEAPON_ROCKETLAUNCHER, |
|
|
TF_WEAPON_PIPEBOMBLAUNCHER, |
|
|
TF_WEAPON_GRENADELAUNCHER, |
|
|
TF_WEAPON_SYRINGEGUN_MEDIC, |
|
|
TF_WEAPON_FLAREGUN, |
|
|
TF_WEAPON_JAR, |
|
|
TF_WEAPON_COMPOUND_BOW, |
|
|
TF_PROJECTILE_FLAME_ROCKET, |
|
|
TF_WEAPON_JAR_MILK, |
|
|
TF_WEAPON_CROSSBOW, |
|
|
TF_WEAPON_PARTICLE_CANNON, |
|
|
TF_WEAPON_RAYGUN, |
|
|
TF_WEAPON_GRENADELAUNCHER, // practice pipes should never kill anyone anyway |
|
|
TF_WEAPON_CLEAVER, |
|
|
TF_WEAPON_STICKY_BALL_LAUNCHER, |
|
|
TF_WEAPON_CANNON, |
|
|
TF_WEAPON_SHOTGUN_BUILDING_RESCUE, |
|
|
TF_WEAPON_COMPOUND_BOW, |
|
|
TF_WEAPON_THROWABLE, |
|
|
TF_WEAPON_SPELLBOOK, |
|
|
TF_WEAPON_JAR, |
|
|
TF_WEAPON_CROSSBOW, |
|
|
TF_WEAPON_JAR, |
|
|
TF_WEAPON_JAR, |
|
|
|
|
|
TF_PROJECTILE_GRAPPLINGHOOK, |
|
|
TF_WEAPON_SENTRY_ROCKET, |
|
|
TF_WEAPON_THROWABLE, |
|
|
|
|
|
#ifdef STAGING_ONLY |
|
|
// Staging |
|
|
TF_WEAPON_REVOLVER, |
|
|
TF_WEAPON_SNIPERRIFLE, |
|
|
TF_WEAPON_THROWABLE, |
|
|
TF_WEAPON_THROWABLE, |
|
|
TF_WEAPON_THROWABLE, |
|
|
TF_WEAPON_CROSSBOW, |
|
|
#endif |
|
|
}; |
|
|
|
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szProjectileNames ) == ARRAYSIZE( g_iProjectileWeapons ) ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Taunt attacks |
|
|
//----------------------------------------------------------------------------- |
|
|
static const char* taunt_attack_name[] = |
|
|
{ |
|
|
"TAUNTATK_NONE", |
|
|
"TAUNTATK_PYRO_HADOUKEN", |
|
|
"TAUNTATK_HEAVY_EAT", |
|
|
"TAUNTATK_HEAVY_RADIAL_BUFF", |
|
|
"TAUNTATK_HEAVY_HIGH_NOON", |
|
|
"TAUNTATK_SCOUT_DRINK", |
|
|
"TAUNTATK_SCOUT_GRAND_SLAM", |
|
|
"TAUNTATK_MEDIC_INHALE", |
|
|
"TAUNTATK_SPY_FENCING_SLASH_A", |
|
|
"TAUNTATK_SPY_FENCING_SLASH_B", |
|
|
"TAUNTATK_SPY_FENCING_STAB", |
|
|
"TAUNTATK_RPS_KILL", |
|
|
"TAUNTATK_SNIPER_ARROW_STAB_IMPALE", |
|
|
"TAUNTATK_SNIPER_ARROW_STAB_KILL", |
|
|
"TAUNTATK_SOLDIER_GRENADE_KILL", |
|
|
"TAUNTATK_DEMOMAN_BARBARIAN_SWING", |
|
|
"TAUNTATK_MEDIC_UBERSLICE_IMPALE", |
|
|
"TAUNTATK_MEDIC_UBERSLICE_KILL", |
|
|
"TAUNTATK_FLIP_LAND_PARTICLE", |
|
|
"TAUNTATK_RPS_PARTICLE", |
|
|
"TAUNTATK_HIGHFIVE_PARTICLE", |
|
|
"TAUNTATK_ENGINEER_GUITAR_SMASH", |
|
|
"TAUNTATK_ENGINEER_ARM_IMPALE", |
|
|
"TAUNTATK_ENGINEER_ARM_KILL", |
|
|
"TAUNTATK_ENGINEER_ARM_BLEND", |
|
|
"TAUNTATK_SOLDIER_GRENADE_KILL_WORMSIGN", |
|
|
"TAUNTATK_SHOW_ITEM", |
|
|
"TAUNTATK_MEDIC_RELEASE_DOVES", |
|
|
"TAUNTATK_PYRO_ARMAGEDDON", |
|
|
"TAUNTATK_PYRO_SCORCHSHOT", |
|
|
"TAUNTATK_ALLCLASS_GUITAR_RIFF", |
|
|
"TAUNTATK_MEDIC_HEROIC_TAUNT", |
|
|
|
|
|
// |
|
|
// INSERT NEW ITEMS HERE TO AVOID BREAKING DEMOS |
|
|
// |
|
|
}; |
|
|
|
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( taunt_attack_name ) == TAUNTATK_COUNT ); |
|
|
|
|
|
taunt_attack_t GetTauntAttackByName( const char* pszTauntAttackName ) |
|
|
{ |
|
|
if ( pszTauntAttackName ) |
|
|
{ |
|
|
for ( int i=0; i<ARRAYSIZE( taunt_attack_name ); ++i ) |
|
|
{ |
|
|
if ( !V_stricmp( pszTauntAttackName, taunt_attack_name[i] ) ) |
|
|
{ |
|
|
return (taunt_attack_t)i; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return TAUNTATK_NONE; |
|
|
} |
|
|
|
|
|
const char *g_pszHintMessages[] = |
|
|
{ |
|
|
"#Hint_spotted_a_friend", |
|
|
"#Hint_spotted_an_enemy", |
|
|
"#Hint_killing_enemies_is_good", |
|
|
"#Hint_out_of_ammo", |
|
|
"#Hint_turn_off_hints", |
|
|
"#Hint_pickup_ammo", |
|
|
"#Hint_Cannot_Teleport_With_Flag", |
|
|
"#Hint_Cannot_Cloak_With_Flag", |
|
|
"#Hint_Cannot_Disguise_With_Flag", |
|
|
"#Hint_Cannot_Attack_While_Feign_Armed", |
|
|
"#Hint_ClassMenu", |
|
|
|
|
|
// Grenades |
|
|
"#Hint_gren_caltrops", |
|
|
"#Hint_gren_concussion", |
|
|
"#Hint_gren_emp", |
|
|
"#Hint_gren_gas", |
|
|
"#Hint_gren_mirv", |
|
|
"#Hint_gren_nail", |
|
|
"#Hint_gren_napalm", |
|
|
"#Hint_gren_normal", |
|
|
|
|
|
// Altfires |
|
|
"#Hint_altfire_sniperrifle", |
|
|
"#Hint_altfire_flamethrower", |
|
|
"#Hint_altfire_grenadelauncher", |
|
|
"#Hint_altfire_pipebomblauncher", |
|
|
"#Hint_altfire_rotate_building", |
|
|
|
|
|
// Soldier |
|
|
"#Hint_Soldier_rpg_reload", |
|
|
|
|
|
// Engineer |
|
|
"#Hint_Engineer_use_wrench_onown", |
|
|
"#Hint_Engineer_use_wrench_onother", |
|
|
"#Hint_Engineer_use_wrench_onfriend", |
|
|
"#Hint_Engineer_build_sentrygun", |
|
|
"#Hint_Engineer_build_dispenser", |
|
|
"#Hint_Engineer_build_teleporters", |
|
|
"#Hint_Engineer_pickup_metal", |
|
|
"#Hint_Engineer_repair_object", |
|
|
"#Hint_Engineer_metal_to_upgrade", |
|
|
"#Hint_Engineer_upgrade_sentrygun", |
|
|
|
|
|
"#Hint_object_has_sapper", |
|
|
|
|
|
"#Hint_object_your_object_sapped", |
|
|
"#Hint_enemy_using_dispenser", |
|
|
"#Hint_enemy_using_tp_entrance", |
|
|
"#Hint_enemy_using_tp_exit", |
|
|
|
|
|
"#Hint_Cannot_Phase_With_Flag", |
|
|
|
|
|
"#Hint_Cannot_Attack_While_Cloaked", |
|
|
|
|
|
"#Hint_Cannot_Arm_Feign_Now", |
|
|
}; |
|
|
|
|
|
const char *g_pszArrowModels[] = |
|
|
{ |
|
|
"models/weapons/w_models/w_arrow.mdl", |
|
|
"models/weapons/w_models/w_repair_claw.mdl", |
|
|
"models/weapons/w_models/w_baseball.mdl", |
|
|
"models/weapons/w_models/w_arrow_xmas.mdl", |
|
|
"models/weapons/w_models/w_syringe_proj.mdl", |
|
|
#ifdef STAGING_ONLY |
|
|
"models/workshop/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow_xmas_proj.mdl", |
|
|
#else |
|
|
"models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow_xmas_proj.mdl", |
|
|
#endif |
|
|
"models/weapons/w_models/w_breadmonster/w_breadmonster.mdl", |
|
|
"models/weapons/c_models/c_grapple_proj/c_grapple_proj.mdl", |
|
|
|
|
|
#ifdef STAGING_ONLY |
|
|
"models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl" |
|
|
#else |
|
|
"models/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl" |
|
|
#endif |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszArrowModels ) == TF_ARROW_MODEL_COUNT ); |
|
|
|
|
|
const char *g_pszCampaignMedalIcons[] = |
|
|
{ |
|
|
"", |
|
|
// Gun Mettle Campaign |
|
|
"../hud/coin_summer2015_gravel", |
|
|
"../hud/coin_summer2015_bronze", |
|
|
"../hud/coin_summer2015_silver", |
|
|
"../hud/coin_summer2015_gold", |
|
|
|
|
|
// Invasion Community Update |
|
|
"../HUD/scoreboard_invasion", |
|
|
|
|
|
// Halloween |
|
|
"../HUD/coin_halloween2015_gravel", |
|
|
"../HUD/coin_halloween2015_bronze", |
|
|
"../HUD/coin_halloween2015_silver", |
|
|
"../HUD/coin_halloween2015_gold", |
|
|
|
|
|
// Tough Break Campaign |
|
|
"../HUD/stamp_winter2016_gravel1", |
|
|
"../HUD/stamp_winter2016_bronze1", |
|
|
"../HUD/stamp_winter2016_silver1", |
|
|
"../HUD/stamp_winter2016_gold1", |
|
|
|
|
|
"../HUD/stamp_winter2016_gravel2", |
|
|
"../HUD/stamp_winter2016_bronze2", |
|
|
"../HUD/stamp_winter2016_silver2", |
|
|
"../HUD/stamp_winter2016_gold2", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszCampaignMedalIcons ) == CAMPAIGN_MEDAL_DISPLAY_TYPE_COUNT ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Dead Calling Cards |
|
|
const char *g_pszDeathCallingCardModels[] = |
|
|
{ |
|
|
"", // Empty at zero |
|
|
"models/props_gameplay/tombstone_specialdelivery.mdl", // Scout PolyCount Set |
|
|
"models/props_gameplay/tombstone_crocostyle.mdl", // Sniper PolyCount Set |
|
|
"models/props_gameplay/tombstone_tankbuster.mdl", // Solider PolyCount Set |
|
|
"models/props_gameplay/tombstone_gasjockey.mdl", // Pyro PolyCount Set |
|
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
int GetWeaponId( const char *pszWeaponName ) |
|
|
{ |
|
|
// if this doesn't match, you need to add missing weapons to the array |
|
|
COMPILE_TIME_ASSERT( TF_WEAPON_COUNT == ARRAYSIZE( g_aWeaponNames ) ); |
|
|
|
|
|
for ( int iWeapon = 0; iWeapon < ARRAYSIZE( g_aWeaponNames ); ++iWeapon ) |
|
|
{ |
|
|
if ( !Q_stricmp( pszWeaponName, g_aWeaponNames[iWeapon] ) ) |
|
|
return iWeapon; |
|
|
} |
|
|
|
|
|
return TF_WEAPON_NONE; |
|
|
} |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *WeaponIdToAlias( int iWeapon ) |
|
|
{ |
|
|
// if this doesn't match, you need to add missing weapons to the array |
|
|
COMPILE_TIME_ASSERT( TF_WEAPON_COUNT == ARRAYSIZE( g_aWeaponNames ) ); |
|
|
|
|
|
if ( ( iWeapon >= ARRAYSIZE( g_aWeaponNames ) ) || ( iWeapon < 0 ) ) |
|
|
return NULL; |
|
|
|
|
|
return g_aWeaponNames[iWeapon]; |
|
|
} |
|
|
|
|
|
#ifdef GAME_DLL |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
int GetWeaponFromDamage( const CTakeDamageInfo &info ) |
|
|
{ |
|
|
int iWeapon = TF_WEAPON_NONE; |
|
|
|
|
|
const char *killer_weapon_name = ""; |
|
|
|
|
|
// Find the killer & the scorer |
|
|
CBaseEntity *pInflictor = info.GetInflictor(); |
|
|
CBaseEntity *pKiller = info.GetAttacker(); |
|
|
CBasePlayer *pScorer = TFGameRules()->GetDeathScorer( pKiller, pInflictor, NULL ); |
|
|
|
|
|
// find the weapon the killer used |
|
|
|
|
|
if ( pScorer ) // Is the killer a client? |
|
|
{ |
|
|
if ( pInflictor ) |
|
|
{ |
|
|
if ( pInflictor == pScorer ) |
|
|
{ |
|
|
// If the inflictor is the killer, then it must be their current weapon doing the damage |
|
|
if ( pScorer->GetActiveWeapon() ) |
|
|
{ |
|
|
killer_weapon_name = pScorer->GetActiveWeapon()->GetClassname(); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
killer_weapon_name = STRING( pInflictor->m_iClassname ); // it's just that easy |
|
|
} |
|
|
} |
|
|
} |
|
|
else if ( pInflictor ) |
|
|
{ |
|
|
killer_weapon_name = STRING( pInflictor->m_iClassname ); |
|
|
} |
|
|
|
|
|
if ( !Q_strnicmp( killer_weapon_name, "tf_projectile", 13 ) ) |
|
|
{ |
|
|
for( int i = 0; i < ARRAYSIZE( g_szProjectileNames ); i++ ) |
|
|
{ |
|
|
if ( !Q_stricmp( &killer_weapon_name[ 3 ], g_szProjectileNames[ i ] ) ) |
|
|
{ |
|
|
iWeapon = g_iProjectileWeapons[ i ]; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
int iLen = Q_strlen( killer_weapon_name ); |
|
|
|
|
|
// strip off _projectile from projectiles shot from other projectiles |
|
|
if ( ( iLen < 256 ) && ( iLen > 11 ) && !Q_stricmp( &killer_weapon_name[ iLen - 11 ], "_projectile" ) ) |
|
|
{ |
|
|
char temp[ 256 ]; |
|
|
V_strcpy_safe( temp, killer_weapon_name ); |
|
|
temp[ iLen - 11 ] = 0; |
|
|
|
|
|
// set the weapon used |
|
|
iWeapon = GetWeaponId( temp ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
// set the weapon used |
|
|
iWeapon = GetWeaponId( killer_weapon_name ); |
|
|
} |
|
|
} |
|
|
|
|
|
AssertMsg( iWeapon >= 0 && iWeapon < TF_WEAPON_COUNT, "Referencing a weapon not in tf_shareddefs.h. Check to make it's defined and it's mapped correctly in g_szProjectileNames and g_iProjectileWeapons." ); |
|
|
return iWeapon; |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
// ------------------------------------------------------------------------------------------------ // |
|
|
// CObjectInfo tables. |
|
|
// ------------------------------------------------------------------------------------------------ // |
|
|
|
|
|
CObjectInfo::CObjectInfo( const char *pObjectName ) |
|
|
{ |
|
|
m_pObjectName = pObjectName; |
|
|
m_pClassName = NULL; |
|
|
m_flBuildTime = -9999; |
|
|
m_nMaxObjects = -9999; |
|
|
m_Cost = -9999; |
|
|
m_CostMultiplierPerInstance = -999; |
|
|
m_flUpgradeDuration = -999; |
|
|
m_UpgradeCost = -9999; |
|
|
m_MaxUpgradeLevel = -9999; |
|
|
m_pBuilderWeaponName = NULL; |
|
|
m_pBuilderPlacementString = NULL; |
|
|
m_SelectionSlot = -9999; |
|
|
m_SelectionPosition = -9999; |
|
|
m_bSolidToPlayerMovement = false; |
|
|
m_pIconActive = NULL; |
|
|
m_pIconInactive = NULL; |
|
|
m_pIconMenu = NULL; |
|
|
m_pViewModel = NULL; |
|
|
m_pPlayerModel = NULL; |
|
|
m_iDisplayPriority = 0; |
|
|
m_bVisibleInWeaponSelection = true; |
|
|
m_pExplodeSound = NULL; |
|
|
m_pUpgradeSound = NULL; |
|
|
m_pExplosionParticleEffect = NULL; |
|
|
m_bAutoSwitchTo = false; |
|
|
m_iBuildCount = 0; |
|
|
m_iNumAltModes = 0; |
|
|
m_bRequiresOwnBuilder = false; |
|
|
} |
|
|
|
|
|
|
|
|
CObjectInfo::~CObjectInfo() |
|
|
{ |
|
|
delete [] m_pClassName; |
|
|
delete [] m_pStatusName; |
|
|
delete [] m_pBuilderWeaponName; |
|
|
delete [] m_pBuilderPlacementString; |
|
|
delete [] m_pIconActive; |
|
|
delete [] m_pIconInactive; |
|
|
delete [] m_pIconMenu; |
|
|
delete [] m_pViewModel; |
|
|
delete [] m_pPlayerModel; |
|
|
delete [] m_pExplodeSound; |
|
|
delete [] m_pUpgradeSound; |
|
|
delete [] m_pExplosionParticleEffect; |
|
|
} |
|
|
|
|
|
CObjectInfo g_ObjectInfos[OBJ_LAST] = |
|
|
{ |
|
|
CObjectInfo( "OBJ_DISPENSER" ), |
|
|
CObjectInfo( "OBJ_TELEPORTER" ), |
|
|
CObjectInfo( "OBJ_SENTRYGUN" ), |
|
|
CObjectInfo( "OBJ_ATTACHMENT_SAPPER" ), |
|
|
#ifdef STAGING_ONLY |
|
|
CObjectInfo( "OBJ_CATAPULT" ), |
|
|
CObjectInfo( "OBJ_SPY_TRAP" ), |
|
|
#endif |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_ObjectInfos ) == OBJ_LAST ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
int GetBuildableId( const char *pszBuildableName ) |
|
|
{ |
|
|
for ( int iBuildable = 0; iBuildable < OBJ_LAST; ++iBuildable ) |
|
|
{ |
|
|
if ( !Q_stricmp( pszBuildableName, g_ObjectInfos[iBuildable].m_pObjectName ) ) |
|
|
return iBuildable; |
|
|
} |
|
|
|
|
|
return OBJ_LAST; |
|
|
} |
|
|
|
|
|
bool AreObjectInfosLoaded() |
|
|
{ |
|
|
return g_ObjectInfos[0].m_pClassName != NULL; |
|
|
} |
|
|
|
|
|
static void SpewFileInfo( IBaseFileSystem *pFileSystem, const char *resourceName, const char *pathID, KeyValues *pValues ) |
|
|
{ |
|
|
bool bFileExists = pFileSystem->FileExists( resourceName, pathID ); |
|
|
bool bFileWritable = pFileSystem->IsFileWritable( resourceName, pathID ); |
|
|
unsigned int nSize = pFileSystem->Size( resourceName, pathID ); |
|
|
|
|
|
Msg( "resourceName:%s pathID:%s bFileExists:%d size:%u writeable:%d\n", resourceName, pathID, bFileExists, nSize, bFileWritable ); |
|
|
|
|
|
unsigned int filesize = ( unsigned int )-1; |
|
|
FileHandle_t f = filesystem->Open( resourceName, "rb", pathID ); |
|
|
if ( f ) |
|
|
{ |
|
|
filesize = filesystem->Size( f ); |
|
|
filesystem->Close( f ); |
|
|
} |
|
|
|
|
|
Msg( " FileHandle_t:%p size:%u\n", f, filesize ); |
|
|
|
|
|
IFileSystem *pFS = (IFileSystem *)filesystem; |
|
|
|
|
|
char cwd[ MAX_PATH ]; |
|
|
cwd[ 0 ] = 0; |
|
|
pFS->GetCurrentDirectory( cwd, ARRAYSIZE( cwd ) ); |
|
|
|
|
|
bool bAvailable = pFS->IsFileImmediatelyAvailable( resourceName ); |
|
|
|
|
|
Msg( " IsFileImmediatelyAvailable:%d cwd:%s\n", bAvailable, cwd ); |
|
|
|
|
|
pFS->PrintSearchPaths(); |
|
|
|
|
|
if ( pValues ) |
|
|
{ |
|
|
Msg( "Keys:" ); |
|
|
KeyValuesDumpAsDevMsg( pValues, 2, 0 ); |
|
|
} |
|
|
} |
|
|
|
|
|
void LoadObjectInfos( IBaseFileSystem *pFileSystem ) |
|
|
{ |
|
|
const char *pFilename = "scripts/objects.txt"; |
|
|
|
|
|
// Make sure this stuff hasn't already been loaded. |
|
|
Assert( !AreObjectInfosLoaded() ); |
|
|
|
|
|
KeyValues *pValues = new KeyValues( "Object descriptions" ); |
|
|
if ( !pValues->LoadFromFile( pFileSystem, pFilename, "GAME" ) ) |
|
|
{ |
|
|
// Getting "Can't open scripts/objects.txt for object info." errors. Spew file information |
|
|
// before the Error() call which should show up in the minidumps. |
|
|
SpewFileInfo( pFileSystem, pFilename, "GAME", NULL ); |
|
|
|
|
|
Error( "Can't open %s for object info.", pFilename ); |
|
|
pValues->deleteThis(); |
|
|
return; |
|
|
} |
|
|
|
|
|
// Now read each class's information in. |
|
|
for ( int iObj=0; iObj < ARRAYSIZE( g_ObjectInfos ); iObj++ ) |
|
|
{ |
|
|
CObjectInfo *pInfo = &g_ObjectInfos[iObj]; |
|
|
KeyValues *pSub = pValues->FindKey( pInfo->m_pObjectName ); |
|
|
if ( !pSub ) |
|
|
{ |
|
|
// Getting "Missing section 'OBJ_DISPENSER' from scripts/objects.txt" errors. |
|
|
SpewFileInfo( pFileSystem, pFilename, "GAME", pValues ); |
|
|
|
|
|
// It seems that folks have corrupt files when these errors are seen in http://minidump. |
|
|
// Does it make sense to call the below Steam API so it'll force a validation next startup time? |
|
|
// Need to verify it's real corruption and not someone dorking around with their objects.txt file... |
|
|
// |
|
|
// From Martin Otten: If you have a file on disc and you<EFBFBD>re 100% sure it<EFBFBD>s |
|
|
// corrupt, call ISteamApps::MarkContentCorrupt( false ), before you shutdown |
|
|
// the game. This will cause a content validation in Steam. |
|
|
|
|
|
Error( "Missing section '%s' from %s.", pInfo->m_pObjectName, pFilename ); |
|
|
pValues->deleteThis(); |
|
|
return; |
|
|
} |
|
|
|
|
|
// Read all the info in. |
|
|
if ( (pInfo->m_flBuildTime = pSub->GetFloat( "BuildTime", -999 )) == -999 || |
|
|
(pInfo->m_nMaxObjects = pSub->GetInt( "MaxObjects", -999 )) == -999 || |
|
|
(pInfo->m_Cost = pSub->GetInt( "Cost", -999 )) == -999 || |
|
|
(pInfo->m_CostMultiplierPerInstance = pSub->GetFloat( "CostMultiplier", -999 )) == -999 || |
|
|
(pInfo->m_flUpgradeDuration = pSub->GetFloat( "UpgradeDuration", -999 )) == -999 || |
|
|
(pInfo->m_UpgradeCost = pSub->GetInt( "UpgradeCost", -999 )) == -999 || |
|
|
(pInfo->m_MaxUpgradeLevel = pSub->GetInt( "MaxUpgradeLevel", -999 )) == -999 || |
|
|
(pInfo->m_SelectionSlot = pSub->GetInt( "SelectionSlot", -999 )) == -999 || |
|
|
(pInfo->m_iBuildCount = pSub->GetInt( "BuildCount", -999 )) == -999 || |
|
|
(pInfo->m_SelectionPosition = pSub->GetInt( "SelectionPosition", -999 )) == -999 ) |
|
|
{ |
|
|
SpewFileInfo( pFileSystem, pFilename, "GAME", pValues ); |
|
|
|
|
|
Error( "Missing data for object '%s' in %s.", pInfo->m_pObjectName, pFilename ); |
|
|
pValues->deleteThis(); |
|
|
return; |
|
|
} |
|
|
|
|
|
pInfo->m_pClassName = ReadAndAllocStringValue( pSub, "ClassName", pFilename ); |
|
|
pInfo->m_pStatusName = ReadAndAllocStringValue( pSub, "StatusName", pFilename ); |
|
|
pInfo->m_pBuilderWeaponName = ReadAndAllocStringValue( pSub, "BuilderWeaponName", pFilename ); |
|
|
pInfo->m_pBuilderPlacementString = ReadAndAllocStringValue( pSub, "BuilderPlacementString", pFilename ); |
|
|
pInfo->m_bSolidToPlayerMovement = pSub->GetInt( "SolidToPlayerMovement", 0 ) ? true : false; |
|
|
pInfo->m_pIconActive = ReadAndAllocStringValue( pSub, "IconActive", pFilename ); |
|
|
pInfo->m_pIconInactive = ReadAndAllocStringValue( pSub, "IconInactive", pFilename ); |
|
|
pInfo->m_pIconMenu = ReadAndAllocStringValue( pSub, "IconMenu", pFilename ); |
|
|
pInfo->m_bUseItemInfo = ( pSub->GetInt( "UseItemInfo", 0 ) > 0 ); |
|
|
pInfo->m_pViewModel = ReadAndAllocStringValue( pSub, "Viewmodel", pFilename ); |
|
|
pInfo->m_pPlayerModel = ReadAndAllocStringValue( pSub, "Playermodel", pFilename ); |
|
|
pInfo->m_iDisplayPriority = pSub->GetInt( "DisplayPriority", 0 ); |
|
|
pInfo->m_pHudStatusIcon = ReadAndAllocStringValue( pSub, "HudStatusIcon", pFilename ); |
|
|
pInfo->m_bVisibleInWeaponSelection = ( pSub->GetInt( "VisibleInWeaponSelection", 1 ) > 0 ); |
|
|
pInfo->m_pExplodeSound = ReadAndAllocStringValue( pSub, "ExplodeSound", pFilename ); |
|
|
pInfo->m_pUpgradeSound = ReadAndAllocStringValue( pSub, "UpgradeSound", pFilename ); |
|
|
pInfo->m_pExplosionParticleEffect = ReadAndAllocStringValue( pSub, "ExplodeEffect", pFilename ); |
|
|
pInfo->m_bAutoSwitchTo = ( pSub->GetInt( "autoswitchto", 0 ) > 0 ); |
|
|
pInfo->m_iMetalToDropInGibs = pSub->GetInt( "MetalToDropInGibs", 0 ); |
|
|
pInfo->m_bRequiresOwnBuilder = pSub->GetBool( "RequiresOwnBuilder", 0 ); |
|
|
|
|
|
// Read the other alternate object modes. |
|
|
KeyValues *pAltModesKey = pSub->FindKey( "AltModes" ); |
|
|
if ( pAltModesKey ) |
|
|
{ |
|
|
int iIndex = 0; |
|
|
while ( iIndex<OBJECT_MAX_MODES ) |
|
|
{ |
|
|
char buf[256]; |
|
|
Q_snprintf( buf, sizeof(buf), "AltMode%d", iIndex ); |
|
|
KeyValues *pCurrentModeKey = pAltModesKey->FindKey( buf ); |
|
|
if ( !pCurrentModeKey ) |
|
|
break; |
|
|
|
|
|
pInfo->m_AltModes[iIndex].pszStatusName = ReadAndAllocStringValue( pCurrentModeKey, "StatusName", pFilename ); |
|
|
pInfo->m_AltModes[iIndex].pszModeName = ReadAndAllocStringValue( pCurrentModeKey, "ModeName", pFilename ); |
|
|
pInfo->m_AltModes[iIndex].pszIconMenu = ReadAndAllocStringValue( pCurrentModeKey, "IconMenu", pFilename ); |
|
|
|
|
|
iIndex++; |
|
|
} |
|
|
pInfo->m_iNumAltModes = iIndex-1; |
|
|
} |
|
|
|
|
|
// Alternate mode 0 always matches the defaults. |
|
|
pInfo->m_AltModes[0].pszStatusName = pInfo->m_pStatusName; |
|
|
pInfo->m_AltModes[0].pszIconMenu = pInfo->m_pIconMenu; |
|
|
} |
|
|
|
|
|
pValues->deleteThis(); |
|
|
} |
|
|
|
|
|
|
|
|
const CObjectInfo* GetObjectInfo( int iObject ) |
|
|
{ |
|
|
Assert( iObject >= 0 && iObject < OBJ_LAST ); |
|
|
Assert( AreObjectInfosLoaded() ); |
|
|
return &g_ObjectInfos[iObject]; |
|
|
} |
|
|
|
|
|
ConVar tf_cheapobjects( "tf_cheapobjects","0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Set to 1 and all objects will cost 0" ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Return the cost of another object of the specified type |
|
|
// If bLast is set, return the cost of the last built object of the specified type |
|
|
// |
|
|
// Note: Used to contain logic from tf2 that multiple instances of the same object |
|
|
// cost different amounts. See tf2/game_shared/tf_shareddefs.cpp for details |
|
|
//----------------------------------------------------------------------------- |
|
|
int InternalCalculateObjectCost( int iObjectType ) |
|
|
{ |
|
|
if ( tf_cheapobjects.GetInt() ) |
|
|
{ |
|
|
return 0; |
|
|
} |
|
|
|
|
|
int iCost = GetObjectInfo( iObjectType )->m_Cost; |
|
|
|
|
|
return iCost; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Calculate the cost to upgrade an object of a specific type |
|
|
//----------------------------------------------------------------------------- |
|
|
int CalculateObjectUpgrade( int iObjectType, int iObjectLevel ) |
|
|
{ |
|
|
// Max level? |
|
|
if ( iObjectLevel >= GetObjectInfo( iObjectType )->m_MaxUpgradeLevel ) |
|
|
return 0; |
|
|
|
|
|
int iCost = GetObjectInfo( iObjectType )->m_UpgradeCost; |
|
|
for ( int i = 0; i < (iObjectLevel - 1); i++ ) |
|
|
{ |
|
|
iCost *= OBJECT_UPGRADE_COST_MULTIPLIER_PER_LEVEL; |
|
|
} |
|
|
|
|
|
return iCost; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Return true if the specified class is allowed to build the specified object type |
|
|
//----------------------------------------------------------------------------- |
|
|
bool ClassCanBuild( int iClass, int iObjectType ) |
|
|
{ |
|
|
/* |
|
|
for ( int i = 0; i < OBJ_LAST; i++ ) |
|
|
{ |
|
|
// Hit the end? |
|
|
if ( g_TFClassInfos[iClass].m_pClassObjects[i] == OBJ_LAST ) |
|
|
return false; |
|
|
|
|
|
// Found it? |
|
|
if ( g_TFClassInfos[iClass].m_pClassObjects[i] == iObjectType ) |
|
|
return true; |
|
|
} |
|
|
|
|
|
return false; |
|
|
*/ |
|
|
|
|
|
return ( iClass == TF_CLASS_ENGINEER ); |
|
|
} |
|
|
|
|
|
const unsigned char *GetTFEncryptionKey( void ) |
|
|
{ |
|
|
return (unsigned char *)"E2NcUkG2"; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Per-class weapon entity translations |
|
|
//----------------------------------------------------------------------------- |
|
|
struct wpntranslation_class_weapons_t |
|
|
{ |
|
|
const char *pszWpnString; |
|
|
const char *pszClassWpn[TF_LAST_NORMAL_CLASS]; |
|
|
}; |
|
|
|
|
|
wpntranslation_class_weapons_t pszWpnEntTranslationList[] = |
|
|
{ |
|
|
{ |
|
|
"tf_weapon_shotgun", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_shotgun_soldier",// TF_CLASS_SOLDIER, |
|
|
"", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"tf_weapon_shotgun_hwg", // TF_CLASS_HEAVYWEAPONS, |
|
|
"tf_weapon_shotgun_pyro", // TF_CLASS_PYRO, |
|
|
"", // TF_CLASS_SPY, |
|
|
"tf_weapon_shotgun_primary",// TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
|
|
|
{ |
|
|
"tf_weapon_pistol", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"tf_weapon_pistol_scout", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"", // TF_CLASS_SOLDIER, |
|
|
"", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"", // TF_CLASS_HEAVYWEAPONS, |
|
|
"", // TF_CLASS_PYRO, |
|
|
"", // TF_CLASS_SPY, |
|
|
"tf_weapon_pistol", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
|
|
|
{ |
|
|
"tf_weapon_shovel", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_shovel", // TF_CLASS_SOLDIER, |
|
|
"tf_weapon_bottle", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"", // TF_CLASS_HEAVYWEAPONS, |
|
|
"", // TF_CLASS_PYRO, |
|
|
"", // TF_CLASS_SPY, |
|
|
"", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
"tf_weapon_bottle", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_shovel", // TF_CLASS_SOLDIER, |
|
|
"tf_weapon_bottle", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"", // TF_CLASS_HEAVYWEAPONS, |
|
|
"", // TF_CLASS_PYRO, |
|
|
"", // TF_CLASS_SPY, |
|
|
"", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
"saxxy", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"tf_weapon_bat", // TF_CLASS_SCOUT, |
|
|
"tf_weapon_club", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_shovel", // TF_CLASS_SOLDIER, |
|
|
"tf_weapon_bottle", // TF_CLASS_DEMOMAN, |
|
|
"tf_weapon_bonesaw", // TF_CLASS_MEDIC, |
|
|
"tf_weapon_fireaxe", // TF_CLASS_HEAVYWEAPONS, HWG uses a fireaxe because he doesn't have a default melee weapon of his own; also I am a terrible person |
|
|
"tf_weapon_fireaxe", // TF_CLASS_PYRO, |
|
|
"tf_weapon_knife", // TF_CLASS_SPY, |
|
|
"tf_weapon_wrench", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
"tf_weapon_throwable", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_SCOUT, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_SOLDIER, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_DEMOMAN, |
|
|
"tf_weapon_throwable_primary", // TF_CLASS_MEDIC, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_HEAVYWEAPONS |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_PYRO, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_SPY, |
|
|
"tf_weapon_throwable_secondary", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
"tf_weapon_parachute", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"tf_weapon_parachute_secondary", // TF_CLASS_SOLDIER, |
|
|
"tf_weapon_parachute_primary", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"", // TF_CLASS_HEAVYWEAPONS |
|
|
"", // TF_CLASS_PYRO, |
|
|
"" // TF_CLASS_SPY, |
|
|
"", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
"tf_weapon_revolver", |
|
|
{ |
|
|
"", // TF_CLASS_UNDEFINED = 0, |
|
|
"", // TF_CLASS_SCOUT, |
|
|
"", // TF_CLASS_SNIPER, |
|
|
"", // TF_CLASS_SOLDIER, |
|
|
"", // TF_CLASS_DEMOMAN, |
|
|
"", // TF_CLASS_MEDIC, |
|
|
"", // TF_CLASS_HEAVYWEAPONS |
|
|
"", // TF_CLASS_PYRO, |
|
|
"tf_weapon_revolver", // TF_CLASS_SPY, |
|
|
"tf_weapon_revolver_secondary", // TF_CLASS_ENGINEER, |
|
|
} |
|
|
}, |
|
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: We need to support players putting any shotgun into a shotgun slot, pistol into a pistol slot, etc. |
|
|
// For legacy reasons, different classes actually spawn different entities for their shotguns/pistols/etc. |
|
|
// To deal with this, we translate entities into the right one for the class we're playing. |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *TranslateWeaponEntForClass( const char *pszName, int iClass ) |
|
|
{ |
|
|
if ( pszName ) |
|
|
{ |
|
|
for ( int i = 0; i < ARRAYSIZE(pszWpnEntTranslationList); i++ ) |
|
|
{ |
|
|
if ( !Q_stricmp( pszName, pszWpnEntTranslationList[i].pszWpnString ) ) |
|
|
{ |
|
|
const char *pTransName = pszWpnEntTranslationList[i].pszClassWpn[ iClass ]; |
|
|
Assert( pTransName && pTransName[0] ); |
|
|
return pTransName; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return pszName; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Helltower Announcer lines for Redmond and Blutarch |
|
|
//----------------------------------------------------------------------------- |
|
|
helltower_vo_t g_pszHelltowerAnnouncerLines[] = |
|
|
{ |
|
|
// EACH MISC PAIR SHOULD HAVE THE SAME NUMBER OF LINES |
|
|
{ "Announcer.Helltower_Red_Misc%02u", 16 }, |
|
|
{ "Announcer.Helltower_Blue_Misc%02u", 16 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Misc_Rare%02u", 21 }, |
|
|
{ "Announcer.Helltower_Blue_Misc_Rare%02u", 21 }, |
|
|
|
|
|
// THESE PAIRS CAN HAVE DIFFERENT COUNTS |
|
|
{ "Announcer.Helltower_Red_Winning%02u", 12 }, |
|
|
{ "Announcer.Helltower_Blue_Winning%02u", 13 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Winning_Rare%02u", 12 }, |
|
|
{ "Announcer.Helltower_Blue_Winning_Rare%02u", 8 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Losing%02u", 15 }, |
|
|
{ "Announcer.Helltower_Blue_Losing%02u", 16 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Losing_Rare%02u", 6 }, |
|
|
{ "Announcer.Helltower_Blue_Losing_Rare%02u", 5 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Win%02u", 7 }, |
|
|
{ "Announcer.Helltower_Blue_Win%02u", 7 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Win_Rare%02u", 1 }, |
|
|
{ "Announcer.Helltower_Blue_Win_Rare%02u", 3 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Lose%02u", 7 }, |
|
|
{ "Announcer.Helltower_Blue_Lose%02u", 7 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Lose_Rare%02u", 1 }, |
|
|
{ "Announcer.Helltower_Blue_Lose_Rare%02u", 1 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_RoundStart%02u", 4 }, |
|
|
{ "Announcer.Helltower_Blue_RoundStart%02u", 2 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_RoundStart_Rare%02u", 4 }, |
|
|
{ "Announcer.Helltower_Blue_RoundStart_Rare%02u", 2 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Skeleton_King%02u", 4 }, |
|
|
{ "Announcer.Helltower_Blue_Skeleton_King%02u", 4 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Almost_Win%02u", 1 }, |
|
|
{ "Announcer.Helltower_Blue_Almost_Win%02u", 1 }, |
|
|
|
|
|
{ "Announcer.Helltower_Red_Almost_Lose%02u", 1 }, |
|
|
{ "Announcer.Helltower_Blue_Almost_Lose%02u", 1 }, |
|
|
|
|
|
}; |
|
|
|
|
|
#ifdef TF_CLIENT_DLL |
|
|
//----------------------------------------------------------------------------- |
|
|
// |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *g_pszInvasionMaps[] = |
|
|
{ |
|
|
"maps/ctf_2fort_invasion.bsp", |
|
|
"maps/koth_probed.bsp", |
|
|
"maps/arena_byre.bsp", |
|
|
"maps/pd_watergate.bsp" |
|
|
}; |
|
|
|
|
|
bool IsPlayingInvasionMap( void ) |
|
|
{ |
|
|
const char *pszCurrentMap = engine->GetLevelName(); |
|
|
|
|
|
for ( int i = 0; i < ARRAYSIZE( g_pszInvasionMaps ); i++ ) |
|
|
{ |
|
|
if ( FStrEq( g_pszInvasionMaps[i], pszCurrentMap ) ) |
|
|
return true; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
const char *g_pszClassIcons[SCOREBOARD_CLASS_ICONS] = |
|
|
{ |
|
|
"", |
|
|
"../hud/leaderboard_class_scout", |
|
|
"../hud/leaderboard_class_sniper", |
|
|
"../hud/leaderboard_class_soldier", |
|
|
"../hud/leaderboard_class_demo", |
|
|
"../hud/leaderboard_class_medic", |
|
|
"../hud/leaderboard_class_heavy", |
|
|
"../hud/leaderboard_class_pyro", |
|
|
"../hud/leaderboard_class_spy", |
|
|
"../hud/leaderboard_class_engineer", |
|
|
"../hud/leaderboard_class_scout_d", |
|
|
"../hud/leaderboard_class_sniper_d", |
|
|
"../hud/leaderboard_class_soldier_d", |
|
|
"../hud/leaderboard_class_demo_d", |
|
|
"../hud/leaderboard_class_medic_d", |
|
|
"../hud/leaderboard_class_heavy_d", |
|
|
"../hud/leaderboard_class_pyro_d", |
|
|
"../hud/leaderboard_class_spy_d", |
|
|
"../hud/leaderboard_class_engineer_d", |
|
|
}; |
|
|
|
|
|
const char *g_pszClassIconsAlt[SCOREBOARD_CLASS_ICONS] = |
|
|
{ |
|
|
"", |
|
|
"class_icons/class_icon_orange_scout", |
|
|
"class_icons/class_icon_orange_sniper", |
|
|
"class_icons/class_icon_orange_soldier", |
|
|
"class_icons/class_icon_orange_demo", |
|
|
"class_icons/class_icon_orange_medic", |
|
|
"class_icons/class_icon_orange_heavy", |
|
|
"class_icons/class_icon_orange_pyro", |
|
|
"class_icons/class_icon_orange_spy", |
|
|
"class_icons/class_icon_orange_engineer", |
|
|
"class_icons/class_icon_orange_scout_d", |
|
|
"class_icons/class_icon_orange_sniper_d", |
|
|
"class_icons/class_icon_orange_soldier_d", |
|
|
"class_icons/class_icon_orange_demo_d", |
|
|
"class_icons/class_icon_orange_medic_d", |
|
|
"class_icons/class_icon_orange_heavy_d", |
|
|
"class_icons/class_icon_orange_pyro_d", |
|
|
"class_icons/class_icon_orange_spy_d", |
|
|
"class_icons/class_icon_orange_engineer_d", |
|
|
}; |
|
|
|
|
|
const char *g_pszItemClassImagesRed[] = |
|
|
{ |
|
|
"class_portraits/all_class", // TF_CLASS_UNDEFINED = 0, |
|
|
"class_portraits/scout", // TF_CLASS_SCOUT, |
|
|
"class_portraits/sniper", // TF_CLASS_SNIPER, |
|
|
"class_portraits/soldier", // TF_CLASS_SOLDIER, |
|
|
"class_portraits/demoman", // TF_CLASS_DEMOMAN, |
|
|
"class_portraits/medic", // TF_CLASS_MEDIC, |
|
|
"class_portraits/heavy", // TF_CLASS_HEAVYWEAPONS, |
|
|
"class_portraits/pyro", // TF_CLASS_PYRO, |
|
|
"class_portraits/spy", // TF_CLASS_SPY, |
|
|
"class_portraits/engineer", // TF_CLASS_ENGINEER, |
|
|
"class_portraits/scout_grey", // TF_CLASS_SCOUT, |
|
|
"class_portraits/sniper_grey", // TF_CLASS_SNIPER, |
|
|
"class_portraits/soldier_grey", // TF_CLASS_SOLDIER, |
|
|
"class_portraits/demoman_grey", // TF_CLASS_DEMOMAN, |
|
|
"class_portraits/medic_grey", // TF_CLASS_MEDIC, |
|
|
"class_portraits/heavy_grey", // TF_CLASS_HEAVYWEAPONS, |
|
|
"class_portraits/pyro_grey", // TF_CLASS_PYRO, |
|
|
"class_portraits/spy_grey", // TF_CLASS_SPY, |
|
|
"class_portraits/engineer_grey", // TF_CLASS_ENGINEER, |
|
|
}; |
|
|
|
|
|
const char *g_pszItemClassImagesBlue[] = |
|
|
{ |
|
|
"class_portraits/all_class", // TF_CLASS_UNDEFINED = 0, |
|
|
"class_portraits/scout_blue", // TF_CLASS_SCOUT, |
|
|
"class_portraits/sniper_blue", // TF_CLASS_SNIPER, |
|
|
"class_portraits/soldier_blue", // TF_CLASS_SOLDIER, |
|
|
"class_portraits/demoman_blue", // TF_CLASS_DEMOMAN, |
|
|
"class_portraits/medic_blue", // TF_CLASS_MEDIC, |
|
|
"class_portraits/heavy_blue", // TF_CLASS_HEAVYWEAPONS, |
|
|
"class_portraits/pyro_blue", // TF_CLASS_PYRO, |
|
|
"class_portraits/spy_blue", // TF_CLASS_SPY, |
|
|
"class_portraits/engineer_blue", // TF_CLASS_ENGINEER, |
|
|
"class_portraits/scout_blue_grey", // TF_CLASS_SCOUT, |
|
|
"class_portraits/sniper_blue_grey", // TF_CLASS_SNIPER, |
|
|
"class_portraits/soldier_blue_grey", // TF_CLASS_SOLDIER, |
|
|
"class_portraits/demoman_blue_grey", // TF_CLASS_DEMOMAN, |
|
|
"class_portraits/medic_blue_grey", // TF_CLASS_MEDIC, |
|
|
"class_portraits/heavy_blue_grey", // TF_CLASS_HEAVYWEAPONS, |
|
|
"class_portraits/pyro_blue_grey", // TF_CLASS_PYRO, |
|
|
"class_portraits/spy_blue_grey", // TF_CLASS_SPY, |
|
|
"class_portraits/engineer_blue_grey", // TF_CLASS_ENGINEER, |
|
|
}; |
|
|
|
|
|
const char *g_pszCompetitiveMedalImages[] = |
|
|
{ |
|
|
"", |
|
|
"competitive/competitive_coin_bronze", |
|
|
"competitive/competitive_coin_silver", |
|
|
"competitive/competitive_coin_gold", |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszCompetitiveMedalImages ) == StatMedal_Max ); |
|
|
|
|
|
#endif // TF_CLIENT_DLL |
|
|
|
|
|
|
|
|
// rune icons for each team |
|
|
static const char *s_pszRuneIcons[2][RUNE_TYPES_MAX] = |
|
|
{ |
|
|
// RED TEAM |
|
|
{ |
|
|
"powerup_icon_strength_red", |
|
|
"powerup_icon_haste_red", |
|
|
"powerup_icon_regen_red", |
|
|
"powerup_icon_resist_red", |
|
|
"powerup_icon_vampire_red", |
|
|
"powerup_icon_reflect_red", |
|
|
"powerup_icon_precision_red", |
|
|
"powerup_icon_agility_red", |
|
|
"powerup_icon_knockout_red", |
|
|
"powerup_icon_king_red", |
|
|
"powerup_icon_plague_red", |
|
|
"powerup_icon_supernova_red", |
|
|
}, |
|
|
// BLUE TEAM |
|
|
{ |
|
|
"powerup_icon_strength_blue", |
|
|
"powerup_icon_haste_blue", |
|
|
"powerup_icon_regen_blue", |
|
|
"powerup_icon_resist_blue", |
|
|
"powerup_icon_vampire_blue", |
|
|
"powerup_icon_reflect_blue", |
|
|
"powerup_icon_precision_blue", |
|
|
"powerup_icon_agility_blue", |
|
|
"powerup_icon_knockout_blue", |
|
|
"powerup_icon_king_blue", |
|
|
"powerup_icon_plague_blue", |
|
|
"powerup_icon_supernova_blue", |
|
|
} |
|
|
}; |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( s_pszRuneIcons[0] ) == RUNE_TYPES_MAX ); |
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( s_pszRuneIcons[1] ) == RUNE_TYPES_MAX ); |
|
|
|
|
|
const char *GetPowerupIconName( RuneTypes_t type, int iTeam ) |
|
|
{ |
|
|
int iTeamIndex = iTeam == TF_TEAM_RED ? 0 : 1; |
|
|
if ( type != RUNE_NONE && type < RUNE_TYPES_MAX ) |
|
|
{ |
|
|
return s_pszRuneIcons[ iTeamIndex ][ type ]; |
|
|
} |
|
|
|
|
|
return NULL; |
|
|
}
|
|
|
|