Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2011 lines
60 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tf_shareddefs.h"
  8. #include "KeyValues.h"
  9. #include "takedamageinfo.h"
  10. #include "tf_gamerules.h"
  11. #include "filesystem.h"
  12. #include "tf_matchmaking_shared.h"
  13. //-----------------------------------------------------------------------------
  14. // Teams.
  15. //-----------------------------------------------------------------------------
  16. const char *g_aTeamNames[TF_TEAM_COUNT] =
  17. {
  18. "Unassigned",
  19. "Spectator",
  20. "Red",
  21. "Blue"
  22. };
  23. color32 g_aTeamColors[TF_TEAM_COUNT] =
  24. {
  25. { 0, 0, 0, 0 },
  26. { 0, 0, 0, 0 },
  27. { 255, 0, 0, 0 },
  28. { 0, 0, 255, 0 }
  29. };
  30. //-----------------------------------------------------------------------------
  31. // Classes.
  32. //-----------------------------------------------------------------------------
  33. const char *g_aPlayerClassNames[TF_CLASS_MENU_BUTTONS] =
  34. {
  35. "#TF_Class_Name_Undefined",
  36. "#TF_Class_Name_Scout",
  37. "#TF_Class_Name_Sniper",
  38. "#TF_Class_Name_Soldier",
  39. "#TF_Class_Name_Demoman",
  40. "#TF_Class_Name_Medic",
  41. "#TF_Class_Name_HWGuy",
  42. "#TF_Class_Name_Pyro",
  43. "#TF_Class_Name_Spy",
  44. "#TF_Class_Name_Engineer",
  45. "#TF_Class_Name_Civilian",
  46. "",
  47. "#TF_Random"
  48. };
  49. const char *g_aPlayerClassNames_NonLocalized[TF_CLASS_MENU_BUTTONS] =
  50. {
  51. "Undefined",
  52. "Scout",
  53. "Sniper",
  54. "Soldier",
  55. "Demoman",
  56. "Medic",
  57. "Heavy",
  58. "Pyro",
  59. "Spy",
  60. "Engineer",
  61. "Civilian",
  62. "",
  63. "Random"
  64. };
  65. const char *g_aRawPlayerClassNamesShort[TF_CLASS_MENU_BUTTONS] =
  66. {
  67. "undefined",
  68. "scout",
  69. "sniper",
  70. "soldier",
  71. "demo", // short
  72. "medic",
  73. "heavy",// short
  74. "pyro",
  75. "spy",
  76. "engineer",
  77. "civilian",
  78. "",
  79. "random"
  80. };
  81. const char *g_aRawPlayerClassNames[TF_CLASS_MENU_BUTTONS] =
  82. {
  83. "undefined",
  84. "scout",
  85. "sniper",
  86. "soldier",
  87. "demoman",
  88. "medic",
  89. "heavyweapons",
  90. "pyro",
  91. "spy",
  92. "engineer",
  93. "civilian",
  94. "",
  95. "random"
  96. };
  97. const char g_szBotModels[][ MAX_PATH ] =
  98. {
  99. "", //TF_CLASS_UNDEFINED
  100. "models/bots/scout/bot_scout.mdl",
  101. "models/bots/sniper/bot_sniper.mdl",
  102. "models/bots/soldier/bot_soldier.mdl",
  103. "models/bots/demo/bot_demo.mdl",
  104. "models/bots/medic/bot_medic.mdl",
  105. "models/bots/heavy/bot_heavy.mdl",
  106. "models/bots/pyro/bot_pyro.mdl",
  107. "models/bots/spy/bot_spy.mdl",
  108. "models/bots/engineer/bot_engineer.mdl",
  109. };
  110. const char g_szPlayerRobotModels[][MAX_PATH] =
  111. {
  112. "", //TF_CLASS_UNDEFINED
  113. "models/bots/scout/bot_scout_human_anim.mdl",
  114. "models/bots/sniper/bot_sniper_human_anim.mdl",
  115. "models/bots/soldier/bot_soldier_human_anim.mdl",
  116. "models/bots/demo/bot_demo_human_anim.mdl",
  117. "models/bots/medic/bot_medic_human_anims.mdl",
  118. "models/bots/heavy/bot_heavy_human_anims.mdl",
  119. "models/bots/pyro/bot_pyro_human_anim.mdl",
  120. "models/bots/spy/bot_spy_human_anims.mdl",
  121. "models/bots/engineer/bot_engineer_human_anim.mdl",
  122. };
  123. const char g_szBotBossModels[][ MAX_PATH ] =
  124. {
  125. "", //TF_CLASS_UNDEFINED
  126. "models/bots/scout_boss/bot_scout_boss.mdl",
  127. "models/bots/sniper/bot_sniper.mdl",
  128. "models/bots/soldier_boss/bot_soldier_boss.mdl",
  129. "models/bots/demo_boss/bot_demo_boss.mdl",
  130. "models/bots/medic/bot_medic.mdl",
  131. "models/bots/heavy_boss/bot_heavy_boss.mdl",
  132. "models/bots/pyro_boss/bot_pyro_boss.mdl",
  133. "models/bots/spy/bot_spy.mdl",
  134. "models/bots/engineer/bot_engineer.mdl",
  135. };
  136. const char g_szBotBossSentryBusterModel[ MAX_PATH ] = "models/bots/demo/bot_sentry_buster.mdl";
  137. // Rome 2 promo models
  138. const char g_szRomePromoItems_Hat[][ MAX_PATH ] =
  139. {
  140. "", //TF_CLASS_UNDEFINED
  141. "tw_scoutbot_hat",
  142. "tw_sniperbot_helmet",
  143. "tw_soldierbot_helmet",
  144. "tw_demobot_helmet",
  145. "tw_medibot_hat",
  146. "tw_heavybot_helmet",
  147. "tw_pyrobot_helmet",
  148. "tw_spybot_hood",
  149. "tw_engineerbot_helmet",
  150. };
  151. const char g_szRomePromoItems_Misc[][ MAX_PATH ] =
  152. {
  153. "", //TF_CLASS_UNDEFINED
  154. "tw_scoutbot_armor",
  155. "tw_sniperbot_armor",
  156. "tw_soldierbot_armor",
  157. "tw_demobot_armor",
  158. "tw_medibot_chariot",
  159. "tw_heavybot_armor",
  160. "tw_pyrobot_armor",
  161. "tw_spybot_armor",
  162. "tw_engineerbot_armor",
  163. };
  164. const char *g_pszBreadModels[] =
  165. {
  166. "models/weapons/c_models/c_bread/c_bread_baguette.mdl", // Spy
  167. "models/weapons/c_models/c_bread/c_bread_burnt.mdl", // Pyro
  168. "models/weapons/c_models/c_bread/c_bread_cinnamon.mdl", // Demo?
  169. "models/weapons/c_models/c_bread/c_bread_cornbread.mdl", // Engineer
  170. "models/weapons/c_models/c_bread/c_bread_crumpet.mdl", // Sniper?
  171. "models/weapons/c_models/c_bread/c_bread_plainloaf.mdl", // Scout
  172. "models/weapons/c_models/c_bread/c_bread_pretzel.mdl", // Medic
  173. "models/weapons/c_models/c_bread/c_bread_ration.mdl", // Soldier
  174. "models/weapons/c_models/c_bread/c_bread_russianblack.mdl", // Heavy?
  175. };
  176. int GetClassIndexFromString( const char *pClassName, int nLastClassIndex/*=TF_LAST_NORMAL_CLASS*/ )
  177. {
  178. for ( int i = TF_FIRST_NORMAL_CLASS; i <= nLastClassIndex; ++i )
  179. {
  180. // compare first N characters to allow matching both "heavy" and "heavyweapons"
  181. int classnameLength = V_strlen( g_aPlayerClassNames_NonLocalized[i] );
  182. if ( V_strlen( pClassName ) < classnameLength )
  183. continue;
  184. if ( !V_strnicmp( g_aPlayerClassNames_NonLocalized[i], pClassName, classnameLength ) )
  185. {
  186. return i;
  187. }
  188. }
  189. return TF_CLASS_UNDEFINED;
  190. }
  191. int iRemapIndexToClass[TF_CLASS_MENU_BUTTONS] =
  192. {
  193. 0,
  194. TF_CLASS_SCOUT,
  195. TF_CLASS_SOLDIER,
  196. TF_CLASS_PYRO,
  197. TF_CLASS_DEMOMAN,
  198. TF_CLASS_HEAVYWEAPONS,
  199. TF_CLASS_ENGINEER,
  200. TF_CLASS_MEDIC,
  201. TF_CLASS_SNIPER,
  202. TF_CLASS_SPY,
  203. 0,
  204. 0,
  205. TF_CLASS_RANDOM
  206. };
  207. int GetRemappedMenuIndexForClass( int iClass )
  208. {
  209. int iIndex = 0;
  210. for ( int i = 0 ; i < TF_CLASS_MENU_BUTTONS ; i++ )
  211. {
  212. if ( iRemapIndexToClass[i] == iClass )
  213. {
  214. iIndex = i;
  215. break;
  216. }
  217. }
  218. return iIndex;
  219. }
  220. ETFCond condition_to_attribute_translation[] =
  221. {
  222. TF_COND_BURNING, // 1 (1<<0)
  223. TF_COND_AIMING, // 2 (1<<1)
  224. TF_COND_ZOOMED, // 4 (1<<2)
  225. TF_COND_DISGUISING, // 8 (...)
  226. TF_COND_DISGUISED, // 16
  227. TF_COND_STEALTHED, // 32
  228. TF_COND_INVULNERABLE, // 64
  229. TF_COND_TELEPORTED, // 128
  230. TF_COND_TAUNTING, // 256
  231. TF_COND_INVULNERABLE_WEARINGOFF, // 512
  232. TF_COND_STEALTHED_BLINK, // 1024
  233. TF_COND_SELECTED_TO_TELEPORT, // 2048
  234. TF_COND_CRITBOOSTED, // 4096
  235. TF_COND_TMPDAMAGEBONUS, // 8192
  236. TF_COND_FEIGN_DEATH, // 16384
  237. TF_COND_PHASE, // 32768
  238. TF_COND_STUNNED, // 65536
  239. TF_COND_HEALTH_BUFF, // 131072
  240. TF_COND_HEALTH_OVERHEALED, // 262144
  241. TF_COND_URINE, // 524288
  242. TF_COND_ENERGY_BUFF, // 1048576
  243. TF_COND_LAST // sentinel value checked against when iterating
  244. };
  245. ETFCond g_aDebuffConditions[] =
  246. {
  247. TF_COND_BURNING,
  248. TF_COND_URINE,
  249. TF_COND_BLEEDING,
  250. TF_COND_MAD_MILK,
  251. TF_COND_LAST
  252. };
  253. bool ConditionExpiresFast( ETFCond eCond )
  254. {
  255. return eCond == TF_COND_BURNING
  256. || eCond == TF_COND_URINE
  257. || eCond == TF_COND_BLEEDING
  258. || eCond == TF_COND_MAD_MILK;
  259. }
  260. static const char *g_aConditionNames[] =
  261. {
  262. "TF_COND_AIMING", // Sniper aiming, Heavy minigun.
  263. "TF_COND_ZOOMED",
  264. "TF_COND_DISGUISING",
  265. "TF_COND_DISGUISED",
  266. "TF_COND_STEALTHED", // Spy specific
  267. "TF_COND_INVULNERABLE",
  268. "TF_COND_TELEPORTED",
  269. "TF_COND_TAUNTING",
  270. "TF_COND_INVULNERABLE_WEARINGOFF",
  271. "TF_COND_STEALTHED_BLINK",
  272. "TF_COND_SELECTED_TO_TELEPORT",
  273. "TF_COND_CRITBOOSTED", // DO NOT RE-USE THIS -- THIS IS FOR KRITZKRIEG AND REVENGE CRITS ONLY
  274. "TF_COND_TMPDAMAGEBONUS",
  275. "TF_COND_FEIGN_DEATH",
  276. "TF_COND_PHASE",
  277. "TF_COND_STUNNED", // Any type of stun. Check iStunFlags for more info.
  278. "TF_COND_OFFENSEBUFF",
  279. "TF_COND_SHIELD_CHARGE",
  280. "TF_COND_DEMO_BUFF",
  281. "TF_COND_ENERGY_BUFF",
  282. "TF_COND_RADIUSHEAL",
  283. "TF_COND_HEALTH_BUFF",
  284. "TF_COND_BURNING",
  285. "TF_COND_HEALTH_OVERHEALED",
  286. "TF_COND_URINE",
  287. "TF_COND_BLEEDING",
  288. "TF_COND_DEFENSEBUFF", // 35% defense! No crit damage.
  289. "TF_COND_MAD_MILK",
  290. "TF_COND_MEGAHEAL",
  291. "TF_COND_REGENONDAMAGEBUFF",
  292. "TF_COND_MARKEDFORDEATH",
  293. "TF_COND_NOHEALINGDAMAGEBUFF",
  294. "TF_COND_SPEED_BOOST", // = 32
  295. "TF_COND_CRITBOOSTED_PUMPKIN", // Brandon hates bits
  296. "TF_COND_CRITBOOSTED_USER_BUFF",
  297. "TF_COND_CRITBOOSTED_DEMO_CHARGE",
  298. "TF_COND_SODAPOPPER_HYPE",
  299. "TF_COND_CRITBOOSTED_FIRST_BLOOD", // arena mode first blood
  300. "TF_COND_CRITBOOSTED_BONUS_TIME",
  301. "TF_COND_CRITBOOSTED_CTF_CAPTURE",
  302. "TF_COND_CRITBOOSTED_ON_KILL", // =40. KGB, etc.
  303. "TF_COND_CANNOT_SWITCH_FROM_MELEE",
  304. "TF_COND_DEFENSEBUFF_NO_CRIT_BLOCK", // 35% defense! Still damaged by crits.
  305. "TF_COND_REPROGRAMMED", // Bots only
  306. "TF_COND_CRITBOOSTED_RAGE_BUFF",
  307. "TF_COND_DEFENSEBUFF_HIGH", // 75% defense! Still damaged by crits.
  308. "TF_COND_SNIPERCHARGE_RAGE_BUFF", // Sniper Rage - Charge time speed up
  309. "TF_COND_DISGUISE_WEARINGOFF", // Applied for half-second post-disguise
  310. "TF_COND_MARKEDFORDEATH_SILENT", // Sans sound
  311. "TF_COND_DISGUISED_AS_DISPENSER",
  312. "TF_COND_SAPPED", // =50. Bots only
  313. "TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED",
  314. "TF_COND_INVULNERABLE_USER_BUFF",
  315. "TF_COND_HALLOWEEN_BOMB_HEAD",
  316. "TF_COND_HALLOWEEN_THRILLER",
  317. "TF_COND_RADIUSHEAL_ON_DAMAGE",
  318. "TF_COND_CRITBOOSTED_CARD_EFFECT",
  319. "TF_COND_INVULNERABLE_CARD_EFFECT",
  320. "TF_COND_MEDIGUN_UBER_BULLET_RESIST",
  321. "TF_COND_MEDIGUN_UBER_BLAST_RESIST",
  322. "TF_COND_MEDIGUN_UBER_FIRE_RESIST", // =60
  323. "TF_COND_MEDIGUN_SMALL_BULLET_RESIST",
  324. "TF_COND_MEDIGUN_SMALL_BLAST_RESIST",
  325. "TF_COND_MEDIGUN_SMALL_FIRE_RESIST",
  326. "TF_COND_STEALTHED_USER_BUFF", // Any class can have this
  327. "TF_COND_MEDIGUN_DEBUFF",
  328. "TF_COND_STEALTHED_USER_BUFF_FADING",
  329. "TF_COND_BULLET_IMMUNE",
  330. "TF_COND_BLAST_IMMUNE",
  331. "TF_COND_FIRE_IMMUNE",
  332. "TF_COND_PREVENT_DEATH", // =70
  333. "TF_COND_MVM_BOT_STUN_RADIOWAVE", // Bots only
  334. "TF_COND_HALLOWEEN_SPEED_BOOST",
  335. "TF_COND_HALLOWEEN_QUICK_HEAL",
  336. "TF_COND_HALLOWEEN_GIANT",
  337. "TF_COND_HALLOWEEN_TINY",
  338. "TF_COND_HALLOWEEN_IN_HELL",
  339. "TF_COND_HALLOWEEN_GHOST_MODE", // =77
  340. "TF_COND_MINICRITBOOSTED_ON_KILL",
  341. "TF_COND_OBSCURED_SMOKE",
  342. "TF_COND_PARACHUTE_DEPLOYED", // =80
  343. "TF_COND_BLASTJUMPING",
  344. "TF_COND_HALLOWEEN_KART",
  345. "TF_COND_HALLOWEEN_KART_DASH",
  346. "TF_COND_BALLOON_HEAD", // =84 larger head, lower-gravity-feeling jumps
  347. "TF_COND_MELEE_ONLY", // =85 melee only
  348. "TF_COND_SWIMMING_CURSE", // player movement become swimming movement
  349. "TF_COND_FREEZE_INPUT", // freezes player input
  350. "TF_COND_HALLOWEEN_KART_CAGE", // attach cage model to player while in kart
  351. "TF_COND_DONOTUSE_0",
  352. "TF_COND_RUNE_STRENGTH",
  353. "TF_COND_RUNE_HASTE",
  354. "TF_COND_RUNE_REGEN",
  355. "TF_COND_RUNE_RESIST",
  356. "TF_COND_RUNE_VAMPIRE",
  357. "TF_COND_RUNE_REFLECT",
  358. "TF_COND_RUNE_PRECISION",
  359. "TF_COND_RUNE_AGILITY",
  360. "TF_COND_GRAPPLINGHOOK",
  361. "TF_COND_GRAPPLINGHOOK_SAFEFALL",
  362. "TF_COND_GRAPPLINGHOOK_LATCHED",
  363. "TF_COND_GRAPPLINGHOOK_BLEEDING",
  364. "TF_COND_AFTERBURN_IMMUNE",
  365. "TF_COND_RUNE_KNOCKOUT",
  366. "TF_COND_RUNE_IMBALANCE",
  367. "TF_COND_CRITBOOSTED_RUNE_TEMP",
  368. "TF_COND_PASSTIME_INTERCEPTION",
  369. "TF_COND_SWIMMING_NO_EFFECTS", // =107_DNOC_FT
  370. "TF_COND_PURGATORY",
  371. "TF_COND_RUNE_KING",
  372. "TF_COND_RUNE_PLAGUE",
  373. "TF_COND_RUNE_SUPERNOVA",
  374. "TF_COND_PLAGUE",
  375. "TF_COND_KING_BUFFED",
  376. "TF_COND_TEAM_GLOWS", // used to show team glows to living players
  377. "TF_COND_KNOCKED_INTO_AIR",
  378. "TF_COND_COMPETITIVE_WINNER",
  379. "TF_COND_COMPETITIVE_LOSER",
  380. "TF_COND_HEALING_DEBUFF",
  381. "TF_COND_PASSTIME_PENALTY_DEBUFF",
  382. "TF_COND_GRAPPLED_TO_PLAYER",
  383. "TF_COND_GRAPPLED_BY_PLAYER",
  384. //
  385. // ADD NEW ITEMS HERE TO AVOID BREAKING DEMOS
  386. //
  387. // ******** Keep this block last! ********
  388. // Keep experimental conditions below and graduate out of it before shipping
  389. #ifdef STAGING_ONLY
  390. "TF_COND_NO_COMBAT_SPEED_BOOST", // STAGING_ENGY
  391. "TF_COND_TRANQ_SPY_BOOST", // STAGING_SPY
  392. "TF_COND_TRANQ_MARKED",
  393. // "TF_COND_SPACE_GRAVITY",
  394. // "TF_COND_SELF_CONC",
  395. "TF_COND_ROCKETPACK",
  396. "TF_COND_STEALTHED_PHASE",
  397. "TF_COND_CLIP_OVERLOAD",
  398. "TF_COND_SPY_CLASS_STEAL",
  399. #endif // STAGING_ONLY
  400. };
  401. COMPILE_TIME_ASSERT( ARRAYSIZE( g_aConditionNames ) == TF_COND_LAST );
  402. const char *GetTFConditionName( ETFCond eCond )
  403. {
  404. if ( ( eCond >= ARRAYSIZE( g_aConditionNames ) ) || ( eCond < 0 ) )
  405. return NULL;
  406. return g_aConditionNames[eCond];
  407. }
  408. ETFCond GetTFConditionFromName( const char *pszCondName )
  409. {
  410. for( uint i=0; i<TF_COND_LAST; i++ )
  411. {
  412. ETFCond eCond = (ETFCond)i;
  413. if ( !V_stricmp( GetTFConditionName( eCond ), pszCondName ) )
  414. return eCond;
  415. }
  416. Assert( !!"Invalid Condition Name" );
  417. return TF_COND_INVALID;
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Gametypes.
  421. //-----------------------------------------------------------------------------
  422. static const char *s_aGameTypeNames[] =
  423. {
  424. "Undefined",
  425. "#Gametype_CTF",
  426. "#Gametype_CP",
  427. "#Gametype_Escort",
  428. "#Gametype_Arena",
  429. "#Gametype_MVM",
  430. "#Gametype_RobotDestruction",
  431. "#GameType_Passtime",
  432. "#GameType_PlayerDestruction",
  433. };
  434. COMPILE_TIME_ASSERT( TF_GAMETYPE_COUNT == ARRAYSIZE( s_aGameTypeNames ) );
  435. const char *GetGameTypeName( ETFGameType gameType )
  436. {
  437. return s_aGameTypeNames[ gameType ];
  438. }
  439. static const char *s_aEnumGameTypeName[] =
  440. {
  441. "TF_GAMETYPE_UNDEFINED",
  442. "TF_GAMETYPE_CTF",
  443. "TF_GAMETYPE_CP",
  444. "TF_GAMETYPE_ESCORT",
  445. "TF_GAMETYPE_ARENA",
  446. "TF_GAMETYPE_MVM",
  447. "TF_GAMETYPE_RD",
  448. "TF_GAMETYPE_PASSTIME",
  449. "TF_GAMETYPE_PD"
  450. };
  451. COMPILE_TIME_ASSERT( TF_GAMETYPE_COUNT == ARRAYSIZE( s_aEnumGameTypeName ) );
  452. const char *GetEnumGameTypeName( ETFGameType gameType )
  453. {
  454. return s_aEnumGameTypeName[ gameType ];
  455. }
  456. ETFGameType GetGameTypeFromName( const char *pszGameType )
  457. {
  458. for ( int i=0; i<TF_GAMETYPE_COUNT; ++i )
  459. {
  460. if ( FStrEq( pszGameType, s_aEnumGameTypeName[i] ) )
  461. return ETFGameType(i);
  462. }
  463. return TF_GAMETYPE_UNDEFINED;
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Ammo.
  467. //-----------------------------------------------------------------------------
  468. const char *g_aAmmoNames[] =
  469. {
  470. "DUMMY AMMO",
  471. "TF_AMMO_PRIMARY",
  472. "TF_AMMO_SECONDARY",
  473. "TF_AMMO_METAL",
  474. "TF_AMMO_GRENADES1",
  475. "TF_AMMO_GRENADES2",
  476. "TF_AMMO_GRENADES3"
  477. };
  478. COMPILE_TIME_ASSERT( ARRAYSIZE( g_aAmmoNames ) == TF_AMMO_COUNT );
  479. const char *GetAmmoName( int iAmmoType )
  480. {
  481. ETFAmmoType eAmmoType = (ETFAmmoType)iAmmoType;
  482. return g_aAmmoNames[ eAmmoType ];
  483. }
  484. const char *g_aCTFEventNames[] =
  485. {
  486. "",
  487. "TF_FLAGEVENT_PICKUP",
  488. "TF_FLAGEVENT_CAPTURE",
  489. "TF_FLAGEVENT_DEFEND",
  490. "TF_FLAGEVENT_DROPPED",
  491. "TF_FLAGEVENT_RETURNED",
  492. };
  493. COMPILE_TIME_ASSERT( ARRAYSIZE( g_aCTFEventNames ) == TF_NUM_FLAG_EVENTS );
  494. const char *GetCTFEventName( ETFFlagEventTypes iEventType )
  495. {
  496. return g_aCTFEventNames[ iEventType ];
  497. }
  498. ETFFlagEventTypes GetCTFEventTypeFromName( const char *pszName )
  499. {
  500. for( int i=TF_FLAGEVENT_PICKUP; i < TF_NUM_FLAG_EVENTS; ++i )
  501. {
  502. if ( FStrEq( pszName, GetCTFEventName( (ETFFlagEventTypes)i ) ) )
  503. {
  504. return (ETFFlagEventTypes)i;
  505. }
  506. }
  507. Assert( false );
  508. return TF_NUM_FLAG_EVENTS;
  509. }
  510. const char *GetRDScoreMethodName( RDScoreMethod_t iScoreMethod )
  511. {
  512. static const char *aRDScoreMethodNames[] =
  513. {
  514. "SCORE_UNDEFINED", // -1
  515. "SCORE_REACTOR_CAPTURED", // 0
  516. "SCORE_CORES_COLLECTED",
  517. "SCORE_REACTOR_RETURNED",
  518. "SCORE_REACTOR_STEAL",
  519. "NUM_SCORE_TYPES"
  520. };
  521. return aRDScoreMethodNames[ iScoreMethod + 1 ];
  522. }
  523. RDScoreMethod_t GetRDScoreMethodFromName( const char *pszName )
  524. {
  525. for( int i=SCORE_UNDEFINED; i < NUM_SCORE_TYPES; ++i )
  526. {
  527. if ( FStrEq( pszName, GetRDScoreMethodName( (RDScoreMethod_t)i ) ) )
  528. {
  529. return (RDScoreMethod_t)i;
  530. }
  531. }
  532. Assert( false );
  533. return SCORE_UNDEFINED;
  534. }
  535. //-----------------------------------------------------------------------------
  536. // Weapons.
  537. //-----------------------------------------------------------------------------
  538. const char *g_aWeaponNames[] =
  539. {
  540. "TF_WEAPON_NONE",
  541. "TF_WEAPON_BAT",
  542. "TF_WEAPON_BAT_WOOD",
  543. "TF_WEAPON_BOTTLE",
  544. "TF_WEAPON_FIREAXE",
  545. "TF_WEAPON_CLUB",
  546. "TF_WEAPON_CROWBAR",
  547. "TF_WEAPON_KNIFE",
  548. "TF_WEAPON_FISTS",
  549. "TF_WEAPON_SHOVEL",
  550. "TF_WEAPON_WRENCH",
  551. "TF_WEAPON_BONESAW",
  552. "TF_WEAPON_SHOTGUN_PRIMARY",
  553. "TF_WEAPON_SHOTGUN_SOLDIER",
  554. "TF_WEAPON_SHOTGUN_HWG",
  555. "TF_WEAPON_SHOTGUN_PYRO",
  556. "TF_WEAPON_SCATTERGUN",
  557. "TF_WEAPON_SNIPERRIFLE",
  558. "TF_WEAPON_MINIGUN",
  559. "TF_WEAPON_SMG",
  560. "TF_WEAPON_SYRINGEGUN_MEDIC",
  561. "TF_WEAPON_TRANQ",
  562. "TF_WEAPON_ROCKETLAUNCHER",
  563. "TF_WEAPON_GRENADELAUNCHER",
  564. "TF_WEAPON_PIPEBOMBLAUNCHER",
  565. "TF_WEAPON_FLAMETHROWER",
  566. "TF_WEAPON_GRENADE_NORMAL",
  567. "TF_WEAPON_GRENADE_CONCUSSION",
  568. "TF_WEAPON_GRENADE_NAIL",
  569. "TF_WEAPON_GRENADE_MIRV",
  570. "TF_WEAPON_GRENADE_MIRV_DEMOMAN",
  571. "TF_WEAPON_GRENADE_NAPALM",
  572. "TF_WEAPON_GRENADE_GAS",
  573. "TF_WEAPON_GRENADE_EMP",
  574. "TF_WEAPON_GRENADE_CALTROP",
  575. "TF_WEAPON_GRENADE_PIPEBOMB",
  576. "TF_WEAPON_GRENADE_SMOKE_BOMB",
  577. "TF_WEAPON_GRENADE_HEAL",
  578. "TF_WEAPON_GRENADE_STUNBALL",
  579. "TF_WEAPON_GRENADE_JAR",
  580. "TF_WEAPON_GRENADE_JAR_MILK",
  581. "TF_WEAPON_PISTOL",
  582. "TF_WEAPON_PISTOL_SCOUT",
  583. "TF_WEAPON_REVOLVER",
  584. "TF_WEAPON_NAILGUN",
  585. "TF_WEAPON_PDA",
  586. "TF_WEAPON_PDA_ENGINEER_BUILD",
  587. "TF_WEAPON_PDA_ENGINEER_DESTROY",
  588. "TF_WEAPON_PDA_SPY",
  589. "TF_WEAPON_BUILDER",
  590. "TF_WEAPON_MEDIGUN",
  591. "TF_WEAPON_GRENADE_MIRVBOMB",
  592. "TF_WEAPON_FLAMETHROWER_ROCKET",
  593. "TF_WEAPON_GRENADE_DEMOMAN",
  594. "TF_WEAPON_SENTRY_BULLET",
  595. "TF_WEAPON_SENTRY_ROCKET",
  596. "TF_WEAPON_DISPENSER",
  597. "TF_WEAPON_INVIS",
  598. "TF_WEAPON_FLAREGUN",
  599. "TF_WEAPON_LUNCHBOX",
  600. "TF_WEAPON_JAR",
  601. "TF_WEAPON_COMPOUND_BOW",
  602. "TF_WEAPON_BUFF_ITEM",
  603. "TF_WEAPON_PUMPKIN_BOMB",
  604. "TF_WEAPON_SWORD",
  605. "TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT",
  606. "TF_WEAPON_LIFELINE",
  607. "TF_WEAPON_LASER_POINTER",
  608. "TF_WEAPON_DISPENSER_GUN",
  609. "TF_WEAPON_SENTRY_REVENGE",
  610. "TF_WEAPON_JAR_MILK",
  611. "TF_WEAPON_HANDGUN_SCOUT_PRIMARY",
  612. "TF_WEAPON_BAT_FISH",
  613. "TF_WEAPON_CROSSBOW",
  614. "TF_WEAPON_STICKBOMB",
  615. "TF_WEAPON_HANDGUN_SCOUT_SECONDARY",
  616. "TF_WEAPON_SODA_POPPER",
  617. "TF_WEAPON_SNIPERRIFLE_DECAP",
  618. "TF_WEAPON_RAYGUN",
  619. "TF_WEAPON_PARTICLE_CANNON",
  620. "TF_WEAPON_MECHANICAL_ARM",
  621. "TF_WEAPON_DRG_POMSON",
  622. "TF_WEAPON_BAT_GIFTWRAP",
  623. "TF_WEAPON_GRENADE_ORNAMENT_BALL",
  624. "TF_WEAPON_FLAREGUN_REVENGE",
  625. "TF_WEAPON_PEP_BRAWLER_BLASTER",
  626. "TF_WEAPON_CLEAVER",
  627. "TF_WEAPON_GRENADE_CLEAVER",
  628. "TF_WEAPON_STICKY_BALL_LAUNCHER",
  629. "TF_WEAPON_GRENADE_STICKY_BALL",
  630. "TF_WEAPON_SHOTGUN_BUILDING_RESCUE",
  631. "TF_WEAPON_CANNON",
  632. "TF_WEAPON_THROWABLE",
  633. "TF_WEAPON_GRENADE_THROWABLE",
  634. "TF_WEAPON_PDA_SPY_BUILD",
  635. "TF_WEAPON_GRENADE_WATERBALLOON",
  636. "TF_WEAPON_HARVESTER_SAW",
  637. "TF_WEAPON_SPELLBOOK",
  638. "TF_WEAPON_SPELLBOOK_PROJECTILE",
  639. "TF_WEAPON_SNIPERRIFLE_CLASSIC",
  640. "TF_WEAPON_PARACHUTE",
  641. "TF_WEAPON_GRAPPLINGHOOK",
  642. "TF_WEAPON_PASSTIME_GUN",
  643. #ifdef STAGING_ONLY
  644. "TF_WEAPON_SNIPERRIFLE_REVOLVER",
  645. #endif
  646. "TF_WEAPON_CHARGED_SMG",
  647. };
  648. COMPILE_TIME_ASSERT( ARRAYSIZE( g_aWeaponNames ) == TF_WEAPON_COUNT );
  649. int g_aWeaponDamageTypes[] =
  650. {
  651. DMG_GENERIC, // TF_WEAPON_NONE
  652. DMG_CLUB, // TF_WEAPON_BAT,
  653. DMG_CLUB, // TF_WEAPON_BAT_WOOD,
  654. DMG_CLUB, // TF_WEAPON_BOTTLE,
  655. DMG_CLUB, // TF_WEAPON_FIREAXE,
  656. DMG_CLUB, // TF_WEAPON_CLUB,
  657. DMG_CLUB, // TF_WEAPON_CROWBAR,
  658. DMG_SLASH, // TF_WEAPON_KNIFE,
  659. DMG_CLUB, // TF_WEAPON_FISTS,
  660. DMG_CLUB, // TF_WEAPON_SHOVEL,
  661. DMG_CLUB, // TF_WEAPON_WRENCH,
  662. DMG_SLASH, // TF_WEAPON_BONESAW,
  663. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_PRIMARY,
  664. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_SOLDIER,
  665. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_HWG,
  666. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_PYRO,
  667. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SCATTERGUN,
  668. DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE,
  669. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_MINIGUN,
  670. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_SMG,
  671. DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_SYRINGEGUN_MEDIC,
  672. DMG_BULLET | DMG_USEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE | DMG_PARALYZE, // TF_WEAPON_TRANQ,
  673. DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_ROCKETLAUNCHER,
  674. DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_GRENADELAUNCHER,
  675. DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_PIPEBOMBLAUNCHER,
  676. DMG_IGNITE | DMG_PREVENT_PHYSICS_FORCE | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_FLAMETHROWER,
  677. DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_NORMAL,
  678. DMG_SONIC | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_CONCUSSION,
  679. DMG_BULLET | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_NAIL,
  680. DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_MIRV,
  681. DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_MIRV_DEMOMAN,
  682. DMG_BURN | DMG_RADIUS_MAX, // TF_WEAPON_GRENADE_NAPALM,
  683. DMG_POISON | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_GAS,
  684. DMG_BLAST | DMG_HALF_FALLOFF | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_GRENADE_EMP,
  685. DMG_GENERIC, // TF_WEAPON_GRENADE_CALTROP,
  686. DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_GRENADE_PIPEBOMB,
  687. DMG_GENERIC, // TF_WEAPON_GRENADE_SMOKE_BOMB,
  688. DMG_GENERIC, // TF_WEAPON_GRENADE_HEAL
  689. DMG_CLUB, // TF_WEAPON_GRENADE_STUNBALL
  690. DMG_CLUB, // TF_WEAPON_GRENADE_JAR
  691. DMG_CLUB, // TF_WEAPON_GRENADE_JAR_MILK
  692. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_PISTOL,
  693. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_PISTOL_SCOUT,
  694. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_REVOLVER,
  695. DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD | DMG_PREVENT_PHYSICS_FORCE, // TF_WEAPON_NAILGUN,
  696. DMG_BULLET, // TF_WEAPON_PDA,
  697. DMG_BULLET, // TF_WEAPON_PDA_ENGINEER_BUILD,
  698. DMG_BULLET, // TF_WEAPON_PDA_ENGINEER_DESTROY,
  699. DMG_BULLET, // TF_WEAPON_PDA_SPY,
  700. DMG_BULLET, // TF_WEAPON_BUILDER
  701. DMG_BULLET, // TF_WEAPON_MEDIGUN
  702. DMG_BLAST, // TF_WEAPON_GRENADE_MIRVBOMB
  703. DMG_BLAST | DMG_IGNITE | DMG_RADIUS_MAX, // TF_WEAPON_FLAMETHROWER_ROCKET
  704. DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_GRENADE_DEMOMAN
  705. DMG_BULLET, // TF_WEAPON_SENTRY_BULLET
  706. DMG_BLAST, // TF_WEAPON_SENTRY_ROCKET
  707. DMG_GENERIC, // TF_WEAPON_DISPENSER
  708. DMG_GENERIC, // TF_WEAPON_INVIS
  709. DMG_BULLET | DMG_IGNITE, // TF_WEAPON_FLAREGUN
  710. DMG_GENERIC, // TF_WEAPON_LUNCHBOX
  711. DMG_GENERIC, // TF_WEAPON_JAR
  712. DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_COMPOUND_BOW
  713. DMG_GENERIC, // TF_WEAPON_BUFF_ITEM
  714. DMG_CLUB, // TF_WEAPON_PUMPKIN_BOMB
  715. DMG_CLUB, // TF_WEAPON_SWORD
  716. DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT,
  717. DMG_CLUB, // TF_WEAPON_LIFELINE
  718. DMG_CLUB, // TF_WEAPON_LASER_POINTER
  719. DMG_BULLET, // TF_WEAPON_DISPENSER_GUN
  720. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SENTRY_REVENGE
  721. DMG_GENERIC, // TF_WEAPON_JAR_MILK
  722. DMG_BUCKSHOT | DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_HANDGUN_SCOUT_PRIMARY
  723. DMG_CLUB, // TF_WEAPON_BAT_FISH
  724. DMG_BULLET | DMG_USE_HITLOCATIONS,
  725. DMG_CLUB, // TF_WEAPON_STICKBOMB
  726. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_HANDGUN_SCOUT_SECONDARY
  727. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SODA_POPPER,
  728. DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_DECAP,
  729. DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_RAYGUN,
  730. DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD, // TF_WEAPON_PARTICLE_CANNON,
  731. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_MECHANICAL_ARM,
  732. DMG_BULLET | DMG_USEDISTANCEMOD | DMG_NOCLOSEDISTANCEMOD, // TF_WEAPON_DRG_POMSON,
  733. DMG_CLUB, // TF_WEAPON_BAT_GIFTWRAP,
  734. DMG_CLUB, // TF_WEAPON_GRENADE_ORNAMENT_BALL
  735. DMG_BULLET | DMG_IGNITE, // TF_WEAPON_FLAREGUN_REVENGE,
  736. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_PEP_BRAWLER_BLASTER,
  737. DMG_GENERIC, // TF_WEAPON_CLEAVER
  738. DMG_SLASH, // TF_WEAPON_GRENADE_CLEAVER
  739. DMG_GENERIC, // TF_WEAPON_STICKY_BALL_LAUNCHER,
  740. DMG_GENERIC, // TF_WEAPON_GRENADE_STICKY_BALL,
  741. DMG_BUCKSHOT | DMG_USEDISTANCEMOD, // TF_WEAPON_SHOTGUN_BUILDING_RESCUE,
  742. DMG_BLAST | DMG_HALF_FALLOFF, // TF_WEAPON_CANNON
  743. DMG_BULLET, // TF_WEAPON_THROWABLE
  744. DMG_BULLET, // TF_WEAPON_GRENADE_THROWABLE
  745. DMG_BULLET, // TF_WEAPON_PDA_SPY_BUILD
  746. DMG_BULLET, // TF_WEAPON_GRENADE_WATERBALLOON
  747. DMG_SLASH, // TF_WEAPON_HARVESTER_SAW
  748. DMG_GENERIC, // TF_WEAPON_SPELLBOOK
  749. DMG_GENERIC, // TF_WEAPON_SPELLBOOK_PROJECTILE
  750. DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_CLASSIC,
  751. DMG_GENERIC, // TF_WEAPON_PARACHUTE,
  752. DMG_GENERIC, // TF_WEAPON_GRAPPLINGHOOK,
  753. DMG_GENERIC, // TF_WEAPON_PASSTIME_GUN
  754. #ifdef STAGING_ONLY
  755. DMG_BULLET | DMG_USE_HITLOCATIONS, // TF_WEAPON_SNIPERRIFLE_REVOLVER,
  756. #endif
  757. DMG_BULLET | DMG_USEDISTANCEMOD, // TF_WEAPON_CHARGED_SMG,
  758. };
  759. const char *g_szSpecialDamageNames[] =
  760. {
  761. "",
  762. "TF_DMG_CUSTOM_HEADSHOT",
  763. "TF_DMG_CUSTOM_BACKSTAB",
  764. "TF_DMG_CUSTOM_BURNING",
  765. "TF_DMG_WRENCH_FIX",
  766. "TF_DMG_CUSTOM_MINIGUN",
  767. "TF_DMG_CUSTOM_SUICIDE",
  768. "TF_DMG_CUSTOM_TAUNTATK_HADOUKEN",
  769. "TF_DMG_CUSTOM_BURNING_FLARE",
  770. "TF_DMG_CUSTOM_TAUNTATK_HIGH_NOON",
  771. "TF_DMG_CUSTOM_TAUNTATK_GRAND_SLAM",
  772. "TF_DMG_CUSTOM_PENETRATE_MY_TEAM",
  773. "TF_DMG_CUSTOM_PENETRATE_ALL_PLAYERS",
  774. "TF_DMG_CUSTOM_TAUNTATK_FENCING",
  775. "TF_DMG_CUSTOM_PENETRATE_NONBURNING_TEAMMATE",
  776. "TF_DMG_CUSTOM_TAUNTATK_ARROW_STAB",
  777. "TF_DMG_CUSTOM_TELEFRAG",
  778. "TF_DMG_CUSTOM_BURNING_ARROW",
  779. "TF_DMG_CUSTOM_FLYINGBURN",
  780. "TF_DMG_CUSTOM_PUMPKIN_BOMB",
  781. "TF_DMG_CUSTOM_DECAPITATION",
  782. "TF_DMG_CUSTOM_TAUNTATK_GRENADE",
  783. "TF_DMG_CUSTOM_BASEBALL",
  784. "TF_DMG_CUSTOM_CHARGE_IMPACT",
  785. "TF_DMG_CUSTOM_TAUNTATK_BARBARIAN_SWING",
  786. "TF_DMG_CUSTOM_AIR_STICKY_BURST",
  787. "TF_DMG_CUSTOM_DEFENSIVE_STICKY",
  788. "TF_DMG_CUSTOM_PICKAXE",
  789. "TF_DMG_CUSTOM_ROCKET_DIRECTHIT",
  790. "TF_DMG_CUSTOM_TAUNTATK_UBERSLICE",
  791. "TF_DMG_CUSTOM_PLAYER_SENTRY",
  792. "TF_DMG_CUSTOM_STANDARD_STICKY",
  793. "TF_DMG_CUSTOM_SHOTGUN_REVENGE_CRIT",
  794. "TF_DMG_CUSTOM_TAUNTATK_ENGINEER_GUITAR_SMASH",
  795. "TF_DMG_CUSTOM_BLEEDING",
  796. "TF_DMG_CUSTOM_GOLD_WRENCH",
  797. "TF_DMG_CUSTOM_CARRIED_BUILDING",
  798. "TF_DMG_CUSTOM_COMBO_PUNCH",
  799. "TF_DMG_CUSTOM_TAUNTATK_ENGINEER_ARM_KILL",
  800. "TF_DMG_CUSTOM_FISH_KILL",
  801. "TF_DMG_CUSTOM_TRIGGER_HURT",
  802. "TF_DMG_CUSTOM_DECAPITATION_BOSS",
  803. "TF_DMG_CUSTOM_STICKBOMB_EXPLOSION",
  804. "TF_DMG_CUSTOM_AEGIS_ROUND",
  805. "TF_DMG_CUSTOM_FLARE_EXPLOSION",
  806. "TF_DMG_CUSTOM_BOOTS_STOMP",
  807. "TF_DMG_CUSTOM_PLASMA",
  808. "TF_DMG_CUSTOM_PLASMA_CHARGED",
  809. "TF_DMG_CUSTOM_PLASMA_GIB",
  810. "TF_DMG_CUSTOM_PRACTICE_STICKY",
  811. "TF_DMG_CUSTOM_EYEBALL_ROCKET",
  812. "TF_DMG_CUSTOM_HEADSHOT_DECAPITATION",
  813. "TF_DMG_CUSTOM_TAUNTATK_ARMAGEDDON",
  814. "TF_DMG_CUSTOM_FLARE_PELLET",
  815. "TF_DMG_CUSTOM_CLEAVER",
  816. "TF_DMG_CUSTOM_CLEAVER_CRIT",
  817. "TF_DMG_CUSTOM_SAPPER_RECORDER_DEATH",
  818. "TF_DMG_CUSTOM_MERASMUS_PLAYER_BOMB",
  819. "TF_DMG_CUSTOM_MERASMUS_GRENADE",
  820. "TF_DMG_CUSTOM_MERASMUS_ZAP",
  821. "TF_DMG_CUSTOM_MERASMUS_DECAPITATION",
  822. "TF_DMG_CUSTOM_CANNONBALL_PUSH",
  823. "TF_DMG_CUSTOM_TAUNTATK_ALLCLASS_GUITAR_RIFF",
  824. "TF_DMG_CUSTOM_THROWABLE",
  825. "TF_DMG_CUSTOM_THROWABLE_KILL",
  826. "TF_DMG_CUSTOM_SPELL_TELEPORT",
  827. "TF_DMG_CUSTOM_SPELL_SKELETON",
  828. "TF_DMG_CUSTOM_SPELL_MIRV",
  829. "TF_DMG_CUSTOM_SPELL_METEOR",
  830. "TF_DMG_CUSTOM_SPELL_LIGHTNING",
  831. "TF_DMG_CUSTOM_SPELL_FIREBALL",
  832. "TF_DMG_CUSTOM_SPELL_MONOCULUS",
  833. "TF_DMG_CUSTOM_SPELL_BLASTJUMP",
  834. "TF_DMG_CUSTOM_SPELL_BATS",
  835. "TF_DMG_CUSTOM_SPELL_TINY",
  836. "TF_DMG_CUSTOM_KART",
  837. "TF_DMG_CUSTOM_GIANT_HAMMER",
  838. "TF_DMG_CUSTOM_RUNE_REFLECT",
  839. };
  840. COMPILE_TIME_ASSERT( ARRAYSIZE( g_szSpecialDamageNames ) == TF_DMG_CUSTOM_END );
  841. const char *GetCustomDamageName( ETFDmgCustom eDmgCustom )
  842. {
  843. if ( ( eDmgCustom >= ARRAYSIZE( g_szSpecialDamageNames ) ) || ( eDmgCustom < 0 ) )
  844. return NULL;
  845. return g_szSpecialDamageNames[eDmgCustom];
  846. }
  847. ETFDmgCustom GetCustomDamageFromName( const char *pszCustomDmgName )
  848. {
  849. for( uint i=0; i<TF_DMG_CUSTOM_END; i++ )
  850. {
  851. ETFDmgCustom eDmgCustom = (ETFDmgCustom)i;
  852. if ( !V_stricmp( GetCustomDamageName( eDmgCustom ), pszCustomDmgName ) )
  853. return eDmgCustom;
  854. }
  855. Assert( !!"Invalid Custom Damage Name" );
  856. return TF_DMG_CUSTOM_NONE;
  857. }
  858. const char *g_szProjectileNames[] =
  859. {
  860. "",
  861. "projectile_bullet",
  862. "projectile_rocket",
  863. "projectile_pipe",
  864. "projectile_pipe_remote",
  865. "projectile_syringe",
  866. "projectile_flare",
  867. "projectile_jar",
  868. "projectile_arrow",
  869. "projectile_flame_rocket",
  870. "projectile_jar_milk",
  871. "projectile_healing_bolt",
  872. "projectile_energy_ball",
  873. "projectile_energy_ring",
  874. "projectile_pipe_remote_practice",
  875. "projectile_cleaver",
  876. "projectile_sticky_ball",
  877. "projectile_cannonball",
  878. "projectile_building_repair_bolt",
  879. "projectile_festive_arrow",
  880. "projectile_throwable",
  881. "projectile_spellfireball",
  882. "projectile_festive_urine",
  883. "projectile_festive_healing_bolt",
  884. "projectfile_breadmonster_jarate",
  885. "projectfile_breadmonster_madmilk",
  886. "projectile_grapplinghook",
  887. "projectile_sentry_rocket",
  888. "projectile_bread_monster",
  889. #ifdef STAGING_ONLY
  890. // Staging
  891. "projectile_tranq",
  892. "projectile_sniperbullet",
  893. "projectile_throwing_knife",
  894. "projectile_grenade_concussion",
  895. "projectile_grenade_teleport",
  896. "projectile_jarate_bolt",
  897. #endif
  898. };
  899. COMPILE_TIME_ASSERT( ARRAYSIZE( g_szProjectileNames ) == TF_NUM_PROJECTILES );
  900. // these map to the projectiles named in g_szProjectileNames
  901. int g_iProjectileWeapons[] =
  902. {
  903. TF_WEAPON_NONE,
  904. TF_WEAPON_PISTOL,
  905. TF_WEAPON_ROCKETLAUNCHER,
  906. TF_WEAPON_PIPEBOMBLAUNCHER,
  907. TF_WEAPON_GRENADELAUNCHER,
  908. TF_WEAPON_SYRINGEGUN_MEDIC,
  909. TF_WEAPON_FLAREGUN,
  910. TF_WEAPON_JAR,
  911. TF_WEAPON_COMPOUND_BOW,
  912. TF_PROJECTILE_FLAME_ROCKET,
  913. TF_WEAPON_JAR_MILK,
  914. TF_WEAPON_CROSSBOW,
  915. TF_WEAPON_PARTICLE_CANNON,
  916. TF_WEAPON_RAYGUN,
  917. TF_WEAPON_GRENADELAUNCHER, // practice pipes should never kill anyone anyway
  918. TF_WEAPON_CLEAVER,
  919. TF_WEAPON_STICKY_BALL_LAUNCHER,
  920. TF_WEAPON_CANNON,
  921. TF_WEAPON_SHOTGUN_BUILDING_RESCUE,
  922. TF_WEAPON_COMPOUND_BOW,
  923. TF_WEAPON_THROWABLE,
  924. TF_WEAPON_SPELLBOOK,
  925. TF_WEAPON_JAR,
  926. TF_WEAPON_CROSSBOW,
  927. TF_WEAPON_JAR,
  928. TF_WEAPON_JAR,
  929. TF_PROJECTILE_GRAPPLINGHOOK,
  930. TF_WEAPON_SENTRY_ROCKET,
  931. TF_WEAPON_THROWABLE,
  932. #ifdef STAGING_ONLY
  933. // Staging
  934. TF_WEAPON_REVOLVER,
  935. TF_WEAPON_SNIPERRIFLE,
  936. TF_WEAPON_THROWABLE,
  937. TF_WEAPON_THROWABLE,
  938. TF_WEAPON_THROWABLE,
  939. TF_WEAPON_CROSSBOW,
  940. #endif
  941. };
  942. COMPILE_TIME_ASSERT( ARRAYSIZE( g_szProjectileNames ) == ARRAYSIZE( g_iProjectileWeapons ) );
  943. //-----------------------------------------------------------------------------
  944. // Taunt attacks
  945. //-----------------------------------------------------------------------------
  946. static const char* taunt_attack_name[] =
  947. {
  948. "TAUNTATK_NONE",
  949. "TAUNTATK_PYRO_HADOUKEN",
  950. "TAUNTATK_HEAVY_EAT",
  951. "TAUNTATK_HEAVY_RADIAL_BUFF",
  952. "TAUNTATK_HEAVY_HIGH_NOON",
  953. "TAUNTATK_SCOUT_DRINK",
  954. "TAUNTATK_SCOUT_GRAND_SLAM",
  955. "TAUNTATK_MEDIC_INHALE",
  956. "TAUNTATK_SPY_FENCING_SLASH_A",
  957. "TAUNTATK_SPY_FENCING_SLASH_B",
  958. "TAUNTATK_SPY_FENCING_STAB",
  959. "TAUNTATK_RPS_KILL",
  960. "TAUNTATK_SNIPER_ARROW_STAB_IMPALE",
  961. "TAUNTATK_SNIPER_ARROW_STAB_KILL",
  962. "TAUNTATK_SOLDIER_GRENADE_KILL",
  963. "TAUNTATK_DEMOMAN_BARBARIAN_SWING",
  964. "TAUNTATK_MEDIC_UBERSLICE_IMPALE",
  965. "TAUNTATK_MEDIC_UBERSLICE_KILL",
  966. "TAUNTATK_FLIP_LAND_PARTICLE",
  967. "TAUNTATK_RPS_PARTICLE",
  968. "TAUNTATK_HIGHFIVE_PARTICLE",
  969. "TAUNTATK_ENGINEER_GUITAR_SMASH",
  970. "TAUNTATK_ENGINEER_ARM_IMPALE",
  971. "TAUNTATK_ENGINEER_ARM_KILL",
  972. "TAUNTATK_ENGINEER_ARM_BLEND",
  973. "TAUNTATK_SOLDIER_GRENADE_KILL_WORMSIGN",
  974. "TAUNTATK_SHOW_ITEM",
  975. "TAUNTATK_MEDIC_RELEASE_DOVES",
  976. "TAUNTATK_PYRO_ARMAGEDDON",
  977. "TAUNTATK_PYRO_SCORCHSHOT",
  978. "TAUNTATK_ALLCLASS_GUITAR_RIFF",
  979. "TAUNTATK_MEDIC_HEROIC_TAUNT",
  980. //
  981. // INSERT NEW ITEMS HERE TO AVOID BREAKING DEMOS
  982. //
  983. };
  984. COMPILE_TIME_ASSERT( ARRAYSIZE( taunt_attack_name ) == TAUNTATK_COUNT );
  985. taunt_attack_t GetTauntAttackByName( const char* pszTauntAttackName )
  986. {
  987. if ( pszTauntAttackName )
  988. {
  989. for ( int i=0; i<ARRAYSIZE( taunt_attack_name ); ++i )
  990. {
  991. if ( !V_stricmp( pszTauntAttackName, taunt_attack_name[i] ) )
  992. {
  993. return (taunt_attack_t)i;
  994. }
  995. }
  996. }
  997. return TAUNTATK_NONE;
  998. }
  999. const char *g_pszHintMessages[] =
  1000. {
  1001. "#Hint_spotted_a_friend",
  1002. "#Hint_spotted_an_enemy",
  1003. "#Hint_killing_enemies_is_good",
  1004. "#Hint_out_of_ammo",
  1005. "#Hint_turn_off_hints",
  1006. "#Hint_pickup_ammo",
  1007. "#Hint_Cannot_Teleport_With_Flag",
  1008. "#Hint_Cannot_Cloak_With_Flag",
  1009. "#Hint_Cannot_Disguise_With_Flag",
  1010. "#Hint_Cannot_Attack_While_Feign_Armed",
  1011. "#Hint_ClassMenu",
  1012. // Grenades
  1013. "#Hint_gren_caltrops",
  1014. "#Hint_gren_concussion",
  1015. "#Hint_gren_emp",
  1016. "#Hint_gren_gas",
  1017. "#Hint_gren_mirv",
  1018. "#Hint_gren_nail",
  1019. "#Hint_gren_napalm",
  1020. "#Hint_gren_normal",
  1021. // Altfires
  1022. "#Hint_altfire_sniperrifle",
  1023. "#Hint_altfire_flamethrower",
  1024. "#Hint_altfire_grenadelauncher",
  1025. "#Hint_altfire_pipebomblauncher",
  1026. "#Hint_altfire_rotate_building",
  1027. // Soldier
  1028. "#Hint_Soldier_rpg_reload",
  1029. // Engineer
  1030. "#Hint_Engineer_use_wrench_onown",
  1031. "#Hint_Engineer_use_wrench_onother",
  1032. "#Hint_Engineer_use_wrench_onfriend",
  1033. "#Hint_Engineer_build_sentrygun",
  1034. "#Hint_Engineer_build_dispenser",
  1035. "#Hint_Engineer_build_teleporters",
  1036. "#Hint_Engineer_pickup_metal",
  1037. "#Hint_Engineer_repair_object",
  1038. "#Hint_Engineer_metal_to_upgrade",
  1039. "#Hint_Engineer_upgrade_sentrygun",
  1040. "#Hint_object_has_sapper",
  1041. "#Hint_object_your_object_sapped",
  1042. "#Hint_enemy_using_dispenser",
  1043. "#Hint_enemy_using_tp_entrance",
  1044. "#Hint_enemy_using_tp_exit",
  1045. "#Hint_Cannot_Phase_With_Flag",
  1046. "#Hint_Cannot_Attack_While_Cloaked",
  1047. "#Hint_Cannot_Arm_Feign_Now",
  1048. };
  1049. const char *g_pszArrowModels[] =
  1050. {
  1051. "models/weapons/w_models/w_arrow.mdl",
  1052. "models/weapons/w_models/w_repair_claw.mdl",
  1053. "models/weapons/w_models/w_baseball.mdl",
  1054. "models/weapons/w_models/w_arrow_xmas.mdl",
  1055. "models/weapons/w_models/w_syringe_proj.mdl",
  1056. #ifdef STAGING_ONLY
  1057. "models/workshop/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow_xmas_proj.mdl",
  1058. #else
  1059. "models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow_xmas_proj.mdl",
  1060. #endif
  1061. "models/weapons/w_models/w_breadmonster/w_breadmonster.mdl",
  1062. "models/weapons/c_models/c_grapple_proj/c_grapple_proj.mdl",
  1063. #ifdef STAGING_ONLY
  1064. "models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"
  1065. #else
  1066. "models/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"
  1067. #endif
  1068. };
  1069. COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszArrowModels ) == TF_ARROW_MODEL_COUNT );
  1070. const char *g_pszCampaignMedalIcons[] =
  1071. {
  1072. "",
  1073. // Gun Mettle Campaign
  1074. "../hud/coin_summer2015_gravel",
  1075. "../hud/coin_summer2015_bronze",
  1076. "../hud/coin_summer2015_silver",
  1077. "../hud/coin_summer2015_gold",
  1078. // Invasion Community Update
  1079. "../HUD/scoreboard_invasion",
  1080. // Halloween
  1081. "../HUD/coin_halloween2015_gravel",
  1082. "../HUD/coin_halloween2015_bronze",
  1083. "../HUD/coin_halloween2015_silver",
  1084. "../HUD/coin_halloween2015_gold",
  1085. // Tough Break Campaign
  1086. "../HUD/stamp_winter2016_gravel1",
  1087. "../HUD/stamp_winter2016_bronze1",
  1088. "../HUD/stamp_winter2016_silver1",
  1089. "../HUD/stamp_winter2016_gold1",
  1090. "../HUD/stamp_winter2016_gravel2",
  1091. "../HUD/stamp_winter2016_bronze2",
  1092. "../HUD/stamp_winter2016_silver2",
  1093. "../HUD/stamp_winter2016_gold2",
  1094. };
  1095. COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszCampaignMedalIcons ) == CAMPAIGN_MEDAL_DISPLAY_TYPE_COUNT );
  1096. //-----------------------------------------------------------------------------
  1097. // Dead Calling Cards
  1098. const char *g_pszDeathCallingCardModels[] =
  1099. {
  1100. "", // Empty at zero
  1101. "models/props_gameplay/tombstone_specialdelivery.mdl", // Scout PolyCount Set
  1102. "models/props_gameplay/tombstone_crocostyle.mdl", // Sniper PolyCount Set
  1103. "models/props_gameplay/tombstone_tankbuster.mdl", // Solider PolyCount Set
  1104. "models/props_gameplay/tombstone_gasjockey.mdl", // Pyro PolyCount Set
  1105. };
  1106. //-----------------------------------------------------------------------------
  1107. // Purpose:
  1108. //-----------------------------------------------------------------------------
  1109. int GetWeaponId( const char *pszWeaponName )
  1110. {
  1111. // if this doesn't match, you need to add missing weapons to the array
  1112. COMPILE_TIME_ASSERT( TF_WEAPON_COUNT == ARRAYSIZE( g_aWeaponNames ) );
  1113. for ( int iWeapon = 0; iWeapon < ARRAYSIZE( g_aWeaponNames ); ++iWeapon )
  1114. {
  1115. if ( !Q_stricmp( pszWeaponName, g_aWeaponNames[iWeapon] ) )
  1116. return iWeapon;
  1117. }
  1118. return TF_WEAPON_NONE;
  1119. }
  1120. //-----------------------------------------------------------------------------
  1121. // Purpose:
  1122. //-----------------------------------------------------------------------------
  1123. const char *WeaponIdToAlias( int iWeapon )
  1124. {
  1125. // if this doesn't match, you need to add missing weapons to the array
  1126. COMPILE_TIME_ASSERT( TF_WEAPON_COUNT == ARRAYSIZE( g_aWeaponNames ) );
  1127. if ( ( iWeapon >= ARRAYSIZE( g_aWeaponNames ) ) || ( iWeapon < 0 ) )
  1128. return NULL;
  1129. return g_aWeaponNames[iWeapon];
  1130. }
  1131. #ifdef GAME_DLL
  1132. //-----------------------------------------------------------------------------
  1133. // Purpose:
  1134. //-----------------------------------------------------------------------------
  1135. int GetWeaponFromDamage( const CTakeDamageInfo &info )
  1136. {
  1137. int iWeapon = TF_WEAPON_NONE;
  1138. const char *killer_weapon_name = "";
  1139. // Find the killer & the scorer
  1140. CBaseEntity *pInflictor = info.GetInflictor();
  1141. CBaseEntity *pKiller = info.GetAttacker();
  1142. CBasePlayer *pScorer = TFGameRules()->GetDeathScorer( pKiller, pInflictor, NULL );
  1143. // find the weapon the killer used
  1144. if ( pScorer ) // Is the killer a client?
  1145. {
  1146. if ( pInflictor )
  1147. {
  1148. if ( pInflictor == pScorer )
  1149. {
  1150. // If the inflictor is the killer, then it must be their current weapon doing the damage
  1151. if ( pScorer->GetActiveWeapon() )
  1152. {
  1153. killer_weapon_name = pScorer->GetActiveWeapon()->GetClassname();
  1154. }
  1155. }
  1156. else
  1157. {
  1158. killer_weapon_name = STRING( pInflictor->m_iClassname ); // it's just that easy
  1159. }
  1160. }
  1161. }
  1162. else if ( pInflictor )
  1163. {
  1164. killer_weapon_name = STRING( pInflictor->m_iClassname );
  1165. }
  1166. if ( !Q_strnicmp( killer_weapon_name, "tf_projectile", 13 ) )
  1167. {
  1168. for( int i = 0; i < ARRAYSIZE( g_szProjectileNames ); i++ )
  1169. {
  1170. if ( !Q_stricmp( &killer_weapon_name[ 3 ], g_szProjectileNames[ i ] ) )
  1171. {
  1172. iWeapon = g_iProjectileWeapons[ i ];
  1173. break;
  1174. }
  1175. }
  1176. }
  1177. else
  1178. {
  1179. int iLen = Q_strlen( killer_weapon_name );
  1180. // strip off _projectile from projectiles shot from other projectiles
  1181. if ( ( iLen < 256 ) && ( iLen > 11 ) && !Q_stricmp( &killer_weapon_name[ iLen - 11 ], "_projectile" ) )
  1182. {
  1183. char temp[ 256 ];
  1184. V_strcpy_safe( temp, killer_weapon_name );
  1185. temp[ iLen - 11 ] = 0;
  1186. // set the weapon used
  1187. iWeapon = GetWeaponId( temp );
  1188. }
  1189. else
  1190. {
  1191. // set the weapon used
  1192. iWeapon = GetWeaponId( killer_weapon_name );
  1193. }
  1194. }
  1195. 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." );
  1196. return iWeapon;
  1197. }
  1198. #endif
  1199. // ------------------------------------------------------------------------------------------------ //
  1200. // CObjectInfo tables.
  1201. // ------------------------------------------------------------------------------------------------ //
  1202. CObjectInfo::CObjectInfo( const char *pObjectName )
  1203. {
  1204. m_pObjectName = pObjectName;
  1205. m_pClassName = NULL;
  1206. m_flBuildTime = -9999;
  1207. m_nMaxObjects = -9999;
  1208. m_Cost = -9999;
  1209. m_CostMultiplierPerInstance = -999;
  1210. m_flUpgradeDuration = -999;
  1211. m_UpgradeCost = -9999;
  1212. m_MaxUpgradeLevel = -9999;
  1213. m_pBuilderWeaponName = NULL;
  1214. m_pBuilderPlacementString = NULL;
  1215. m_SelectionSlot = -9999;
  1216. m_SelectionPosition = -9999;
  1217. m_bSolidToPlayerMovement = false;
  1218. m_pIconActive = NULL;
  1219. m_pIconInactive = NULL;
  1220. m_pIconMenu = NULL;
  1221. m_pViewModel = NULL;
  1222. m_pPlayerModel = NULL;
  1223. m_iDisplayPriority = 0;
  1224. m_bVisibleInWeaponSelection = true;
  1225. m_pExplodeSound = NULL;
  1226. m_pUpgradeSound = NULL;
  1227. m_pExplosionParticleEffect = NULL;
  1228. m_bAutoSwitchTo = false;
  1229. m_iBuildCount = 0;
  1230. m_iNumAltModes = 0;
  1231. m_bRequiresOwnBuilder = false;
  1232. }
  1233. CObjectInfo::~CObjectInfo()
  1234. {
  1235. delete [] m_pClassName;
  1236. delete [] m_pStatusName;
  1237. delete [] m_pBuilderWeaponName;
  1238. delete [] m_pBuilderPlacementString;
  1239. delete [] m_pIconActive;
  1240. delete [] m_pIconInactive;
  1241. delete [] m_pIconMenu;
  1242. delete [] m_pViewModel;
  1243. delete [] m_pPlayerModel;
  1244. delete [] m_pExplodeSound;
  1245. delete [] m_pUpgradeSound;
  1246. delete [] m_pExplosionParticleEffect;
  1247. }
  1248. CObjectInfo g_ObjectInfos[OBJ_LAST] =
  1249. {
  1250. CObjectInfo( "OBJ_DISPENSER" ),
  1251. CObjectInfo( "OBJ_TELEPORTER" ),
  1252. CObjectInfo( "OBJ_SENTRYGUN" ),
  1253. CObjectInfo( "OBJ_ATTACHMENT_SAPPER" ),
  1254. #ifdef STAGING_ONLY
  1255. CObjectInfo( "OBJ_CATAPULT" ),
  1256. CObjectInfo( "OBJ_SPY_TRAP" ),
  1257. #endif
  1258. };
  1259. COMPILE_TIME_ASSERT( ARRAYSIZE( g_ObjectInfos ) == OBJ_LAST );
  1260. //-----------------------------------------------------------------------------
  1261. // Purpose:
  1262. //-----------------------------------------------------------------------------
  1263. int GetBuildableId( const char *pszBuildableName )
  1264. {
  1265. for ( int iBuildable = 0; iBuildable < OBJ_LAST; ++iBuildable )
  1266. {
  1267. if ( !Q_stricmp( pszBuildableName, g_ObjectInfos[iBuildable].m_pObjectName ) )
  1268. return iBuildable;
  1269. }
  1270. return OBJ_LAST;
  1271. }
  1272. bool AreObjectInfosLoaded()
  1273. {
  1274. return g_ObjectInfos[0].m_pClassName != NULL;
  1275. }
  1276. static void SpewFileInfo( IBaseFileSystem *pFileSystem, const char *resourceName, const char *pathID, KeyValues *pValues )
  1277. {
  1278. bool bFileExists = pFileSystem->FileExists( resourceName, pathID );
  1279. bool bFileWritable = pFileSystem->IsFileWritable( resourceName, pathID );
  1280. unsigned int nSize = pFileSystem->Size( resourceName, pathID );
  1281. Msg( "resourceName:%s pathID:%s bFileExists:%d size:%u writeable:%d\n", resourceName, pathID, bFileExists, nSize, bFileWritable );
  1282. unsigned int filesize = ( unsigned int )-1;
  1283. FileHandle_t f = filesystem->Open( resourceName, "rb", pathID );
  1284. if ( f )
  1285. {
  1286. filesize = filesystem->Size( f );
  1287. filesystem->Close( f );
  1288. }
  1289. Msg( " FileHandle_t:%p size:%u\n", f, filesize );
  1290. IFileSystem *pFS = (IFileSystem *)filesystem;
  1291. char cwd[ MAX_PATH ];
  1292. cwd[ 0 ] = 0;
  1293. pFS->GetCurrentDirectory( cwd, ARRAYSIZE( cwd ) );
  1294. bool bAvailable = pFS->IsFileImmediatelyAvailable( resourceName );
  1295. Msg( " IsFileImmediatelyAvailable:%d cwd:%s\n", bAvailable, cwd );
  1296. pFS->PrintSearchPaths();
  1297. if ( pValues )
  1298. {
  1299. Msg( "Keys:" );
  1300. KeyValuesDumpAsDevMsg( pValues, 2, 0 );
  1301. }
  1302. }
  1303. void LoadObjectInfos( IBaseFileSystem *pFileSystem )
  1304. {
  1305. const char *pFilename = "scripts/objects.txt";
  1306. // Make sure this stuff hasn't already been loaded.
  1307. Assert( !AreObjectInfosLoaded() );
  1308. KeyValues *pValues = new KeyValues( "Object descriptions" );
  1309. if ( !pValues->LoadFromFile( pFileSystem, pFilename, "GAME" ) )
  1310. {
  1311. // Getting "Can't open scripts/objects.txt for object info." errors. Spew file information
  1312. // before the Error() call which should show up in the minidumps.
  1313. SpewFileInfo( pFileSystem, pFilename, "GAME", NULL );
  1314. Error( "Can't open %s for object info.", pFilename );
  1315. pValues->deleteThis();
  1316. return;
  1317. }
  1318. // Now read each class's information in.
  1319. for ( int iObj=0; iObj < ARRAYSIZE( g_ObjectInfos ); iObj++ )
  1320. {
  1321. CObjectInfo *pInfo = &g_ObjectInfos[iObj];
  1322. KeyValues *pSub = pValues->FindKey( pInfo->m_pObjectName );
  1323. if ( !pSub )
  1324. {
  1325. // Getting "Missing section 'OBJ_DISPENSER' from scripts/objects.txt" errors.
  1326. SpewFileInfo( pFileSystem, pFilename, "GAME", pValues );
  1327. // It seems that folks have corrupt files when these errors are seen in http://minidump.
  1328. // Does it make sense to call the below Steam API so it'll force a validation next startup time?
  1329. // Need to verify it's real corruption and not someone dorking around with their objects.txt file...
  1330. //
  1331. // From Martin Otten: If you have a file on disc and you�re 100% sure it�s
  1332. // corrupt, call ISteamApps::MarkContentCorrupt( false ), before you shutdown
  1333. // the game. This will cause a content validation in Steam.
  1334. Error( "Missing section '%s' from %s.", pInfo->m_pObjectName, pFilename );
  1335. pValues->deleteThis();
  1336. return;
  1337. }
  1338. // Read all the info in.
  1339. if ( (pInfo->m_flBuildTime = pSub->GetFloat( "BuildTime", -999 )) == -999 ||
  1340. (pInfo->m_nMaxObjects = pSub->GetInt( "MaxObjects", -999 )) == -999 ||
  1341. (pInfo->m_Cost = pSub->GetInt( "Cost", -999 )) == -999 ||
  1342. (pInfo->m_CostMultiplierPerInstance = pSub->GetFloat( "CostMultiplier", -999 )) == -999 ||
  1343. (pInfo->m_flUpgradeDuration = pSub->GetFloat( "UpgradeDuration", -999 )) == -999 ||
  1344. (pInfo->m_UpgradeCost = pSub->GetInt( "UpgradeCost", -999 )) == -999 ||
  1345. (pInfo->m_MaxUpgradeLevel = pSub->GetInt( "MaxUpgradeLevel", -999 )) == -999 ||
  1346. (pInfo->m_SelectionSlot = pSub->GetInt( "SelectionSlot", -999 )) == -999 ||
  1347. (pInfo->m_iBuildCount = pSub->GetInt( "BuildCount", -999 )) == -999 ||
  1348. (pInfo->m_SelectionPosition = pSub->GetInt( "SelectionPosition", -999 )) == -999 )
  1349. {
  1350. SpewFileInfo( pFileSystem, pFilename, "GAME", pValues );
  1351. Error( "Missing data for object '%s' in %s.", pInfo->m_pObjectName, pFilename );
  1352. pValues->deleteThis();
  1353. return;
  1354. }
  1355. pInfo->m_pClassName = ReadAndAllocStringValue( pSub, "ClassName", pFilename );
  1356. pInfo->m_pStatusName = ReadAndAllocStringValue( pSub, "StatusName", pFilename );
  1357. pInfo->m_pBuilderWeaponName = ReadAndAllocStringValue( pSub, "BuilderWeaponName", pFilename );
  1358. pInfo->m_pBuilderPlacementString = ReadAndAllocStringValue( pSub, "BuilderPlacementString", pFilename );
  1359. pInfo->m_bSolidToPlayerMovement = pSub->GetInt( "SolidToPlayerMovement", 0 ) ? true : false;
  1360. pInfo->m_pIconActive = ReadAndAllocStringValue( pSub, "IconActive", pFilename );
  1361. pInfo->m_pIconInactive = ReadAndAllocStringValue( pSub, "IconInactive", pFilename );
  1362. pInfo->m_pIconMenu = ReadAndAllocStringValue( pSub, "IconMenu", pFilename );
  1363. pInfo->m_bUseItemInfo = ( pSub->GetInt( "UseItemInfo", 0 ) > 0 );
  1364. pInfo->m_pViewModel = ReadAndAllocStringValue( pSub, "Viewmodel", pFilename );
  1365. pInfo->m_pPlayerModel = ReadAndAllocStringValue( pSub, "Playermodel", pFilename );
  1366. pInfo->m_iDisplayPriority = pSub->GetInt( "DisplayPriority", 0 );
  1367. pInfo->m_pHudStatusIcon = ReadAndAllocStringValue( pSub, "HudStatusIcon", pFilename );
  1368. pInfo->m_bVisibleInWeaponSelection = ( pSub->GetInt( "VisibleInWeaponSelection", 1 ) > 0 );
  1369. pInfo->m_pExplodeSound = ReadAndAllocStringValue( pSub, "ExplodeSound", pFilename );
  1370. pInfo->m_pUpgradeSound = ReadAndAllocStringValue( pSub, "UpgradeSound", pFilename );
  1371. pInfo->m_pExplosionParticleEffect = ReadAndAllocStringValue( pSub, "ExplodeEffect", pFilename );
  1372. pInfo->m_bAutoSwitchTo = ( pSub->GetInt( "autoswitchto", 0 ) > 0 );
  1373. pInfo->m_iMetalToDropInGibs = pSub->GetInt( "MetalToDropInGibs", 0 );
  1374. pInfo->m_bRequiresOwnBuilder = pSub->GetBool( "RequiresOwnBuilder", 0 );
  1375. // Read the other alternate object modes.
  1376. KeyValues *pAltModesKey = pSub->FindKey( "AltModes" );
  1377. if ( pAltModesKey )
  1378. {
  1379. int iIndex = 0;
  1380. while ( iIndex<OBJECT_MAX_MODES )
  1381. {
  1382. char buf[256];
  1383. Q_snprintf( buf, sizeof(buf), "AltMode%d", iIndex );
  1384. KeyValues *pCurrentModeKey = pAltModesKey->FindKey( buf );
  1385. if ( !pCurrentModeKey )
  1386. break;
  1387. pInfo->m_AltModes[iIndex].pszStatusName = ReadAndAllocStringValue( pCurrentModeKey, "StatusName", pFilename );
  1388. pInfo->m_AltModes[iIndex].pszModeName = ReadAndAllocStringValue( pCurrentModeKey, "ModeName", pFilename );
  1389. pInfo->m_AltModes[iIndex].pszIconMenu = ReadAndAllocStringValue( pCurrentModeKey, "IconMenu", pFilename );
  1390. iIndex++;
  1391. }
  1392. pInfo->m_iNumAltModes = iIndex-1;
  1393. }
  1394. // Alternate mode 0 always matches the defaults.
  1395. pInfo->m_AltModes[0].pszStatusName = pInfo->m_pStatusName;
  1396. pInfo->m_AltModes[0].pszIconMenu = pInfo->m_pIconMenu;
  1397. }
  1398. pValues->deleteThis();
  1399. }
  1400. const CObjectInfo* GetObjectInfo( int iObject )
  1401. {
  1402. Assert( iObject >= 0 && iObject < OBJ_LAST );
  1403. Assert( AreObjectInfosLoaded() );
  1404. return &g_ObjectInfos[iObject];
  1405. }
  1406. ConVar tf_cheapobjects( "tf_cheapobjects","0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Set to 1 and all objects will cost 0" );
  1407. //-----------------------------------------------------------------------------
  1408. // Purpose: Return the cost of another object of the specified type
  1409. // If bLast is set, return the cost of the last built object of the specified type
  1410. //
  1411. // Note: Used to contain logic from tf2 that multiple instances of the same object
  1412. // cost different amounts. See tf2/game_shared/tf_shareddefs.cpp for details
  1413. //-----------------------------------------------------------------------------
  1414. int InternalCalculateObjectCost( int iObjectType )
  1415. {
  1416. if ( tf_cheapobjects.GetInt() )
  1417. {
  1418. return 0;
  1419. }
  1420. int iCost = GetObjectInfo( iObjectType )->m_Cost;
  1421. return iCost;
  1422. }
  1423. //-----------------------------------------------------------------------------
  1424. // Purpose: Calculate the cost to upgrade an object of a specific type
  1425. //-----------------------------------------------------------------------------
  1426. int CalculateObjectUpgrade( int iObjectType, int iObjectLevel )
  1427. {
  1428. // Max level?
  1429. if ( iObjectLevel >= GetObjectInfo( iObjectType )->m_MaxUpgradeLevel )
  1430. return 0;
  1431. int iCost = GetObjectInfo( iObjectType )->m_UpgradeCost;
  1432. for ( int i = 0; i < (iObjectLevel - 1); i++ )
  1433. {
  1434. iCost *= OBJECT_UPGRADE_COST_MULTIPLIER_PER_LEVEL;
  1435. }
  1436. return iCost;
  1437. }
  1438. //-----------------------------------------------------------------------------
  1439. // Purpose: Return true if the specified class is allowed to build the specified object type
  1440. //-----------------------------------------------------------------------------
  1441. bool ClassCanBuild( int iClass, int iObjectType )
  1442. {
  1443. /*
  1444. for ( int i = 0; i < OBJ_LAST; i++ )
  1445. {
  1446. // Hit the end?
  1447. if ( g_TFClassInfos[iClass].m_pClassObjects[i] == OBJ_LAST )
  1448. return false;
  1449. // Found it?
  1450. if ( g_TFClassInfos[iClass].m_pClassObjects[i] == iObjectType )
  1451. return true;
  1452. }
  1453. return false;
  1454. */
  1455. return ( iClass == TF_CLASS_ENGINEER );
  1456. }
  1457. const unsigned char *GetTFEncryptionKey( void )
  1458. {
  1459. return (unsigned char *)"E2NcUkG2";
  1460. }
  1461. //-----------------------------------------------------------------------------
  1462. // Per-class weapon entity translations
  1463. //-----------------------------------------------------------------------------
  1464. struct wpntranslation_class_weapons_t
  1465. {
  1466. const char *pszWpnString;
  1467. const char *pszClassWpn[TF_LAST_NORMAL_CLASS];
  1468. };
  1469. wpntranslation_class_weapons_t pszWpnEntTranslationList[] =
  1470. {
  1471. {
  1472. "tf_weapon_shotgun",
  1473. {
  1474. "", // TF_CLASS_UNDEFINED = 0,
  1475. "", // TF_CLASS_SCOUT,
  1476. "", // TF_CLASS_SNIPER,
  1477. "tf_weapon_shotgun_soldier",// TF_CLASS_SOLDIER,
  1478. "", // TF_CLASS_DEMOMAN,
  1479. "", // TF_CLASS_MEDIC,
  1480. "tf_weapon_shotgun_hwg", // TF_CLASS_HEAVYWEAPONS,
  1481. "tf_weapon_shotgun_pyro", // TF_CLASS_PYRO,
  1482. "", // TF_CLASS_SPY,
  1483. "tf_weapon_shotgun_primary",// TF_CLASS_ENGINEER,
  1484. }
  1485. },
  1486. {
  1487. "tf_weapon_pistol",
  1488. {
  1489. "", // TF_CLASS_UNDEFINED = 0,
  1490. "tf_weapon_pistol_scout", // TF_CLASS_SCOUT,
  1491. "", // TF_CLASS_SNIPER,
  1492. "", // TF_CLASS_SOLDIER,
  1493. "", // TF_CLASS_DEMOMAN,
  1494. "", // TF_CLASS_MEDIC,
  1495. "", // TF_CLASS_HEAVYWEAPONS,
  1496. "", // TF_CLASS_PYRO,
  1497. "", // TF_CLASS_SPY,
  1498. "tf_weapon_pistol", // TF_CLASS_ENGINEER,
  1499. }
  1500. },
  1501. {
  1502. "tf_weapon_shovel",
  1503. {
  1504. "", // TF_CLASS_UNDEFINED = 0,
  1505. "", // TF_CLASS_SCOUT,
  1506. "", // TF_CLASS_SNIPER,
  1507. "tf_weapon_shovel", // TF_CLASS_SOLDIER,
  1508. "tf_weapon_bottle", // TF_CLASS_DEMOMAN,
  1509. "", // TF_CLASS_MEDIC,
  1510. "", // TF_CLASS_HEAVYWEAPONS,
  1511. "", // TF_CLASS_PYRO,
  1512. "", // TF_CLASS_SPY,
  1513. "", // TF_CLASS_ENGINEER,
  1514. }
  1515. },
  1516. {
  1517. "tf_weapon_bottle",
  1518. {
  1519. "", // TF_CLASS_UNDEFINED = 0,
  1520. "", // TF_CLASS_SCOUT,
  1521. "", // TF_CLASS_SNIPER,
  1522. "tf_weapon_shovel", // TF_CLASS_SOLDIER,
  1523. "tf_weapon_bottle", // TF_CLASS_DEMOMAN,
  1524. "", // TF_CLASS_MEDIC,
  1525. "", // TF_CLASS_HEAVYWEAPONS,
  1526. "", // TF_CLASS_PYRO,
  1527. "", // TF_CLASS_SPY,
  1528. "", // TF_CLASS_ENGINEER,
  1529. }
  1530. },
  1531. {
  1532. "saxxy",
  1533. {
  1534. "", // TF_CLASS_UNDEFINED = 0,
  1535. "tf_weapon_bat", // TF_CLASS_SCOUT,
  1536. "tf_weapon_club", // TF_CLASS_SNIPER,
  1537. "tf_weapon_shovel", // TF_CLASS_SOLDIER,
  1538. "tf_weapon_bottle", // TF_CLASS_DEMOMAN,
  1539. "tf_weapon_bonesaw", // TF_CLASS_MEDIC,
  1540. "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
  1541. "tf_weapon_fireaxe", // TF_CLASS_PYRO,
  1542. "tf_weapon_knife", // TF_CLASS_SPY,
  1543. "tf_weapon_wrench", // TF_CLASS_ENGINEER,
  1544. }
  1545. },
  1546. {
  1547. "tf_weapon_throwable",
  1548. {
  1549. "", // TF_CLASS_UNDEFINED = 0,
  1550. "tf_weapon_throwable_secondary", // TF_CLASS_SCOUT,
  1551. "tf_weapon_throwable_secondary", // TF_CLASS_SNIPER,
  1552. "tf_weapon_throwable_secondary", // TF_CLASS_SOLDIER,
  1553. "tf_weapon_throwable_secondary", // TF_CLASS_DEMOMAN,
  1554. "tf_weapon_throwable_primary", // TF_CLASS_MEDIC,
  1555. "tf_weapon_throwable_secondary", // TF_CLASS_HEAVYWEAPONS
  1556. "tf_weapon_throwable_secondary", // TF_CLASS_PYRO,
  1557. "tf_weapon_throwable_secondary", // TF_CLASS_SPY,
  1558. "tf_weapon_throwable_secondary", // TF_CLASS_ENGINEER,
  1559. }
  1560. },
  1561. {
  1562. "tf_weapon_parachute",
  1563. {
  1564. "", // TF_CLASS_UNDEFINED = 0,
  1565. "", // TF_CLASS_SCOUT,
  1566. "", // TF_CLASS_SNIPER,
  1567. "tf_weapon_parachute_secondary", // TF_CLASS_SOLDIER,
  1568. "tf_weapon_parachute_primary", // TF_CLASS_DEMOMAN,
  1569. "", // TF_CLASS_MEDIC,
  1570. "", // TF_CLASS_HEAVYWEAPONS
  1571. "", // TF_CLASS_PYRO,
  1572. "" // TF_CLASS_SPY,
  1573. "", // TF_CLASS_ENGINEER,
  1574. }
  1575. },
  1576. {
  1577. "tf_weapon_revolver",
  1578. {
  1579. "", // TF_CLASS_UNDEFINED = 0,
  1580. "", // TF_CLASS_SCOUT,
  1581. "", // TF_CLASS_SNIPER,
  1582. "", // TF_CLASS_SOLDIER,
  1583. "", // TF_CLASS_DEMOMAN,
  1584. "", // TF_CLASS_MEDIC,
  1585. "", // TF_CLASS_HEAVYWEAPONS
  1586. "", // TF_CLASS_PYRO,
  1587. "tf_weapon_revolver", // TF_CLASS_SPY,
  1588. "tf_weapon_revolver_secondary", // TF_CLASS_ENGINEER,
  1589. }
  1590. },
  1591. };
  1592. //-----------------------------------------------------------------------------
  1593. // Purpose: We need to support players putting any shotgun into a shotgun slot, pistol into a pistol slot, etc.
  1594. // For legacy reasons, different classes actually spawn different entities for their shotguns/pistols/etc.
  1595. // To deal with this, we translate entities into the right one for the class we're playing.
  1596. //-----------------------------------------------------------------------------
  1597. const char *TranslateWeaponEntForClass( const char *pszName, int iClass )
  1598. {
  1599. if ( pszName )
  1600. {
  1601. for ( int i = 0; i < ARRAYSIZE(pszWpnEntTranslationList); i++ )
  1602. {
  1603. if ( !Q_stricmp( pszName, pszWpnEntTranslationList[i].pszWpnString ) )
  1604. {
  1605. const char *pTransName = pszWpnEntTranslationList[i].pszClassWpn[ iClass ];
  1606. Assert( pTransName && pTransName[0] );
  1607. return pTransName;
  1608. }
  1609. }
  1610. }
  1611. return pszName;
  1612. }
  1613. //-----------------------------------------------------------------------------
  1614. // Helltower Announcer lines for Redmond and Blutarch
  1615. //-----------------------------------------------------------------------------
  1616. helltower_vo_t g_pszHelltowerAnnouncerLines[] =
  1617. {
  1618. // EACH MISC PAIR SHOULD HAVE THE SAME NUMBER OF LINES
  1619. { "Announcer.Helltower_Red_Misc%02u", 16 },
  1620. { "Announcer.Helltower_Blue_Misc%02u", 16 },
  1621. { "Announcer.Helltower_Red_Misc_Rare%02u", 21 },
  1622. { "Announcer.Helltower_Blue_Misc_Rare%02u", 21 },
  1623. // THESE PAIRS CAN HAVE DIFFERENT COUNTS
  1624. { "Announcer.Helltower_Red_Winning%02u", 12 },
  1625. { "Announcer.Helltower_Blue_Winning%02u", 13 },
  1626. { "Announcer.Helltower_Red_Winning_Rare%02u", 12 },
  1627. { "Announcer.Helltower_Blue_Winning_Rare%02u", 8 },
  1628. { "Announcer.Helltower_Red_Losing%02u", 15 },
  1629. { "Announcer.Helltower_Blue_Losing%02u", 16 },
  1630. { "Announcer.Helltower_Red_Losing_Rare%02u", 6 },
  1631. { "Announcer.Helltower_Blue_Losing_Rare%02u", 5 },
  1632. { "Announcer.Helltower_Red_Win%02u", 7 },
  1633. { "Announcer.Helltower_Blue_Win%02u", 7 },
  1634. { "Announcer.Helltower_Red_Win_Rare%02u", 1 },
  1635. { "Announcer.Helltower_Blue_Win_Rare%02u", 3 },
  1636. { "Announcer.Helltower_Red_Lose%02u", 7 },
  1637. { "Announcer.Helltower_Blue_Lose%02u", 7 },
  1638. { "Announcer.Helltower_Red_Lose_Rare%02u", 1 },
  1639. { "Announcer.Helltower_Blue_Lose_Rare%02u", 1 },
  1640. { "Announcer.Helltower_Red_RoundStart%02u", 4 },
  1641. { "Announcer.Helltower_Blue_RoundStart%02u", 2 },
  1642. { "Announcer.Helltower_Red_RoundStart_Rare%02u", 4 },
  1643. { "Announcer.Helltower_Blue_RoundStart_Rare%02u", 2 },
  1644. { "Announcer.Helltower_Red_Skeleton_King%02u", 4 },
  1645. { "Announcer.Helltower_Blue_Skeleton_King%02u", 4 },
  1646. { "Announcer.Helltower_Red_Almost_Win%02u", 1 },
  1647. { "Announcer.Helltower_Blue_Almost_Win%02u", 1 },
  1648. { "Announcer.Helltower_Red_Almost_Lose%02u", 1 },
  1649. { "Announcer.Helltower_Blue_Almost_Lose%02u", 1 },
  1650. };
  1651. #ifdef TF_CLIENT_DLL
  1652. //-----------------------------------------------------------------------------
  1653. //
  1654. //-----------------------------------------------------------------------------
  1655. const char *g_pszInvasionMaps[] =
  1656. {
  1657. "maps/ctf_2fort_invasion.bsp",
  1658. "maps/koth_probed.bsp",
  1659. "maps/arena_byre.bsp",
  1660. "maps/pd_watergate.bsp"
  1661. };
  1662. bool IsPlayingInvasionMap( void )
  1663. {
  1664. const char *pszCurrentMap = engine->GetLevelName();
  1665. for ( int i = 0; i < ARRAYSIZE( g_pszInvasionMaps ); i++ )
  1666. {
  1667. if ( FStrEq( g_pszInvasionMaps[i], pszCurrentMap ) )
  1668. return true;
  1669. }
  1670. return false;
  1671. }
  1672. const char *g_pszClassIcons[SCOREBOARD_CLASS_ICONS] =
  1673. {
  1674. "",
  1675. "../hud/leaderboard_class_scout",
  1676. "../hud/leaderboard_class_sniper",
  1677. "../hud/leaderboard_class_soldier",
  1678. "../hud/leaderboard_class_demo",
  1679. "../hud/leaderboard_class_medic",
  1680. "../hud/leaderboard_class_heavy",
  1681. "../hud/leaderboard_class_pyro",
  1682. "../hud/leaderboard_class_spy",
  1683. "../hud/leaderboard_class_engineer",
  1684. "../hud/leaderboard_class_scout_d",
  1685. "../hud/leaderboard_class_sniper_d",
  1686. "../hud/leaderboard_class_soldier_d",
  1687. "../hud/leaderboard_class_demo_d",
  1688. "../hud/leaderboard_class_medic_d",
  1689. "../hud/leaderboard_class_heavy_d",
  1690. "../hud/leaderboard_class_pyro_d",
  1691. "../hud/leaderboard_class_spy_d",
  1692. "../hud/leaderboard_class_engineer_d",
  1693. };
  1694. const char *g_pszClassIconsAlt[SCOREBOARD_CLASS_ICONS] =
  1695. {
  1696. "",
  1697. "class_icons/class_icon_orange_scout",
  1698. "class_icons/class_icon_orange_sniper",
  1699. "class_icons/class_icon_orange_soldier",
  1700. "class_icons/class_icon_orange_demo",
  1701. "class_icons/class_icon_orange_medic",
  1702. "class_icons/class_icon_orange_heavy",
  1703. "class_icons/class_icon_orange_pyro",
  1704. "class_icons/class_icon_orange_spy",
  1705. "class_icons/class_icon_orange_engineer",
  1706. "class_icons/class_icon_orange_scout_d",
  1707. "class_icons/class_icon_orange_sniper_d",
  1708. "class_icons/class_icon_orange_soldier_d",
  1709. "class_icons/class_icon_orange_demo_d",
  1710. "class_icons/class_icon_orange_medic_d",
  1711. "class_icons/class_icon_orange_heavy_d",
  1712. "class_icons/class_icon_orange_pyro_d",
  1713. "class_icons/class_icon_orange_spy_d",
  1714. "class_icons/class_icon_orange_engineer_d",
  1715. };
  1716. const char *g_pszItemClassImagesRed[] =
  1717. {
  1718. "class_portraits/all_class", // TF_CLASS_UNDEFINED = 0,
  1719. "class_portraits/scout", // TF_CLASS_SCOUT,
  1720. "class_portraits/sniper", // TF_CLASS_SNIPER,
  1721. "class_portraits/soldier", // TF_CLASS_SOLDIER,
  1722. "class_portraits/demoman", // TF_CLASS_DEMOMAN,
  1723. "class_portraits/medic", // TF_CLASS_MEDIC,
  1724. "class_portraits/heavy", // TF_CLASS_HEAVYWEAPONS,
  1725. "class_portraits/pyro", // TF_CLASS_PYRO,
  1726. "class_portraits/spy", // TF_CLASS_SPY,
  1727. "class_portraits/engineer", // TF_CLASS_ENGINEER,
  1728. "class_portraits/scout_grey", // TF_CLASS_SCOUT,
  1729. "class_portraits/sniper_grey", // TF_CLASS_SNIPER,
  1730. "class_portraits/soldier_grey", // TF_CLASS_SOLDIER,
  1731. "class_portraits/demoman_grey", // TF_CLASS_DEMOMAN,
  1732. "class_portraits/medic_grey", // TF_CLASS_MEDIC,
  1733. "class_portraits/heavy_grey", // TF_CLASS_HEAVYWEAPONS,
  1734. "class_portraits/pyro_grey", // TF_CLASS_PYRO,
  1735. "class_portraits/spy_grey", // TF_CLASS_SPY,
  1736. "class_portraits/engineer_grey", // TF_CLASS_ENGINEER,
  1737. };
  1738. const char *g_pszItemClassImagesBlue[] =
  1739. {
  1740. "class_portraits/all_class", // TF_CLASS_UNDEFINED = 0,
  1741. "class_portraits/scout_blue", // TF_CLASS_SCOUT,
  1742. "class_portraits/sniper_blue", // TF_CLASS_SNIPER,
  1743. "class_portraits/soldier_blue", // TF_CLASS_SOLDIER,
  1744. "class_portraits/demoman_blue", // TF_CLASS_DEMOMAN,
  1745. "class_portraits/medic_blue", // TF_CLASS_MEDIC,
  1746. "class_portraits/heavy_blue", // TF_CLASS_HEAVYWEAPONS,
  1747. "class_portraits/pyro_blue", // TF_CLASS_PYRO,
  1748. "class_portraits/spy_blue", // TF_CLASS_SPY,
  1749. "class_portraits/engineer_blue", // TF_CLASS_ENGINEER,
  1750. "class_portraits/scout_blue_grey", // TF_CLASS_SCOUT,
  1751. "class_portraits/sniper_blue_grey", // TF_CLASS_SNIPER,
  1752. "class_portraits/soldier_blue_grey", // TF_CLASS_SOLDIER,
  1753. "class_portraits/demoman_blue_grey", // TF_CLASS_DEMOMAN,
  1754. "class_portraits/medic_blue_grey", // TF_CLASS_MEDIC,
  1755. "class_portraits/heavy_blue_grey", // TF_CLASS_HEAVYWEAPONS,
  1756. "class_portraits/pyro_blue_grey", // TF_CLASS_PYRO,
  1757. "class_portraits/spy_blue_grey", // TF_CLASS_SPY,
  1758. "class_portraits/engineer_blue_grey", // TF_CLASS_ENGINEER,
  1759. };
  1760. const char *g_pszCompetitiveMedalImages[] =
  1761. {
  1762. "",
  1763. "competitive/competitive_coin_bronze",
  1764. "competitive/competitive_coin_silver",
  1765. "competitive/competitive_coin_gold",
  1766. };
  1767. COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszCompetitiveMedalImages ) == StatMedal_Max );
  1768. #endif // TF_CLIENT_DLL
  1769. // rune icons for each team
  1770. static const char *s_pszRuneIcons[2][RUNE_TYPES_MAX] =
  1771. {
  1772. // RED TEAM
  1773. {
  1774. "powerup_icon_strength_red",
  1775. "powerup_icon_haste_red",
  1776. "powerup_icon_regen_red",
  1777. "powerup_icon_resist_red",
  1778. "powerup_icon_vampire_red",
  1779. "powerup_icon_reflect_red",
  1780. "powerup_icon_precision_red",
  1781. "powerup_icon_agility_red",
  1782. "powerup_icon_knockout_red",
  1783. "powerup_icon_king_red",
  1784. "powerup_icon_plague_red",
  1785. "powerup_icon_supernova_red",
  1786. },
  1787. // BLUE TEAM
  1788. {
  1789. "powerup_icon_strength_blue",
  1790. "powerup_icon_haste_blue",
  1791. "powerup_icon_regen_blue",
  1792. "powerup_icon_resist_blue",
  1793. "powerup_icon_vampire_blue",
  1794. "powerup_icon_reflect_blue",
  1795. "powerup_icon_precision_blue",
  1796. "powerup_icon_agility_blue",
  1797. "powerup_icon_knockout_blue",
  1798. "powerup_icon_king_blue",
  1799. "powerup_icon_plague_blue",
  1800. "powerup_icon_supernova_blue",
  1801. }
  1802. };
  1803. COMPILE_TIME_ASSERT( ARRAYSIZE( s_pszRuneIcons[0] ) == RUNE_TYPES_MAX );
  1804. COMPILE_TIME_ASSERT( ARRAYSIZE( s_pszRuneIcons[1] ) == RUNE_TYPES_MAX );
  1805. const char *GetPowerupIconName( RuneTypes_t type, int iTeam )
  1806. {
  1807. int iTeamIndex = iTeam == TF_TEAM_RED ? 0 : 1;
  1808. if ( type != RUNE_NONE && type < RUNE_TYPES_MAX )
  1809. {
  1810. return s_pszRuneIcons[ iTeamIndex ][ type ];
  1811. }
  1812. return NULL;
  1813. }