/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”). Wolf ET Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wolf ET Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ /* * name: bg_misc.c * * desc: both games misc functions, all completely stateless * */ #include "q_shared.h" #include "bg_public.h" #include "../../etmain/ui/menudef.h" #ifdef CGAMEDLL extern vmCvar_t cg_gameType; #define gametypeCvar cg_gameType #elif GAMEDLL extern vmCvar_t g_developer; extern vmCvar_t g_gametype; #define gametypeCvar g_gametype #else extern vmCvar_t ui_gameType; #define gametypeCvar ui_gameType #endif #define BG_IsSinglePlayerGame() ( gametypeCvar.integer == GT_SINGLE_PLAYER ) || ( gametypeCvar.integer == GT_COOP ) const char* skillNames[SK_NUM_SKILLS] = { "Battle Sense", "Engineering", "First Aid", "Signals", "Light Weapons", "Heavy Weapons", "Covert Ops" }; const char* skillNamesLine1[SK_NUM_SKILLS] = { "Battle", "Engineering", "First", "Signals", "Light", "Heavy", "Covert" }; const char* skillNamesLine2[SK_NUM_SKILLS] = { "Sense", "", "Aid", "", "Weapons", "Weapons", "Ops" }; const char* medalNames[SK_NUM_SKILLS] = { "Distinguished Service Medal", "Steel Star", "Silver Cross", "Signals Medal", "Infantry Medal", "Bombardment Medal", "Silver Snake" }; const int skillLevels[NUM_SKILL_LEVELS] = { 0, // reaching level 0 20, // reaching level 1 50, // reaching level 2 90, // reaching level 3 140 // reaching level 4 // 200 // reaching level 5 }; vec3_t playerlegsProneMins = { -13.5f, -13.5f, -24.f }; vec3_t playerlegsProneMaxs = { 13.5f, 13.5f, -14.4f }; int numSplinePaths; splinePath_t splinePaths[MAX_SPLINE_PATHS]; int numPathCorners; pathCorner_t pathCorners[MAX_PATH_CORNERS]; // these defines are matched with the character torso animations #define DELAY_LOW 100 // machineguns, tesla, spear, flame #define DELAY_HIGH 100 // mauser, garand #define DELAY_PISTOL 100 // colt, luger, sp5, cross #define DELAY_SHOULDER 50 // rl #define DELAY_THROW 250 // grenades, dynamite // Arnout: the new loadout for WolfXP int weapBanksMultiPlayer[MAX_WEAP_BANKS_MP][MAX_WEAPS_IN_BANK_MP] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // empty bank '0' {WP_KNIFE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, {WP_LUGER, WP_COLT, WP_AKIMBO_COLT, WP_AKIMBO_LUGER, WP_AKIMBO_SILENCEDCOLT, WP_AKIMBO_SILENCEDLUGER, 0, 0, 0, 0, 0, 0 }, {WP_MP40, WP_THOMPSON, WP_STEN, WP_GARAND, WP_PANZERFAUST, WP_FLAMETHROWER, WP_KAR98, WP_CARBINE, WP_FG42, WP_K43, WP_MOBILE_MG42, WP_MORTAR }, {WP_GRENADE_LAUNCHER, WP_GRENADE_PINEAPPLE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, {WP_MEDIC_SYRINGE, WP_PLIERS, WP_SMOKE_MARKER, WP_SMOKE_BOMB, 0, 0, 0, 0, 0, 0, 0, 0, }, {WP_DYNAMITE, WP_MEDKIT, WP_AMMO, WP_SATCHEL, WP_SATCHEL_DET, 0, 0, 0, 0, 0, 0, 0 }, {WP_LANDMINE, WP_MEDIC_ADRENALINE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, {WP_BINOCULARS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; // TAT 10/4/2002 // Using one unified list for which weapons can received ammo // This is used both by the ammo pack code and by the bot code to determine if reloads are needed int reloadableWeapons[] = { WP_MP40, WP_THOMPSON, WP_STEN, WP_GARAND, WP_PANZERFAUST, WP_FLAMETHROWER, WP_KAR98, WP_CARBINE, WP_FG42, WP_K43, WP_MOBILE_MG42, WP_COLT, WP_LUGER, WP_MORTAR, WP_AKIMBO_COLT, WP_AKIMBO_LUGER, WP_M7, WP_GPG40, WP_AKIMBO_SILENCEDCOLT, WP_AKIMBO_SILENCEDLUGER, -1 }; // [0] = maxammo - max player ammo carrying capacity. // [1] = uses - how many 'rounds' it takes/costs to fire one cycle. // [2] = maxclip - max 'rounds' in a clip. // [3] = reloadTime - time from start of reload until ready to fire. // [4] = fireDelayTime - time from pressing 'fire' until first shot is fired. (used for delaying fire while weapon is 'readied' in animation) // [5] = nextShotTime - when firing continuously, this is the time between shots // [6] = maxHeat - max active firing time before weapon 'overheats' (at which point the weapon will fail for a moment) // [7] = coolRate - how fast the weapon cools down. // [8] = mod - means of death // potential inclusions in the table: // damage - // splashDamage - // soundRange - distance which ai can hear the weapon // ammoWarning - amount we give the player a 'low on ammo' warning (just a HUD color change or something) // clipWarning - amount we give the player a 'low in clip' warning (just a HUD color change or something) // maxclip2 - allow the player to (mod/powerup) upgrade clip size when aplicable (luger has 8 round standard clip and 32 round snail magazine, for ex.) // // // // Separate table for SP and MP allow us to make the ammo and med packs function differently and may allow use to balance // weapons separately for each game. // Gordon: changed to actually use the maxammo values ammotable_t ammoTableMP[WP_NUM_WEAPONS] = { // MAX USES MAX START START RELOAD FIRE NEXT HEAT, COOL, MOD, ... // AMMO AMT. CLIP AMMO CLIP TIME DELAY SHOT { 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0 }, // WP_NONE // 0 { 999, 0, 999, 0, 0, 0, 50, 200, 0, 0, MOD_KNIFE }, // WP_KNIFE // 1 { 24, 1, 8, 24, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_LUGER }, // WP_LUGER // 2 // NOTE: also 32 round 'snail' magazine { 90, 1, 30, 30, 30, 2400, DELAY_LOW, 150, 0, 0, MOD_MP40 }, // WP_MP40 // 3 { 45, 1, 15, 0, 4, 1000, DELAY_THROW, 1600, 0, 0, MOD_GRENADE_LAUNCHER }, // WP_GRENADE_LAUNCHER // 4 { 4, 1, 1, 0, 4, 1000, 750, 2000, 0, 0, MOD_PANZERFAUST }, // WP_PANZERFAUST // 5 // DHM - Nerve :: updated delay so prediction is correct { 200, 1, 200, 0, 200, 1000, DELAY_LOW, 50, 0, 0, MOD_FLAMETHROWER }, // WP_FLAMETHROWER // 6 { 24, 1, 8, 24, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_COLT }, // WP_COLT // 7 { 90, 1, 30, 30, 30, 2400, DELAY_LOW, 150, 0, 0, MOD_THOMPSON }, // WP_THOMPSON // 8 { 45, 1, 15, 0, 4, 1000, DELAY_THROW, 1600, 0, 0, MOD_GRENADE_PINEAPPLE }, // WP_GRENADE_PINEAPPLE // 9 { 96, 1, 32, 32, 32, 3100, DELAY_LOW, 150, 1200, 450, MOD_STEN }, // WP_STEN // 10 { 10, 1, 1, 0, 10, 1500, 50, 1000, 0, 0, MOD_SYRINGE }, // WP_MEDIC_SYRINGE // 11 { 1, 0, 1, 0, 0, 3000, 50, 1000, 0, 0, MOD_AMMO, }, // WP_AMMO // 12 { 1, 0, 1, 0, 1, 3000, 50, 1000, 0, 0, MOD_ARTY, }, // WP_ARTY // 13 { 24, 1, 8, 24, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_SILENCER }, // WP_SILENCER // 14 { 1, 0, 10, 0, 0, 1000, DELAY_THROW, 1600, 0, 0, MOD_DYNAMITE }, // WP_DYNAMITE // 15 { 999, 0, 999, 0, 0, 0, 50, 0, 0, 0, 0 }, // WP_SMOKETRAIL // 16 { 999, 0, 999, 0, 0, 0, 50, 0, 0, 0, 0 }, // WP_MAPMORTAR // 17 { 999, 0, 999, 0, 0, 0, 50, 0, 0, 0, 0 }, // VERYBIGEXPLOSION // 18 { 999, 0, 999, 1, 1, 0, 50, 0, 0, 0, 0 }, // WP_MEDKIT // 19 { 999, 0, 999, 0, 0, 0, 50, 0, 0, 0, 0 }, // WP_BINOCULARS // 20 { 999, 0, 999, 0, 0, 0, 50, 0, 0, 0, 0 }, // WP_PLIERS // 21 { 999, 0, 999, 0, 1, 0, 50, 0, 0, 0, MOD_AIRSTRIKE }, // WP_SMOKE_MARKER // 22 { 30, 1, 10, 20, 10, 2500, DELAY_LOW, 400, 0, 0, MOD_KAR98 }, // WP_KAR98 // 23 K43 { 24, 1, 8, 16, 8, 1500, DELAY_LOW, 400, 0, 0, MOD_CARBINE }, // WP_CARBINE // 24 GARAND { 24, 1, 8, 16, 8, 1500, DELAY_LOW, 400, 0, 0, MOD_GARAND }, // WP_GARAND // 25 GARAND { 1, 0, 1, 0, 1, 100, DELAY_LOW, 100, 0, 0, MOD_LANDMINE }, // WP_LANDMINE // 26 { 1, 0, 1, 0, 0, 3000, DELAY_LOW, 2000, 0, 0, MOD_SATCHEL }, // WP_SATCHEL // 27 { 1, 0, 1, 0, 0, 3000, 722, 2000, 0, 0, 0, }, // WP_SATCHEL_DET // 28 { 6, 1, 1, 0, 0, 2000, DELAY_HIGH, 2000, 0, 0, MOD_TRIPMINE }, // WP_TRIPMINE // 29 { 1, 0, 10, 0, 1, 1000, DELAY_THROW, 1600, 0, 0, MOD_SMOKEBOMB }, // WP_SMOKE_BOMB // 30 { 450, 1, 150, 0, 150, 3000, DELAY_LOW, 66, 1500, 300, MOD_MOBILE_MG42 }, // WP_MOBILE_MG42 // 31 { 30, 1, 10, 20, 10, 2500, DELAY_LOW, 400, 0, 0, MOD_K43 }, // WP_K43 // 32 K43 { 60, 1, 20, 40, 20, 2000, DELAY_LOW, 100, 0, 0, MOD_FG42 }, // WP_FG42 // 33 { 0, 0, 0, 0, 0, 0, 0, 0, 1500, 300, 0 }, // WP_DUMMY_MG42 // 34 { 15, 1, 1, 0, 0, 0, 750, 1600, 0, 0, MOD_MORTAR }, // WP_MORTAR // 35 { 999, 0, 1, 0, 0, 1000, 750, 1600, 0, 0, 0 }, // WP_LOCKPICK // 36 { 48, 1, 8, 48, 8, 2700, DELAY_PISTOL, 200, 0, 0, MOD_AKIMBO_COLT }, // WP_AKIMBO_COLT // 37 { 48, 1, 8, 48, 8, 2700, DELAY_PISTOL, 200, 0, 0, MOD_AKIMBO_LUGER }, // WP_AKIMBO_LUGER // 38 { 4, 1, 1, 4, 1, 3000, DELAY_LOW, 400, 0, 0, MOD_GPG40 }, // WP_GPG40 // 39 { 4, 1, 1, 4, 1, 3000, DELAY_LOW, 400, 0, 0, MOD_M7 }, // WP_M7 // 40 { 24, 1, 8, 24, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_SILENCED_COLT }, // WP_SILENCED_COLT // 41 { 24, 1, 8, 16, 8, 1500, 0, 400, 0, 0, MOD_GARAND_SCOPE }, // WP_GARAND_SCOPE // 42 GARAND { 30, 1, 10, 20, 10, 2500, 0, 400, 0, 0, MOD_K43_SCOPE }, // WP_K43_SCOPE // 43 K43 { 60, 1, 20, 40, 20, 2000, DELAY_LOW, 400, 0, 0, MOD_FG42SCOPE }, // WP_FG42SCOPE // 44 { 16, 1, 1, 12, 0, 0, 750, 1400, 0, 0, MOD_MORTAR }, // WP_MORTAR_SET // 45 { 10, 1, 1, 0, 10, 1500, 50, 1000, 0, 0, MOD_SYRINGE }, // WP_MEDIC_ADRENALINE // 46 { 48, 1, 8, 48, 8, 2700, DELAY_PISTOL, 200, 0, 0, MOD_AKIMBO_SILENCEDCOLT }, // WP_AKIMBO_SILENCEDCOLT // 47 { 48, 1, 8, 48, 8, 2700, DELAY_PISTOL, 200, 0, 0, MOD_AKIMBO_SILENCEDLUGER}, // WP_AKIMBO_SILENCEDLUGER // 48 { 450, 1, 150, 0, 150, 3000, DELAY_LOW, 66, 1500, 300, MOD_MOBILE_MG42 }, // WP_MOBILE_MG42_SET // 49 }; //----(SA) moved in here so both games can get to it int weapAlts[] = { WP_NONE, // 0 WP_NONE WP_NONE, // 1 WP_KNIFE WP_SILENCER, // 2 WP_LUGER WP_NONE, // 3 WP_MP40 WP_NONE, // 4 WP_GRENADE_LAUNCHER WP_NONE, // 5 WP_PANZERFAUST WP_NONE, // 6 WP_FLAMETHROWER WP_SILENCED_COLT, // 7 WP_COLT WP_NONE, // 8 WP_THOMPSON WP_NONE, // 9 WP_GRENADE_PINEAPPLE WP_NONE, // 10 WP_STEN WP_NONE, // 11 WP_MEDIC_SYRINGE // JPW NERVE WP_NONE, // 12 WP_AMMO // JPW NERVE WP_NONE, // 13 WP_ARTY // JPW NERVE WP_LUGER, // 14 WP_SILENCER //----(SA) was sp5 WP_NONE, // 15 WP_DYNAMITE //----(SA) modified (not in rotation yet) WP_NONE, // 16 WP_SMOKETRAIL WP_NONE, // 17 WP_MAPMORTAR WP_NONE, // 18 VERYBIGEXPLOSION WP_NONE, // 19 WP_MEDKIT WP_NONE, // 20 WP_BINOCULARS WP_NONE, // 21 WP_PLIERS WP_NONE, // 22 WP_SMOKE_MARKER WP_GPG40, // 23 WP_KAR98 WP_M7, // 24 WP_CARBINE (GARAND really) WP_GARAND_SCOPE, // 25 WP_GARAND WP_NONE, // 26 WP_LANDMINE WP_NONE, // 27 WP_SATCHEL WP_NONE, // 28 WP_SATCHEL_DET WP_NONE, // 29 WP_TRIPMINE WP_NONE, // 30 WP_SMOKE_BOMB WP_MOBILE_MG42_SET, // 31 WP_MOBILE_MG42 WP_K43_SCOPE, // 32 WP_K43 WP_FG42SCOPE, // 33 WP_FG42 WP_NONE, // 34 WP_DUMMY_MG42 WP_MORTAR_SET, // 35 WP_MORTAR WP_NONE, // 36 WP_LOCKPICK Mad Doc - TDF WP_NONE, // 37 WP_AKIMBO_COLT WP_NONE, // 38 WP_AKIMBO_LUGER WP_KAR98, // 39 WP_GPG40 WP_CARBINE, // 40 WP_M7 WP_COLT, // 41 WP_SILENCED_COLT WP_GARAND, // 42 WP_GARAND_SCOPE WP_K43, // 43 WP_K43_SCOPE WP_FG42, // 44 WP_FG42SCOPE WP_MORTAR, // 45 WP_MORTAR_SET WP_NONE, // 46 WP_MEDIC_ADRENALINE WP_NONE, // 47 WP_AKIMBO_SILENCEDCOLT WP_NONE, // 48 WP_AKIMBO_SILENCEDLUGER WP_MOBILE_MG42, // 49 WP_MOBILE_MG42_SET }; // new (10/18/00) char *animStrings[] = { "BOTH_DEATH1", "BOTH_DEAD1", "BOTH_DEAD1_WATER", "BOTH_DEATH2", "BOTH_DEAD2", "BOTH_DEAD2_WATER", "BOTH_DEATH3", "BOTH_DEAD3", "BOTH_DEAD3_WATER", "BOTH_CLIMB", "BOTH_CLIMB_DOWN", "BOTH_CLIMB_DISMOUNT", "BOTH_SALUTE", "BOTH_PAIN1", "BOTH_PAIN2", "BOTH_PAIN3", "BOTH_PAIN4", "BOTH_PAIN5", "BOTH_PAIN6", "BOTH_PAIN7", "BOTH_PAIN8", "BOTH_GRAB_GRENADE", "BOTH_ATTACK1", "BOTH_ATTACK2", "BOTH_ATTACK3", "BOTH_ATTACK4", "BOTH_ATTACK5", "BOTH_EXTRA1", "BOTH_EXTRA2", "BOTH_EXTRA3", "BOTH_EXTRA4", "BOTH_EXTRA5", "BOTH_EXTRA6", "BOTH_EXTRA7", "BOTH_EXTRA8", "BOTH_EXTRA9", "BOTH_EXTRA10", "BOTH_EXTRA11", "BOTH_EXTRA12", "BOTH_EXTRA13", "BOTH_EXTRA14", "BOTH_EXTRA15", "BOTH_EXTRA16", "BOTH_EXTRA17", "BOTH_EXTRA18", "BOTH_EXTRA19", "BOTH_EXTRA20", "TORSO_GESTURE", "TORSO_GESTURE2", "TORSO_GESTURE3", "TORSO_GESTURE4", "TORSO_DROP", "TORSO_RAISE", // (low) "TORSO_ATTACK", "TORSO_STAND", "TORSO_STAND_ALT1", "TORSO_STAND_ALT2", "TORSO_READY", "TORSO_RELAX", "TORSO_RAISE2", // (high) "TORSO_ATTACK2", "TORSO_STAND2", "TORSO_STAND2_ALT1", "TORSO_STAND2_ALT2", "TORSO_READY2", "TORSO_RELAX2", "TORSO_RAISE3", // (pistol) "TORSO_ATTACK3", "TORSO_STAND3", "TORSO_STAND3_ALT1", "TORSO_STAND3_ALT2", "TORSO_READY3", "TORSO_RELAX3", "TORSO_RAISE4", // (shoulder) "TORSO_ATTACK4", "TORSO_STAND4", "TORSO_STAND4_ALT1", "TORSO_STAND4_ALT2", "TORSO_READY4", "TORSO_RELAX4", "TORSO_RAISE5", // (throw) "TORSO_ATTACK5", "TORSO_ATTACK5B", "TORSO_STAND5", "TORSO_STAND5_ALT1", "TORSO_STAND5_ALT2", "TORSO_READY5", "TORSO_RELAX5", "TORSO_RELOAD1", // (low) "TORSO_RELOAD2", // (high) "TORSO_RELOAD3", // (pistol) "TORSO_RELOAD4", // (shoulder) "TORSO_MG42", // firing tripod mounted weapon animation "TORSO_MOVE", // torso anim to play while moving and not firing (swinging arms type thing) "TORSO_MOVE_ALT", // torso anim to play while moving and not firing (swinging arms type thing) "TORSO_EXTRA", "TORSO_EXTRA2", "TORSO_EXTRA3", "TORSO_EXTRA4", "TORSO_EXTRA5", "TORSO_EXTRA6", "TORSO_EXTRA7", "TORSO_EXTRA8", "TORSO_EXTRA9", "TORSO_EXTRA10", "LEGS_WALKCR", "LEGS_WALKCR_BACK", "LEGS_WALK", "LEGS_RUN", "LEGS_BACK", "LEGS_SWIM", "LEGS_SWIM_IDLE", "LEGS_JUMP", "LEGS_JUMPB", "LEGS_LAND", "LEGS_IDLE", "LEGS_IDLE_ALT", // "LEGS_IDLE2" "LEGS_IDLECR", "LEGS_TURN", "LEGS_BOOT", // kicking animation "LEGS_EXTRA1", "LEGS_EXTRA2", "LEGS_EXTRA3", "LEGS_EXTRA4", "LEGS_EXTRA5", "LEGS_EXTRA6", "LEGS_EXTRA7", "LEGS_EXTRA8", "LEGS_EXTRA9", "LEGS_EXTRA10", }; // old char *animStringsOld[] = { "BOTH_DEATH1", "BOTH_DEAD1", "BOTH_DEATH2", "BOTH_DEAD2", "BOTH_DEATH3", "BOTH_DEAD3", "BOTH_CLIMB", "BOTH_CLIMB_DOWN", "BOTH_CLIMB_DISMOUNT", "BOTH_SALUTE", "BOTH_PAIN1", "BOTH_PAIN2", "BOTH_PAIN3", "BOTH_PAIN4", "BOTH_PAIN5", "BOTH_PAIN6", "BOTH_PAIN7", "BOTH_PAIN8", "BOTH_EXTRA1", "BOTH_EXTRA2", "BOTH_EXTRA3", "BOTH_EXTRA4", "BOTH_EXTRA5", "TORSO_GESTURE", "TORSO_GESTURE2", "TORSO_GESTURE3", "TORSO_GESTURE4", "TORSO_DROP", "TORSO_RAISE", // (low) "TORSO_ATTACK", "TORSO_STAND", "TORSO_READY", "TORSO_RELAX", "TORSO_RAISE2", // (high) "TORSO_ATTACK2", "TORSO_STAND2", "TORSO_READY2", "TORSO_RELAX2", "TORSO_RAISE3", // (pistol) "TORSO_ATTACK3", "TORSO_STAND3", "TORSO_READY3", "TORSO_RELAX3", "TORSO_RAISE4", // (shoulder) "TORSO_ATTACK4", "TORSO_STAND4", "TORSO_READY4", "TORSO_RELAX4", "TORSO_RAISE5", // (throw) "TORSO_ATTACK5", "TORSO_ATTACK5B", "TORSO_STAND5", "TORSO_READY5", "TORSO_RELAX5", "TORSO_RELOAD1", // (low) "TORSO_RELOAD2", // (high) "TORSO_RELOAD3", // (pistol) "TORSO_RELOAD4", // (shoulder) "TORSO_MG42", // firing tripod mounted weapon animation "TORSO_MOVE", // torso anim to play while moving and not firing (swinging arms type thing) "TORSO_EXTRA2", "TORSO_EXTRA3", "TORSO_EXTRA4", "TORSO_EXTRA5", "LEGS_WALKCR", "LEGS_WALKCR_BACK", "LEGS_WALK", "LEGS_RUN", "LEGS_BACK", "LEGS_SWIM", "LEGS_JUMP", "LEGS_LAND", "LEGS_IDLE", "LEGS_IDLE2", "LEGS_IDLECR", "LEGS_TURN", "LEGS_BOOT", // kicking animation "LEGS_EXTRA1", "LEGS_EXTRA2", "LEGS_EXTRA3", "LEGS_EXTRA4", "LEGS_EXTRA5", }; /*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) SUSPENDED SPIN PERSISTANT DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION. SUSPENDED - will allow items to hang in the air, otherwise they are dropped to the next surface. SPIN - will allow items to spin in place. PERSISTANT - some items (ex. clipboards) can be picked up, but don't disappear If an item is the target of another entity, it will not spawn in until fired. An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired. "notfree" if set to 1, don't spawn in free for all games "notteam" if set to 1, don't spawn in team games "notsingle" if set to 1, don't spawn in single player games "wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning. "random" random number of plus or minus seconds varied from the respawn time "count" override quantity or duration on most items. "stand" if the item has a stand (ex: mp40_stand.md3) this specifies which stand tag to attach the weapon to ("stand":"4" would mean "tag_stand4" for example) only weapons support stands currently */ // JOSEPH 5-2-00 //----(SA) the addition of the 'ammotype' field was added by me, not removed by id (SA) gitem_t bg_itemlist[] = { { NULL, NULL, { 0, 0, 0 }, NULL, // icon NULL, // ammo icon NULL, // pickup 0, 0, 0, 0, // ammotype 0, // cliptype "", // precache "", // sounds // {0,0,0,0,0} }, // leave index 0 alone /*QUAKED item_treasure (1 1 0) (-8 -8 -8) (8 8 8) suspended Items the player picks up that are just used to tally a score at end-level "model" defaults to 'models/powerups/treasure/goldbar.md3' "noise" sound to play on pickup. defaults to 'sound/pickup/treasure/gold.wav' "message" what to call the item when it's picked up. defaults to "Treasure Item" (SA: temp) -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/treasure/goldbar.md3" */ /* "scriptName" */ { "item_treasure", "sound/pickup/treasure/gold.wav", { "models/powerups/treasure/goldbar.md3", 0, 0 }, NULL, // (SA) placeholder NULL, // ammo icon "Treasure Item", // (SA) placeholder 5, IT_TREASURE, 0, 0, 0, "", "", // {0,0,0,0,0} }, // // ARMOR/HEALTH/STAMINA // /*QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_s.md3" */ { "item_health_small", "sound/items/n_health.wav", { "models/powerups/health/health_s.md3", 0, 0 }, NULL, NULL, // ammo icon "Small Health", 5, IT_HEALTH, 0, 0, 0, "", "", // {10,5,5,5,5} }, /*QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_m.md3" */ { "item_health", "sound/misc/health_pickup.wav", // "sound/multiplayer/health_pickup.wav", { "models/multiplayer/medpack/medpack_pickup.md3", // JPW NERVE was "models/powerups/health/health_m.md3", 0, 0 }, NULL, NULL, // ammo icon "Med Health", 20, IT_HEALTH, 0, 0, 0, "", "", // {50,25,20,15,15} }, /*QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_m.md3" */ { "item_health_large", "sound/misc/health_pickup.wav", // "sound/multiplayer/health_pickup.wav", { "models/multiplayer/medpack/medpack_pickup.md3", // JPW NERVE was "models/powerups/health/health_m.md3", 0, 0 }, NULL, NULL, // ammo icon "Med Health", 50, // xkan, 12/20/2002 - increased to 50 from 30 and used it for SP. IT_HEALTH, 0, 0, 0, "", "", // {50,25,20,15,15} }, { "item_health_cabinet", "sound/misc/health_pickup.wav", // "sound/multiplayer/health_pickup.wav", { 0, 0, 0 }, NULL, NULL, // ammo icon "Health", 0, IT_WEAPON, 0, 0, 0, "", "", }, /*QUAKED item_health_turkey (.3 .3 1) (-16 -16 -16) (16 16 16) suspended multi-stage health item. gives 40 on first use, then gives 20 on "finishing up" player will only eat what he needs. health at 90, turkey fills up and leaves remains (leaving 15). health at 5 you eat the whole thing. -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_t1.md3" */ { "item_health_turkey", "sound/items/hot_pickup.wav", { "models/powerups/health/health_t3.md3", // just plate (should now be destructable) "models/powerups/health/health_t2.md3", // half eaten "models/powerups/health/health_t1.md3" // whole turkey }, NULL, NULL, // ammo icon "Hot Meal", 20, // amount given in last stage IT_HEALTH, 0, 0, 0, "", "", // {50,50,50,40,30} // amount given in first stage based on gameskill level }, // xkan, 1/6/2002 - updated /*QUAKED item_health_breadandmeat (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN multi-stage health item. gives 30 on first use, then gives 15 on "finishing up" -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_b1.md3" */ { "item_health_breadandmeat", "sound/items/cold_pickup.wav", { "models/powerups/health/health_b3.md3", // just plate (should now be destructable) "models/powerups/health/health_b2.md3", // half eaten "models/powerups/health/health_b1.md3" // whole turkey }, NULL, NULL, // ammo icon "Cold Meal", 15, // amount given in last stage IT_HEALTH, 0, 0, 0, "", "", //{30,30,20,15} // amount given in first stage based on gameskill level }, // xkan, 1/6/2002 - updated /*QUAKED item_health_wall (.3 .3 1) (-16 -16 -16) (16 16 16) suspended defaults to 50 pts health you will probably want to check the 'suspended' box to keep it from falling to the ground -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/health/health_w.md3" */ { "item_health_wall", "sound/items/n_health.wav", { "models/powerups/health/health_w.md3", 0, 0 }, NULL, NULL, // ammo icon "Health", 25, IT_HEALTH, 0, 0, 0, "", "", // {25,25,25,25,25} }, // // STAMINA // // // WEAPONS // // wolf weapons (SA) /*QUAKED weapon_knife (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/knife/knife.md3" */ { "weapon_knife", "sound/misc/w_pkup.wav", { "models/multiplayer/knife/knife.md3", "models/multiplayer/knife/v_knife.md3", 0 }, "icons/iconw_knife_1", // icon "icons/ammo2", // ammo icon "Knife", // pickup 50, IT_WEAPON, WP_KNIFE, WP_KNIFE, WP_KNIFE, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_luger (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/luger/luger.md3" */ { "weapon_luger", "sound/misc/w_pkup.wav", { "models/weapons2/luger/luger.md3", "models/weapons2/luger/v_luger.md3", 0 }, "", // icon "icons/ammo2", // ammo icon "Luger", // pickup 50, IT_WEAPON, WP_LUGER, WP_LUGER, WP_LUGER, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_akimboluger (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/akimbo_luger/luger.md3" */ { "weapon_akimboluger", "sound/misc/w_pkup.wav", { "models/weapons2/luger/luger.md3", "models/weapons2/akimbo_luger/v_akimbo_luger.md3", 0 }, "icons/iconw_colt_1", // icon // FIXME: need new icon "icons/ammo2", // ammo icon "Akimbo Luger", // pickup 50, IT_WEAPON, WP_AKIMBO_LUGER, WP_LUGER, WP_AKIMBO_LUGER, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_akimbosilencedluger (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/akimbo_luger/luger.md3" */ { "weapon_akimbosilencedluger", "sound/misc/w_pkup.wav", { "models/weapons2/luger/luger.md3", "models/weapons2/akimbo_luger/v_akimbo_luger.md3", 0 }, "icons/iconw_colt_1", // icon // FIXME: need new icon "icons/ammo2", // ammo icon "Silenced Akimbo Luger", // pickup 50, IT_WEAPON, WP_AKIMBO_SILENCEDLUGER, WP_LUGER, WP_AKIMBO_LUGER, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_thompson (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/thompson/thompson.md3" */ { "weapon_thompson", "sound/misc/w_pkup.wav", { "models/weapons2/thompson/thompson.md3", // "models/multiplayer/mg42/v_mg42.md3", "models/weapons2/thompson/v_thompson.md3", 0 }, "icons/iconw_thompson_1", // icon "icons/ammo2", // ammo icon "Thompson", // pickup 30, IT_WEAPON, WP_THOMPSON, WP_THOMPSON, WP_THOMPSON, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_dummy", "", { 0, 0, 0 }, "", // icon "", // ammo icon "BLANK", // pickup 0, // quantity IT_WEAPON, // item type WP_DUMMY_MG42, // giTag WP_DUMMY_MG42, // giAmmoIndex WP_DUMMY_MG42, // giClipIndex "", // precache "", // sounds }, /*QUAKED weapon_sten (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/sten/sten.md3" */ { "weapon_sten", "sound/misc/w_pkup.wav", { "models/weapons2/sten/sten.md3", "models/weapons2/sten/v_sten.md3", 0 }, "icons/iconw_sten_1", // icon "icons/ammo2", // ammo icon "Sten", // pickup 30, IT_WEAPON, WP_STEN, WP_STEN, WP_STEN, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_colt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/colt/colt.md3" */ { "weapon_colt", "sound/misc/w_pkup.wav", { "models/weapons2/colt/colt.md3", "models/weapons2/colt/v_colt.md3", 0 }, "icons/iconw_colt_1", // icon "icons/ammo2", // ammo icon "Colt", // pickup 50, IT_WEAPON, WP_COLT, WP_COLT, WP_COLT, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_akimbocolt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/akimbo_colt/colt.md3" */ { "weapon_akimbocolt", "sound/misc/w_pkup.wav", { "models/weapons2/colt/colt.md3", "models/weapons2/akimbo_colt/v_akimbo_colt.md3", 0 }, "icons/iconw_colt_1", // icon // FIXME: need new icon "icons/ammo2", // ammo icon "Akimbo Colt", // pickup 50, IT_WEAPON, WP_AKIMBO_COLT, WP_COLT, WP_AKIMBO_COLT, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_akimbosilencedcolt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/akimbo_colt/colt.md3" */ { "weapon_akimbosilencedcolt", "sound/misc/w_pkup.wav", { "models/weapons2/colt/colt.md3", "models/weapons2/akimbo_colt/v_akimbo_colt.md3", 0 }, "icons/iconw_colt_1", // icon // FIXME: need new icon "icons/ammo2", // ammo icon "Silenced Akimbo Colt", // pickup 50, IT_WEAPON, WP_AKIMBO_SILENCEDCOLT, WP_COLT, WP_AKIMBO_COLT, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_mp40 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended "stand" values: no value: laying in a default position on it's side (default) 2: upright, barrel pointing up, slightly angled (rack mount) -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models\weapons2\mp40\mp40.md3" */ { "weapon_mp40", "sound/misc/w_pkup.wav", { "models/weapons2/mp40/mp40.md3", "models/weapons2/mp40/v_mp40.md3", 0 }, "icons/iconw_mp40_1", // icon "icons/ammo2", // ammo icon "MP40", // pickup 30, IT_WEAPON, WP_MP40, WP_MP40, WP_MP40, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_panzerfaust (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/panzerfaust/pf.md3" */ { "weapon_panzerfaust", "sound/misc/w_pkup.wav", { "models/weapons2/panzerfaust/pf.md3", "models/weapons2/panzerfaust/v_pf.md3", 0 }, "icons/iconw_panzerfaust_1", // icon "icons/ammo6", // ammo icon "Panzerfaust", // pickup 1, IT_WEAPON, WP_PANZERFAUST, WP_PANZERFAUST, WP_PANZERFAUST, "", // precache "", // sounds // {0,0,0,0,0} }, //----(SA) removed the quaked for this. we don't actually have a grenade launcher as such. It's given implicitly // by virtue of getting grenade ammo. So we don't need to have them in maps /* weapon_grenadelauncher */ { "weapon_grenadelauncher", "sound/misc/w_pkup.wav", { "models/weapons2/grenade/grenade.md3", "models/weapons2/grenade/v_grenade.md3", 0 }, "icons/iconw_grenade_1", // icon "icons/icona_grenade", // ammo icon "Grenade", // pickup 6, IT_WEAPON, WP_GRENADE_LAUNCHER, WP_GRENADE_LAUNCHER, WP_GRENADE_LAUNCHER, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_grenadePineapple */ { "weapon_grenadepineapple", "sound/misc/w_pkup.wav", { "models/weapons2/grenade/pineapple.md3", "models/weapons2/grenade/v_pineapple.md3", 0 }, "icons/iconw_pineapple_1", // icon "icons/icona_pineapple", // ammo icon "Pineapple", // pickup 6, IT_WEAPON, WP_GRENADE_PINEAPPLE, WP_GRENADE_PINEAPPLE, WP_GRENADE_PINEAPPLE, "", // precache "", // sounds // {0,0,0,0,0} }, /* JPW NERVE weapon_grenadesmoke */ { "weapon_grenadesmoke", "sound/misc/w_pkup.wav", { "models/multiplayer/smokegrenade/smokegrenade.md3", "models/multiplayer/smokegrenade/v_smokegrenade.md3", 0 }, "icons/iconw_smokegrenade_1", // icon "icons/ammo2", // ammo icon "smokeGrenade", // pickup 50, IT_WEAPON, WP_SMOKE_MARKER, WP_SMOKE_MARKER, WP_SMOKE_MARKER, "", // precache "", // sounds // {0,0,0,0,0} }, // jpw /* JPW NERVE weapon_smoketrail -- only used as a special effects emitter for smoke trails (artillery spotter etc) */ { "weapon_smoketrail", "sound/misc/w_pkup.wav", { "models/multiplayer/smokegrenade/smokegrenade.md3", "models/multiplayer/smokegrenade/v_smokegrenade.md3", 0 }, "icons/iconw_smokegrenade_1", // icon "icons/ammo2", // ammo icon "smokeTrail", // pickup 50, IT_WEAPON, WP_SMOKETRAIL, WP_SMOKETRAIL, WP_SMOKETRAIL, "", // precache "", // sounds // {0,0,0,0,0} }, // jpw // DHM - Nerve /* weapon_medic_heal */ { "weapon_medic_heal", "sound/misc/w_pkup.wav", { "models/multiplayer/medpack/medpack.md3", "models/multiplayer/medpack/v_medpack.md3", 0 }, "icons/iconw_medheal_1", // icon "icons/ammo2", // ammo icon "medicheal", // pickup 50, IT_WEAPON, WP_MEDKIT, WP_MEDKIT, WP_MEDKIT, "", // precache "", // sounds // {0,0,0,0,0} }, // dhm /* weapon_dynamite */ { "weapon_dynamite", "sound/misc/w_pkup.wav", { "models/multiplayer/dynamite/dynamite_3rd.md3", // JPW NERVE "models/weapons2/dynamite/v_dynamite.md3", // JPW NERVE 0 }, "icons/iconw_dynamite_1", // icon "icons/ammo9", // ammo icon "Dynamite Weapon", // pickup 7, IT_WEAPON, WP_DYNAMITE, WP_DYNAMITE, WP_DYNAMITE, "models/multiplayer/dynamite/dynamite.md3 models/multiplayer/dynamite/dynamite_3rd.md3", // precache // JPW NERVE "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_flamethrower (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/flamethrower/flamethrower.md3" */ { "weapon_flamethrower", "sound/misc/w_pkup.wav", { "models/weapons2/flamethrower/flamethrower.md3", "models/weapons2/flamethrower/v_flamethrower.md3", "models/weapons2/flamethrower/pu_flamethrower.md3" }, "icons/iconw_flamethrower_1", // icon "icons/ammo10", // ammo icon "Flamethrower", // pickup 200, IT_WEAPON, WP_FLAMETHROWER, WP_FLAMETHROWER, WP_FLAMETHROWER, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_mortar (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_mapmortar", "sound/misc/w_pkup.wav", { "models/weapons2/grenade/grenade.md3", "models/weapons2/grenade/v_grenade.md3", 0 }, "icons/iconw_grenade_1", // icon "icons/icona_grenade", // ammo icon "nopickup(WP_MAPMORTAR)", // pickup 6, IT_WEAPON, WP_MAPMORTAR, WP_MAPMORTAR, WP_MAPMORTAR, "", // precache "sound/weapons/mortar/mortarf1.wav", // sounds // {0,0,0,0,0} }, // JPW NERVE -- class-specific multiplayer weapon, can't be picked up, dropped, or placed in map /* weapon_class_special (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_class_special", "sound/misc/w_pkup.wav", { "models/multiplayer/pliers/pliers.md3", "models/multiplayer/pliers/v_pliers.md3", 0 }, "icons/iconw_pliers_1", // icon "icons/ammo2", // ammo icon "Special", // pickup 50, // this should never be picked up IT_WEAPON, WP_PLIERS, WP_PLIERS, WP_PLIERS, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_arty (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_arty", "sound/misc/w_pkup.wav", { "models/multiplayer/syringe/syringe.md3", "models/multiplayer/syringe/v_syringe.md3", 0 }, "icons/iconw_syringe_1", // icon "icons/ammo2", // ammo icon "Artillery", // pickup 50, // this should never be picked up IT_WEAPON, WP_ARTY, WP_ARTY, WP_ARTY, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_medic_syringe (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_medic_syringe", "sound/misc/w_pkup.wav", { "models/multiplayer/syringe/syringe.md3", "models/multiplayer/syringe/v_syringe.md3", 0 }, "icons/iconw_syringe_1", // icon "icons/ammo2", // ammo icon "Syringe", // pickup 50, // this should never be picked up IT_WEAPON, WP_MEDIC_SYRINGE, WP_MEDIC_SYRINGE, WP_MEDIC_SYRINGE, "", // precache "sound/misc/vo_revive.wav", // sounds // {0,0,0,0,0} }, /* weapon_medic_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_medic_adrenaline", "sound/misc/w_pkup.wav", { "models/multiplayer/syringe/syringe.md3", "models/multiplayer/syringe/v_syringe.md3", 0 }, "icons/iconw_syringe_1", // icon "icons/ammo2", // ammo icon "Adrenaline Syringe", // pickup 50, // this should never be picked up IT_WEAPON, WP_MEDIC_ADRENALINE, WP_MEDIC_SYRINGE, WP_MEDIC_SYRINGE, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_magicammo (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_magicammo", "sound/misc/w_pkup.wav", { "models/multiplayer/ammopack/ammopack.md3", "models/multiplayer/ammopack/v_ammopack.md3", "models/multiplayer/ammopack/ammopack_pickup.md3" }, "icons/iconw_ammopack_1", // icon "icons/ammo2", // ammo icon "Ammo Pack", // pickup 50, // this should never be picked up IT_WEAPON, WP_AMMO, WP_AMMO, WP_AMMO, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_magicammo2", "sound/misc/w_pkup.wav", { "models/multiplayer/binocs/v_binocs.md3", "models/multiplayer/binocs/v_binocs.md3", "models/multiplayer/binocs/v_binocs.md3", // "models/multiplayer/ammopack/ammopack.md3", // "models/multiplayer/ammopack/v_ammopack.md3", // "models/multiplayer/ammopack/ammopack_pickup_s.md3" }, "icons/iconw_ammopack_1", // icon "icons/ammo2", // ammo icon "Mega Ammo Pack", // pickup 50, // this should never be picked up IT_WEAPON, WP_AMMO, WP_AMMO, WP_AMMO, "", // precache "", // sounds }, /* weapon_binoculars (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_binoculars", "sound/misc/w_pkup.wav", { "", "models/multiplayer/binocs/v_binocs.md3", 0 }, "", // icon "", // ammo icon "Binoculars", // pickup 50, // this should never be picked up IT_WEAPON, WP_BINOCULARS, WP_BINOCULARS, WP_BINOCULARS, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_k43 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="" */ { "weapon_kar43", "sound/misc/w_pkup.wav", { "models/multiplayer/kar98/kar98_3rd.md3", "models/multiplayer/kar98/v_kar98.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_mauser_1", // icon "icons/ammo3", // ammo icon "K43 Rifle", // pickup 50, IT_WEAPON, WP_K43, WP_K43, WP_K43, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_kar43_scope (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="" */ { "weapon_kar43_scope", "sound/misc/w_pkup.wav", { "models/multiplayer/kar98/kar98_3rd.md3", "models/multiplayer/kar98/v_kar98.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_mauser_1", // icon "icons/ammo3", // ammo icon "K43 Rifle Scope", // pickup 50, IT_WEAPON, WP_K43_SCOPE, WP_K43, WP_K43, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_kar98Rifle (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/mauser/mauser.md3" */ { "weapon_kar98Rifle", "sound/misc/w_pkup.wav", /* { "models/weapons2/mauser/kar98.md3", "models/multiplayer/kar98/v_kar98.md3", "models/multiplayer/mauser/kar98_pickup.md3" }, "icons/iconw_kar98_1", // icon "icons/ammo3", // ammo icon*/ { "models/multiplayer/kar98/kar98_3rd.md3", "models/multiplayer/kar98/v_kar98.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_kar98_1", // icon "icons/ammo3", // ammo icon "K43", // pickup 50, IT_WEAPON, WP_KAR98, WP_KAR98, WP_KAR98, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_gpg40 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/mauser/mauser.md3" */ { "weapon_gpg40", "sound/misc/w_pkup.wav", { "models/multiplayer/kar98/kar98_3rd.md3", "models/multiplayer/kar98/v_kar98.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_kar98_1", // icon "icons/ammo10", // ammo icon "GPG40", // pickup 200, IT_WEAPON, WP_GPG40, WP_GPG40, WP_GPG40, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_gpg40_allied (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/mauser/mauser.md3" */ { "weapon_gpg40_allied", "sound/misc/w_pkup.wav", { "models/multiplayer/m1_garand/m1_garand_3rd.md3", "models/multiplayer/m1_garand/v_m1_garand.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_m1_garand_1", // icon "icons/ammo10", // ammo icon "GPG40A", // pickup 200, IT_WEAPON, WP_M7, WP_M7, WP_M7, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_M1CarbineRifle (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/mauser/mauser.md3" */ { "weapon_M1CarbineRifle", "sound/misc/w_pkup.wav", /* { "models/weapons2/mauser/mauser.md3", "models/weapons2/mauser/v_mauser.md3", "models/multiplayer/mauser/mauser_pickup.md3" },*/ { "models/multiplayer/m1_garand/m1_garand_3rd.md3", "models/multiplayer/m1_garand/v_m1_garand.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_m1_garand_1", // icon "icons/ammo3", // ammo icon "M1 Garand", // pickup 50, IT_WEAPON, WP_CARBINE, WP_CARBINE, WP_CARBINE, "", // precache "", // sounds // {0,0,0,0,0} }, /* weapon_garandRifle (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/garand/garand.md3" */ { "weapon_garandRifle", "sound/misc/w_pkup.wav", { "models/multiplayer/m1_garand/m1_garand_3rd.md3", "models/multiplayer/m1_garand/v_m1_garand.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_mauser_1", // icon "icons/ammo3", // ammo icon "Garand", // pickup 50, IT_WEAPON, WP_GARAND, WP_GARAND, WP_GARAND, "", // precache "", // sounds // {0,0,0,0} }, /* weapon_garandRifleScope (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/garand/garand.md3" */ { "weapon_garandRifleScope", "sound/misc/w_pkup.wav", { "models/multiplayer/m1_garand/m1_garand_3rd.md3", "models/multiplayer/m1_garand/v_m1_garand.md3", "models/multiplayer/mauser/mauser_pickup.md3" }, "icons/iconw_mauser_1", // icon "icons/ammo3", // ammo icon "M1 Garand Scope", // pickup 50, IT_WEAPON, WP_GARAND_SCOPE, WP_GARAND, WP_GARAND, "", // precache "", // sounds // {0,0,0,0} }, /*QUAKED weapon_fg42 (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/fg42/fg42.md3" */ { "weapon_fg42", "sound/misc/w_pkup.wav", { "models/weapons2/fg42/fg42.md3", "models/weapons2/fg42/v_fg42.md3", "models/weapons2/fg42/pu_fg42.md3" }, "icons/iconw_fg42_1", // icon "icons/ammo5", // ammo icon "FG42 Paratroop Rifle", // pickup 10, IT_WEAPON, WP_FG42, WP_FG42, WP_FG42, "", // precache "", // sounds // {0,0,0,0} }, /*QUAKED weapon_fg42scope (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/fg42/fg42.md3" */ { "weapon_fg42scope", //----(SA) modified "sound/misc/w_pkup.wav", { "models/weapons2/fg42/fg42.md3", "models/weapons2/fg42/v_fg42.md3", "models/weapons2/fg42/pu_fg42.md3"}, "icons/iconw_fg42_1", // icon "icons/ammo5", // ammo icon "FG42 Scope", // pickup //----(SA) modified 0, IT_WEAPON, WP_FG42SCOPE, // this weap WP_FG42, // shares ammo w/ WP_FG42, // shares clip w/ "", // precache "", // sounds // {0,0,0,0} }, /* weapon_mortar (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/bla?bla?/bla!.md3" */ { "weapon_mortar", "sound/misc/w_pkup.wav", { "models/multiplayer/mortar/mortar_3rd.md3", "models/multiplayer/mortar/v_mortar.md3", 0}, "icons/iconw_mortar_1", // icon "icons/ammo5", // ammo icon "Mortar", // pickup //----(SA) modified 0, IT_WEAPON, WP_MORTAR, // this weap WP_MORTAR, // shares ammo w/ WP_MORTAR, // shares clip w/ "", // precache "", // sounds // {0,0,0,0} }, { "weapon_mortar_set", "sound/misc/w_pkup.wav", { "models/multiplayer/mortar/mortar_3rd.md3", "models/multiplayer/mortar/v_mortar.md3", 0}, "icons/iconw_mortar_1", // icon "icons/ammo5", // ammo icon "Mounted Mortar", // pickup //----(SA) modified 0, IT_WEAPON, WP_MORTAR_SET, // this weap WP_MORTAR, // shares ammo w/ WP_MORTAR, // shares clip w/ "", // precache "", // sounds // {0,0,0,0} }, /* weapon_landmine */ { "weapon_landmine", "", { "models/multiplayer/landmine/landmine.md3", "models/multiplayer/landmine/v_landmine.md3", 0 }, "icons/iconw_landmine_1", // icon "icons/ammo9", // ammo icon "Landmine", // pickup 7, IT_WEAPON, WP_LANDMINE, WP_LANDMINE, WP_LANDMINE, "models/multiplayer/landmine/landmine.md3", "", // sounds // {0,0,0,0,0} }, /* weapon_satchel (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { "weapon_satchel", "sound/misc/w_pkup.wav", { "models/multiplayer/satchel/satchel.md3", "models/multiplayer/satchel/v_satchel.md3", 0 }, "icons/iconw_satchel_1", // icon "icons/ammo2", // ammo icon "Satchel Charge", // pickup 0, IT_WEAPON, WP_SATCHEL, WP_SATCHEL, WP_SATCHEL, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_satchelDetonator", "", { "models/multiplayer/satchel/radio.md3", "models/multiplayer/satchel/v_satchel.md3", 0 }, "icons/iconw_radio_1", // icon "icons/ammo2", // ammo icon "Satchel Charge Detonator", // pickup 0, IT_WEAPON, WP_SATCHEL_DET, WP_SATCHEL_DET, WP_SATCHEL_DET, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_smokebomb", "", { "models/multiplayer/smokebomb/smokebomb.md3", "models/multiplayer/smokebomb/v_smokebomb.md3", 0 }, "icons/iconw_dynamite_1", // icon "icons/ammo9", // ammo icon "Smoke Bomb", // pickup 0, IT_WEAPON, WP_SMOKE_BOMB, WP_SMOKE_BOMB, WP_SMOKE_BOMB, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_tripmine", "sound/misc/w_pkup.wav", { "models/multiplayer/dynamite/dynamite_3rd.md3", "models/weapons2/dynamite/v_dynamite.md3", 0 }, "icons/iconw_dynamite_1", // icon "icons/ammo9", // ammo icon "Tripmine", // pickup 7, IT_WEAPON, WP_TRIPMINE, WP_TRIPMINE, WP_TRIPMINE, "models/multiplayer/dynamite/dynamite.md3 models/multiplayer/dynamite/dynamite_3rd.md3", "", // sounds // {0,0,0,0,0} }, /*QUAKED weapon_mobile_mg42 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended spin - respawn -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/multiplayer/mg42/v_mg42.md3" */ { "weapon_mobile_mg42", "sound/misc/w_pkup.wav", { "models/multiplayer/mg42/mg42_3rd.md3", "models/multiplayer/mg42/v_mg42.md3", 0 }, "icons/iconw_mg42_1", // icon "icons/ammo2", // ammo icon "Mobile MG42", // pickup 30, IT_WEAPON, WP_MOBILE_MG42, WP_MOBILE_MG42, WP_MOBILE_MG42, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_mobile_mg42_set", "sound/misc/w_pkup.wav", { "models/multiplayer/mg42/mg42_3rd.md3", "models/multiplayer/mg42/v_mg42.md3", 0 }, "icons/iconw_mg42_1", // icon "icons/ammo2", // ammo icon "Mobile MG42 Bipod", // pickup 30, IT_WEAPON, WP_MOBILE_MG42_SET, WP_MOBILE_MG42, WP_MOBILE_MG42, "", // precache "", // sounds // {0,0,0,0,0} }, { "weapon_silencer", "sound/misc/w_pkup.wav", { "models/weapons2/silencer/silencer.md3", //----(SA) changed 10/25 "models/weapons2/silencer/v_silencer.md3", "models/weapons2/silencer/pu_silencer.md3"}, "icons/iconw_silencer_1", // icon "icons/ammo5", // ammo icon // "Silencer", // pickup "sp5 pistol", 10, IT_WEAPON, WP_SILENCER, WP_LUGER, WP_LUGER, "", // precache "", // sounds // {0,0,0,0} }, /*QUAKED weapon_colt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/weapons2/colt/colt.md3" */ { "weapon_silencedcolt", "sound/misc/w_pkup.wav", { "models/weapons2/colt/colt.md3", "models/multiplayer/silencedcolt/v_silencedcolt.md3", 0 }, "icons/iconw_colt_1", // icon "icons/ammo2", // ammo icon "Silenced Colt", // pickup 50, IT_WEAPON, WP_SILENCED_COLT, WP_COLT, WP_COLT, "", // precache "", // sounds // {0,0,0,0,0} }, // DHM - Nerve /* weapon_medic_heal */ { "weapon_medic_heal", "sound/misc/w_pkup.wav", { "models/multiplayer/medpack/medpack.md3", "models/multiplayer/medpack/v_medpack.md3", 0 }, "icons/iconw_medheal_1", // icon "icons/ammo2", // ammo icon "medicheal", // pickup 50, IT_WEAPON, WP_MEDKIT, WP_MEDKIT, WP_MEDKIT, "", // precache "", // sounds // {0,0,0,0,0} }, // dhm /*QUAKED ammo_syringe (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: medic -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/syringe/syringe.md3 */ { "ammo_syringe", "sound/misc/am_pkup.wav", { "models/ammo/syringe/syringe.md3", 0, 0}, "", // icon NULL, // ammo icon "syringe", // pickup //----(SA) changed 1, IT_AMMO, WP_MEDIC_SYRINGE, WP_MEDIC_SYRINGE, WP_MEDIC_SYRINGE, "", // precache "", // sounds }, /*QUAKED ammo_smoke_grenade (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: engineer -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/smoke_grenade/smoke_grenade.md3" */ { "ammo_smoke_grenade", "sound/misc/am_pkup.wav", { "models/ammo/smoke_grenade/smoke_grenade.md3", 0, 0 }, "", // icon NULL, // ammo icon "smoke grenade", // pickup //----(SA) changed 1, IT_AMMO, WP_SMOKE_BOMB, WP_SMOKE_BOMB, WP_SMOKE_BOMB, "", // precache "", // sounds }, /*QUAKED ammo_dynamite (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: engineer -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/dynamite/dynamite.md3" */ { "ammo_dynamite", "sound/misc/am_pkup.wav", { "models/ammo/dynamite/dynamite.md3", 0, 0}, "", // icon NULL, // ammo icon "dynamite", // pickup //----(SA) changed 1, IT_AMMO, WP_DYNAMITE, WP_DYNAMITE, WP_DYNAMITE, "", // precache "", // sounds }, /*QUAKED ammo_disguise (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: covertops -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/disguise/disguise.md3" */ { "ammo_disguise", "sound/misc/am_pkup.wav", { "models/ammo/disguise/disguise.md3", 0, 0}, "", // icon NULL, // ammo icon "disguise", // pickup //----(SA) changed 1, IT_AMMO, -1, // ignored -1, // ignored -1, // ignored "", // precache "", // sounds }, /*QUAKED ammo_airstrike (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: LT -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/airstrike/airstrike.md3" */ { "ammo_airstrike", "sound/misc/am_pkup.wav", { "models/ammo/disguise/disguise.md3", 0, 0}, "", // icon NULL, // ammo icon "airstrike canister", // pickup //----(SA) changed 1, IT_AMMO, WP_SMOKE_MARKER, WP_SMOKE_MARKER, WP_SMOKE_MARKER, "", // precache "", // sounds }, /*QUAKED ammo_landmine (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: LT -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/landmine/landmine.md3" */ { "ammo_landmine", "sound/misc/am_pkup.wav", { "models/ammo/landmine/landmine.md3", 0, 0 }, "", // icon NULL, // ammo icon "landmine", // pickup //----(SA) changed 1, IT_AMMO, WP_LANDMINE, WP_LANDMINE, WP_LANDMINE, "", // precache "", // sounds }, /*QUAKED ammo_satchel_charge (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: LT -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/ammo/satchel/satchel.md3" */ { "ammo_satchel_charge", "sound/misc/am_pkup.wav", { "models/ammo/satchel/satchel.md3", 0, 0 }, "", // icon NULL, // ammo icon "satchel charge", // pickup //----(SA) changed 1, IT_AMMO, WP_SATCHEL, WP_SATCHEL, WP_SATCHEL, "", // precache "", // sounds }, // // AMMO ITEMS // /*QUAKED ammo_9mm_small (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Luger pistol, MP40 machinegun -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am9mm_s.md3" */ { "ammo_9mm_small", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am9mm_s.md3", 0, 0 }, "", // icon NULL, // ammo icon "9mm Rounds", // pickup 8, IT_AMMO, WP_LUGER, WP_LUGER, WP_LUGER, "", // precache "", // sounds // {32,24,16,16} }, /*QUAKED ammo_9mm (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Luger pistol, MP40 machinegun -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am9mm_m.md3" */ { "ammo_9mm", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am9mm_m.md3", 0, 0 }, "", // icon NULL, // ammo icon "9mm", // pickup //----(SA) changed 16, IT_AMMO, WP_LUGER, WP_LUGER, WP_LUGER, "", // precache "", // sounds // {64,48,32,32} }, /*QUAKED ammo_9mm_large (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Luger pistol, MP40 machinegun -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am9mm_l.md3" */ { "ammo_9mm_large", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am9mm_l.md3", 0, 0 }, "", // icon NULL, // ammo icon "9mm Box", // pickup 24, IT_AMMO, WP_LUGER, WP_LUGER, WP_LUGER, "", // precache "", // sounds // {96,64,48,48} }, /*QUAKED ammo_45cal_small (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Thompson, Colt -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am45cal_s.md3" */ { "ammo_45cal_small", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am45cal_s.md3", 0, 0 }, "", // icon NULL, // ammo icon ".45cal Rounds", // pickup 8, IT_AMMO, WP_COLT, WP_COLT, WP_COLT, "", // precache "", // sounds // {30,20,15,15} }, /*QUAKED ammo_45cal (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Thompson, Colt -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am45cal_m.md3" */ { "ammo_45cal", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am45cal_m.md3", 0, 0 }, "", // icon NULL, // ammo icon ".45cal", // pickup //----(SA) changed 16, IT_AMMO, WP_COLT, WP_COLT, WP_COLT, "", // precache "", // sounds // {60,45,30,30} }, /*QUAKED ammo_45cal_large (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Thompson, Colt -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am45cal_l.md3" */ { "ammo_45cal_large", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am45cal_l.md3", 0, 0 }, "", // icon NULL, // ammo icon ".45cal Box", // pickup 24, IT_AMMO, WP_COLT, WP_COLT, WP_COLT, "", // precache "", // sounds // {90,60,45,45} }, /*QUAKED ammo_30cal_small (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Garand rifle -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am30cal_s.md3" */ { "ammo_30cal_small", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am30cal_s.md3", 0, 0}, "", // icon NULL, // ammo icon ".30cal Rounds", // pickup 8, IT_AMMO, WP_GARAND, WP_GARAND, WP_GARAND, "", // precache "", // sounds // {5,2,2,2} }, /*QUAKED ammo_30cal (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Garand rifle -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am30cal_m.md3" */ { "ammo_30cal", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am30cal_m.md3", 0, 0 }, "", // icon NULL, // ammo icon ".30cal", // pickup //----(SA) changed 16, IT_AMMO, WP_GARAND, WP_GARAND, WP_GARAND, "", // precache "", // sounds // {5,5,5,5 } }, /*QUAKED ammo_30cal_large (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN used by: Garand rifle -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/ammo/am30cal_l.md3" */ { "ammo_30cal_large", "sound/misc/am_pkup.wav", { "models/powerups/ammo/am30cal_l.md3", 0, 0 }, "", // icon NULL, // ammo icon ".30cal Box", // pickup 24, IT_AMMO, WP_GARAND, WP_GARAND, WP_GARAND, "", // precache "", // sounds // {10,10,10,5} }, // // POWERUP ITEMS // /*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16) Only in CTF games -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/flags/r_flag.md3" */ { "team_CTF_redflag", "", { 0, 0, 0 }, "", // icon NULL, // ammo icon "Objective", // pickup 0, IT_TEAM, PW_REDFLAG, 0, 0, "", // precache "", // sounds // {0,0,0,0,0} }, /*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16) Only in CTF games -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/flags/b_flag.md3" */ { "team_CTF_blueflag", "", { 0, 0, 0 }, "", // icon NULL, // ammo icon "Blue Flag", // pickup 0, IT_TEAM, PW_BLUEFLAG, 0, 0, "", // precache "", // sounds // {0,0,0,0,0} }, //---- (SA) Wolf keys /* QUAKED key_1 (1 1 0) (-8 -8 -8) (8 8 8) SUSPENDED SPIN - RESPAWN key 1 pickup sound : "sound/misc/w_pkup.wav" -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY -------- model="models/powerups/xp_key/key.md3" */ /* { "key_key1", "sound/misc/w_pkup.wav", //"sound/pickup/keys/skull.wav", { "models/powerups/xp_key/key.md3", 0, 0 }, "", //"icons/iconk_skull", // icon NULL, // ammo icon "Key 1", // pickup 0, IT_KEY, KEY_1, 0, 0, "", // precache "models/keys/key.wav", // sounds //{0,0,0,0} }, */ // end of list marker {NULL} }; // END JOSEPH int bg_numItems = sizeof( bg_itemlist ) / sizeof( bg_itemlist[0] ) - 1; /* ============== BG_FindItemForHoldable ============== */ gitem_t *BG_FindItemForHoldable( holdable_t pw ) { int i; for ( i = 0 ; i < bg_numItems ; i++ ) { if ( bg_itemlist[i].giType == IT_HOLDABLE && bg_itemlist[i].giTag == pw ) { return &bg_itemlist[i]; } } // Com_Error( ERR_DROP, "HoldableItem not found" ); return NULL; } /* =============== BG_FindItemForWeapon =============== */ gitem_t *BG_FindItemForWeapon( weapon_t weapon ) { gitem_t *it; for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( it->giType == IT_WEAPON && it->giTag == weapon ) { return it; } } Com_Error( ERR_DROP, "Couldn't find item for weapon %i", weapon ); return NULL; } //----(SA) added #define DEATHMATCH_SHARED_AMMO 0 /* ============== BG_FindClipForWeapon ============== */ weapon_t BG_FindClipForWeapon( weapon_t weapon ) { gitem_t *it; for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( it->giType == IT_WEAPON && it->giTag == weapon ) { return it->giClipIndex; } } return 0; } /* ============== BG_FindAmmoForWeapon ============== */ weapon_t BG_FindAmmoForWeapon( weapon_t weapon ) { gitem_t *it; for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( it->giType == IT_WEAPON && it->giTag == weapon ) { return it->giAmmoIndex; } } return 0; } /* ============== BG_AkimboFireSequence returns 'true' if it's the left hand's turn to fire, 'false' if it's the right hand's turn ============== */ qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int mainClip ) { if ( !BG_IsAkimboWeapon( weapon ) ) { return qfalse; } if ( !akimboClip ) { return qfalse; } // no ammo in main weapon, must be akimbo turn if ( !mainClip ) { return qtrue; } // at this point, both have ammo // now check 'cycle' // (removed old method 11/5/2001) if ( ( akimboClip + mainClip ) & 1 ) { return qfalse; } return qtrue; } /* ============== BG_IsAkimboWeapon ============== */ qboolean BG_IsAkimboWeapon( int weaponNum ) { if ( weaponNum == WP_AKIMBO_COLT || weaponNum == WP_AKIMBO_SILENCEDCOLT || weaponNum == WP_AKIMBO_LUGER || weaponNum == WP_AKIMBO_SILENCEDLUGER ) { return qtrue; } else { return qfalse; } } /* ============== BG_IsAkimboSideArm ============== */ qboolean BG_IsAkimboSideArm( int weaponNum, playerState_t *ps ) { switch ( weaponNum ) { case WP_COLT: if ( ps->weapon == WP_AKIMBO_COLT || ps->weapon == WP_AKIMBO_SILENCEDCOLT ) { return qtrue; } break; case WP_LUGER: if ( ps->weapon == WP_AKIMBO_LUGER || ps->weapon == WP_AKIMBO_SILENCEDLUGER ) { return qtrue; } break; } return qfalse; } /* ============== BG_AkimboSidearm ============== */ int BG_AkimboSidearm( int weaponNum ) { switch ( weaponNum ) { case WP_AKIMBO_COLT: return WP_COLT; break; case WP_AKIMBO_SILENCEDCOLT: return WP_COLT; break; case WP_AKIMBO_LUGER: return WP_LUGER; break; case WP_AKIMBO_SILENCEDLUGER: return WP_LUGER; break; default: return WP_NONE; break; } } /* ============== BG_AkimboForSideArm ============== */ /*int BG_AkimboForSideArm( int weaponNum ) { switch( weaponNum ) { case WP_COLT: return WP_AKIMBO_COLT; break; case WP_SILENCED_COLT: return WP_AKIMBO_SILENCEDCOLT; break; case WP_LUGER: return WP_AKIMBO_LUGER; break; case WP_SILENCER: return WP_AKIMBO_SILENCEDLUGER; break; default: return WP_NONE; break; } }*/ //----(SA) Added keys /* ============== BG_FindItemForKey ============== */ /*gitem_t *BG_FindItemForKey(wkey_t k, int *indexreturn) { int i; for ( i = 0 ; i < bg_numItems ; i++ ) { if ( bg_itemlist[i].giType == IT_KEY && bg_itemlist[i].giTag == k ) { { if(indexreturn) *indexreturn = i; return &bg_itemlist[i]; } } } Com_Error( ERR_DROP, "Key %d not found", k ); return NULL; }*/ //----(SA) end //----(SA) added /* ============== BG_FindItemForAmmo ============== */ gitem_t *BG_FindItemForAmmo( int ammo ) { int i = 0; for (; i < bg_numItems; i++ ) { if ( bg_itemlist[i].giType == IT_AMMO && bg_itemlist[i].giAmmoIndex == ammo ) { return &bg_itemlist[i]; } } Com_Error( ERR_DROP, "Item not found for ammo: %d", ammo ); return NULL; } //----(SA) end /* =============== BG_FindItem =============== */ gitem_t *BG_FindItem( const char *pickupName ) { gitem_t *it; for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( !Q_stricmp( it->pickup_name, pickupName ) ) { return it; } } return NULL; } gitem_t *BG_FindItemForClassName( const char *className ) { gitem_t *it; for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( !Q_stricmp( it->classname, className ) ) { return it; } } return NULL; } // DHM - Nerve :: returns qtrue if a weapon is indeed used in multiplayer // Gordon: FIXME: er, we shouldnt really need this, just remove all the weapons we dont actually want :) qboolean BG_WeaponInWolfMP( int weapon ) { switch ( weapon ) { case WP_KNIFE: case WP_LUGER: case WP_COLT: case WP_MP40: case WP_THOMPSON: case WP_STEN: case WP_GRENADE_LAUNCHER: case WP_GRENADE_PINEAPPLE: case WP_PANZERFAUST: case WP_FLAMETHROWER: case WP_AMMO: case WP_ARTY: case WP_SMOKETRAIL: case WP_MEDKIT: case WP_PLIERS: case WP_SMOKE_MARKER: case WP_DYNAMITE: case WP_MEDIC_SYRINGE: case WP_MEDIC_ADRENALINE: case WP_BINOCULARS: case WP_KAR98: case WP_GPG40: case WP_CARBINE: case WP_M7: case WP_GARAND: case WP_GARAND_SCOPE: case WP_FG42: case WP_FG42SCOPE: case WP_LANDMINE: case WP_SATCHEL: case WP_SATCHEL_DET: // case WP_TRIPMINE: // bye bye tripmines ;( case WP_SMOKE_BOMB: case WP_MOBILE_MG42: case WP_MOBILE_MG42_SET: case WP_SILENCER: case WP_SILENCED_COLT: case WP_K43: case WP_K43_SCOPE: case WP_MORTAR: case WP_MORTAR_SET: //case WP_LOCKPICK: case WP_AKIMBO_LUGER: case WP_AKIMBO_SILENCEDLUGER: case WP_AKIMBO_COLT: case WP_AKIMBO_SILENCEDCOLT: return qtrue; default: return qfalse; } } /* ============ BG_PlayerTouchesItem Items can be picked up without actually touching their physical bounds to make grabbing them easier ============ */ qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ) { vec3_t origin; BG_EvaluateTrajectory( &item->pos, atTime, origin, qfalse, item->effect2Time ); // we are ignoring ducked differences here if ( ps->origin[0] - origin[0] > 36 || ps->origin[0] - origin[0] < -36 || ps->origin[1] - origin[1] > 36 || ps->origin[1] - origin[1] < -36 || ps->origin[2] - origin[2] > 36 || ps->origin[2] - origin[2] < -36 ) { return qfalse; } return qtrue; } /* ================================= BG_AddMagicAmmo: if numOfClips is 0, no ammo is added, it just return whether any ammo CAN be added; otherwise return whether any ammo was ACTUALLY added. WARNING: when numOfClips is 0, DO NOT CHANGE ANYTHING under ps. ================================= */ int BG_GrenadesForClass( int cls, int* skills ) { switch ( cls ) { case PC_MEDIC: if ( skills[SK_FIRST_AID] >= 1 ) { return 2; } return 1; case PC_SOLDIER: return 4; case PC_ENGINEER: return 8; case PC_FIELDOPS: if ( skills[SK_SIGNALS] >= 1 ) { return 2; } return 1; case PC_COVERTOPS: return 2; } return 0; } weapon_t BG_GrenadeTypeForTeam( team_t team ) { switch ( team ) { case TEAM_AXIS: return WP_GRENADE_LAUNCHER; case TEAM_ALLIES: return WP_GRENADE_PINEAPPLE; default: return WP_NONE; } } // Gordon: setting numOfClips = 0 allows you to check if the client needs ammo, but doesnt give any qboolean BG_AddMagicAmmo( playerState_t *ps, int *skill, int teamNum, int numOfClips ) { int i, weapon; int ammoAdded = qfalse; int maxammo; int clip; int weapNumOfClips; // Gordon: handle grenades first i = BG_GrenadesForClass( ps->stats[STAT_PLAYER_CLASS], skill ); weapon = BG_GrenadeTypeForTeam( teamNum ); clip = BG_FindClipForWeapon( weapon ); if ( ps->ammoclip[clip] < i ) { // Gordon: early out if ( !numOfClips ) { return qtrue; } ps->ammoclip[clip] += numOfClips; ammoAdded = qtrue; COM_BitSet( ps->weapons, weapon ); if ( ps->ammoclip[clip] > i ) { ps->ammoclip[clip] = i; } } if ( COM_BitCheck( ps->weapons, WP_MEDIC_SYRINGE ) ) { i = skill[ SK_FIRST_AID ] >= 2 ? 12 : 10; clip = BG_FindClipForWeapon( WP_MEDIC_SYRINGE ); if ( ps->ammoclip[ clip ] < i ) { if ( !numOfClips ) { return qtrue; } ps->ammoclip[ clip ] += numOfClips; ammoAdded = qtrue; if ( ps->ammoclip[ clip ] > i ) { ps->ammoclip[ clip ] = i; } } } // Gordon: now other weapons for ( i = 0; reloadableWeapons[i] >= 0; i++ ) { weapon = reloadableWeapons[i]; if ( COM_BitCheck( ps->weapons, weapon ) ) { maxammo = BG_MaxAmmoForWeapon( weapon, skill ); // Handle weapons that just use clip, and not ammo if ( weapon == WP_FLAMETHROWER ) { clip = BG_FindAmmoForWeapon( weapon ); if ( ps->ammoclip[clip] < maxammo ) { // early out if ( !numOfClips ) { return qtrue; } ammoAdded = qtrue; ps->ammoclip[clip] = maxammo; } } else if ( weapon == WP_PANZERFAUST ) { //% || weapon == WP_MORTAR ) { clip = BG_FindAmmoForWeapon( weapon ); if ( ps->ammoclip[clip] < maxammo ) { // early out if ( !numOfClips ) { return qtrue; } ammoAdded = qtrue; ps->ammoclip[clip] += numOfClips; if ( ps->ammoclip[clip] >= maxammo ) { ps->ammoclip[clip] = maxammo; } } } else { clip = BG_FindAmmoForWeapon( weapon ); if ( ps->ammo[clip] < maxammo ) { // early out if ( !numOfClips ) { return qtrue; } ammoAdded = qtrue; if ( BG_IsAkimboWeapon( weapon ) ) { weapNumOfClips = numOfClips * 2; // double clips babeh! } else { weapNumOfClips = numOfClips; } // add and limit check ps->ammo[clip] += weapNumOfClips * GetAmmoTableData( weapon )->maxclip; if ( ps->ammo[clip] > maxammo ) { ps->ammo[clip] = maxammo; } } } } } return ammoAdded; } /* ================ BG_CanUseWeapon: can a player of the specified team and class use this weapon? extracted and adapted from Bot_GetWeaponForClassAndTeam. ================ - added by xkan, 01/02/03 */ qboolean BG_CanUseWeapon( int classNum, int teamNum, weapon_t weapon ) { // TAT 1/11/2003 - is this SP game? - different weapons available in SP qboolean isSinglePlayer = BG_IsSinglePlayerGame() ? qtrue : qfalse; switch ( classNum ) { case PC_ENGINEER: if ( weapon == WP_PLIERS || weapon == WP_DYNAMITE || weapon == WP_LANDMINE ) { return qtrue; } else if ( weapon == WP_MP40 || weapon == WP_KAR98 ) { return ( teamNum == TEAM_AXIS ); } else if ( weapon == WP_THOMPSON || weapon == WP_CARBINE ) { return ( teamNum == TEAM_ALLIES ); } case PC_FIELDOPS: // TAT 1/11/2003 - in SP, field op can only use handgun, check after switch below if ( isSinglePlayer && teamNum == TEAM_ALLIES ) { break; } if ( weapon == WP_STEN ) { return qtrue; } else if ( weapon == WP_MP40 ) { return ( teamNum == TEAM_AXIS ); } else if ( weapon == WP_THOMPSON ) { return ( teamNum == TEAM_ALLIES ); } break; case PC_SOLDIER: if ( weapon == WP_STEN || weapon == WP_PANZERFAUST || weapon == WP_FLAMETHROWER // Gordon: shouldn't this only be for cvt ops? || weapon == WP_FG42 || weapon == WP_MOBILE_MG42 || weapon == WP_MOBILE_MG42_SET || weapon == WP_MORTAR || weapon == WP_MORTAR_SET ) { return qtrue; } else if ( weapon == WP_MP40 ) { return ( teamNum == TEAM_AXIS ); } else if ( weapon == WP_THOMPSON ) { return ( teamNum == TEAM_ALLIES ); } break; case PC_MEDIC: if ( weapon == WP_MEDIC_SYRINGE || weapon == WP_MEDKIT ) { return qtrue; } // TAT 1/11/2003 - in SP, medic can only use handgun, check after switch below else if ( isSinglePlayer && teamNum == TEAM_ALLIES ) { break; } else if ( weapon == WP_MP40 ) { return ( teamNum == TEAM_AXIS ); } else if ( weapon == WP_THOMPSON ) { return ( teamNum == TEAM_ALLIES ); } break; case PC_COVERTOPS: if ( weapon == WP_STEN || weapon == WP_SMOKE_BOMB || weapon == WP_SATCHEL || weapon == WP_AMMO // Gordon: this is a cvt ops weapon in single player too, right? || weapon == WP_FG42 ) { return qtrue; } else if ( weapon == WP_K43 ) { return ( teamNum == TEAM_AXIS ); } else if ( weapon == WP_GARAND ) { return ( teamNum == TEAM_ALLIES ); } break; } if ( weapon == WP_NONE || weapon == WP_KNIFE || weapon == WP_LUGER || weapon == WP_COLT ) { return qtrue; } // if not any of the above return qfalse; } #define AMMOFORWEAP BG_FindAmmoForWeapon( item->giTag ) /* ================ BG_CanItemBeGrabbed Returns false if the item should not be picked up. This needs to be the same for client side prediction and server use. ================ */ qboolean BG_CanItemBeGrabbed( const entityState_t *ent, const playerState_t *ps, int *skill, int teamNum ) { gitem_t *item; if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) { Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" ); } item = &bg_itemlist[ent->modelindex]; switch ( item->giType ) { case IT_WEAPON: if ( item->giTag == WP_AMMO ) { // magic ammo for any two-handed weapon // xkan, 11/21/2002 - only pick up if ammo is not full, numClips is 0, so ps will // NOT be changed (I know, it places the burden on the programmer, rather than the // compiler, to ensure that). return BG_AddMagicAmmo( (playerState_t *)ps, skill, teamNum, 0 ); // Arnout: had to cast const away } return qtrue; case IT_AMMO: return qfalse; case IT_ARMOR: return qfalse; case IT_HEALTH: // Gordon: ps->teamNum is really class.... thx whoever decided on that... if ( ps->teamNum == PC_MEDIC ) { // Gordon: medics can go up to 12% extra on max health as they have perm. regen if ( ps->stats[STAT_HEALTH] >= (int)( ps->stats[STAT_MAX_HEALTH] * 1.12 ) ) { return qfalse; } } else { if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] ) { return qfalse; } } return qtrue; case IT_TEAM: // team items, such as flags // density tracks how many uses left if ( ( ent->density < 1 ) || ( ( ( ps->persistant[PERS_TEAM] == TEAM_AXIS ) ? ps->powerups[PW_BLUEFLAG] : ps->powerups[PW_REDFLAG] ) != 0 ) ) { return qfalse; } // DHM - Nerve :: otherEntity2 is now used instead of modelindex2 // ent->modelindex2 is non-zero on items if they are dropped // we need to know this because we can pick up our dropped flag (and return it) // but we can't pick up our flag at base if ( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if ( item->giTag == PW_BLUEFLAG || ( item->giTag == PW_REDFLAG && ent->otherEntityNum2 /*ent->modelindex2*/ ) || ( item->giTag == PW_REDFLAG && ps->powerups[PW_BLUEFLAG] ) ) { return qtrue; } } else if ( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if ( item->giTag == PW_REDFLAG || ( item->giTag == PW_BLUEFLAG && ent->otherEntityNum2 /*ent->modelindex2*/ ) || ( item->giTag == PW_BLUEFLAG && ps->powerups[PW_REDFLAG] ) ) { return qtrue; } } return qfalse; case IT_HOLDABLE: return qtrue; case IT_TREASURE: // treasure always picked up return qtrue; case IT_KEY: return qtrue; // keys are always picked up case IT_BAD: Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD" ); } return qfalse; } //====================================================================== void BG_CalculateSpline_r( splinePath_t* spline, vec3_t out1, vec3_t out2, float tension ) { vec3_t points[18]; int i; int count = spline->numControls + 2; vec3_t dist; VectorCopy( spline->point.origin, points[0] ); for ( i = 0; i < spline->numControls; i++ ) { VectorCopy( spline->controls[i].origin, points[i + 1] ); } if ( !spline->next ) { return; // Com_Error( ERR_DROP, "Spline (%s) with no target referenced", spline->point.name ); } VectorCopy( spline->next->point.origin, points[i + 1] ); while ( count > 2 ) { for ( i = 0; i < count - 1; i++ ) { VectorSubtract( points[i + 1], points[i], dist ); VectorMA( points[i], tension, dist, points[i] ); } count--; } VectorCopy( points[0], out1 ); VectorCopy( points[1], out2 ); } qboolean BG_TraverseSpline( float* deltaTime, splinePath_t** pSpline ) { float dist; while ( ( *deltaTime ) > 1 ) { ( *deltaTime ) -= 1; dist = ( *pSpline )->length * ( *deltaTime ); if ( !( *pSpline )->next || !( *pSpline )->next->length ) { return qfalse; // Com_Error( ERR_DROP, "Spline path end passed (%s)", (*pSpline)->point.name ); } ( *pSpline ) = ( *pSpline )->next; *deltaTime = dist / ( *pSpline )->length; } while ( ( *deltaTime ) < 0 ) { dist = -( ( *pSpline )->length * ( *deltaTime ) ); if ( !( *pSpline )->prev || !( *pSpline )->prev->length ) { return qfalse; // Com_Error( ERR_DROP, "Spline path end passed (%s)", (*pSpline)->point.name ); } ( *pSpline ) = ( *pSpline )->prev; ( *deltaTime ) = 1 - ( dist / ( *pSpline )->length ); } return qtrue; } /* ================ BG_RaySphereIntersection ================ */ qboolean BG_RaySphereIntersection( float radius, vec3_t origin, splineSegment_t* path, float *t0, float *t1 ) { vec3_t v; float b, c, d; VectorSubtract( path->start, origin, v ); b = 2 * DotProduct( v, path->v_norm ); c = DotProduct( v, v ) - ( radius * radius ); d = ( b * b ) - ( 4 * c ); if ( d < 0 ) { return qfalse; } d = sqrt( d ); *t0 = ( -b + d ) * 0.5f; *t1 = ( -b - d ) * 0.5f; return qtrue; } void BG_LinearPathOrigin2( float radius, splinePath_t** pSpline, float *deltaTime, vec3_t result, qboolean backwards ) { qboolean first = qtrue; float t = 0.f; int i = floor( ( *deltaTime ) * ( MAX_SPLINE_SEGMENTS ) ); float frac; // int x = 0; // splinePath_t* start = *pSpline; if ( i >= MAX_SPLINE_SEGMENTS ) { i = MAX_SPLINE_SEGMENTS - 1; frac = 1.f; } else { frac = ( ( ( *deltaTime ) * ( MAX_SPLINE_SEGMENTS ) ) - i ); } while ( qtrue ) { float t0, t1; while ( qtrue ) { if ( BG_RaySphereIntersection( radius, result, &( *pSpline )->segments[i], &t0, &t1 ) ) { qboolean found = qfalse; t0 /= ( *pSpline )->segments[i].length; t1 /= ( *pSpline )->segments[i].length; if ( first ) { if ( radius < 0 ) { if ( t0 < frac && ( t0 >= 0.f && t0 <= 1.f ) ) { t = t0; found = qtrue; } else if ( t1 < frac ) { t = t1; found = qtrue; } } else { if ( t0 > frac && ( t0 >= 0.f && t0 <= 1.f ) ) { t = t0; found = qtrue; } else if ( t1 > frac ) { t = t1; found = qtrue; } } } else { if ( radius < 0 ) { if ( t0 < t1 && ( t0 >= 0.f && t0 <= 1.f ) ) { t = t0; found = qtrue; } else { t = t1; found = qtrue; } } else { if ( t0 > t1 && ( t0 >= 0.f && t0 <= 1.f ) ) { t = t0; found = qtrue; } else { t = t1; found = qtrue; } } } if ( found ) { if ( t >= 0.f && t <= 1.f ) { *deltaTime = ( i / (float)( MAX_SPLINE_SEGMENTS ) ) + ( t / (float)( MAX_SPLINE_SEGMENTS ) ); VectorMA( ( *pSpline )->segments[i].start, t * ( *pSpline )->segments[i].length, ( *pSpline )->segments[i].v_norm, result ); return; } } found = qfalse; } first = qfalse; if ( radius < 0 ) { i--; if ( i < 0 ) { i = MAX_SPLINE_SEGMENTS - 1; break; } } else { i++; if ( i >= MAX_SPLINE_SEGMENTS ) { i = 0; break; } } } if ( radius < 0 ) { if ( !( *pSpline )->prev ) { return; // Com_Error( ERR_DROP, "End of spline reached (%s)\n", start->point.name ); } *pSpline = ( *pSpline )->prev; } else { if ( !( *pSpline )->next ) { return; // Com_Error( ERR_DROP, "End of spline reached (%s)\n", start->point.name ); } *pSpline = ( *pSpline )->next; } } } void BG_ComputeSegments( splinePath_t* pSpline ) { int i; float granularity = 1 / ( (float)( MAX_SPLINE_SEGMENTS ) ); vec3_t vec[4]; for ( i = 0; i < MAX_SPLINE_SEGMENTS; i++ ) { BG_CalculateSpline_r( pSpline, vec[0], vec[1], i * granularity ); VectorSubtract( vec[1], vec[0], pSpline->segments[i].start ); VectorMA( vec[0], i * granularity, pSpline->segments[i].start, pSpline->segments[i].start ); BG_CalculateSpline_r( pSpline, vec[2], vec[3], ( i + 1 ) * granularity ); VectorSubtract( vec[3], vec[2], vec[0] ); VectorMA( vec[2], ( i + 1 ) * granularity, vec[0], vec[0] ); VectorSubtract( vec[0], pSpline->segments[i].start, pSpline->segments[i].v_norm ); pSpline->segments[i].length = VectorLength( pSpline->segments[i].v_norm ); VectorNormalize( pSpline->segments[i].v_norm ); } } /* ================ BG_EvaluateTrajectory ================ */ void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result, qboolean isAngle, int splinePath ) { float deltaTime; float phase; vec3_t v; splinePath_t* pSpline; vec3_t vec[2]; qboolean backwards = qfalse; float deltaTime2; switch ( tr->trType ) { case TR_STATIONARY: case TR_INTERPOLATE: case TR_GRAVITY_PAUSED: //----(SA) VectorCopy( tr->trBase, result ); break; case TR_LINEAR: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); break; case TR_SINE: deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration; phase = sin( deltaTime * M_PI * 2 ); VectorMA( tr->trBase, phase, tr->trDelta, result ); break; //----(SA) removed case TR_LINEAR_STOP: if ( atTime > tr->trTime + tr->trDuration ) { atTime = tr->trTime + tr->trDuration; } deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds if ( deltaTime < 0 ) { deltaTime = 0; } VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); break; case TR_GRAVITY: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); result[2] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity... break; // Ridah case TR_GRAVITY_LOW: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); result[2] -= 0.5 * ( DEFAULT_GRAVITY * 0.3 ) * deltaTime * deltaTime; // FIXME: local gravity... break; // done. //----(SA) case TR_GRAVITY_FLOAT: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); result[2] -= 0.5 * ( DEFAULT_GRAVITY * 0.2 ) * deltaTime; break; //----(SA) end // RF, acceleration case TR_ACCELERATE: // trDelta is the ultimate speed if ( atTime > tr->trTime + tr->trDuration ) { atTime = tr->trTime + tr->trDuration; } deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds // phase is the acceleration constant phase = VectorLength( tr->trDelta ) / ( tr->trDuration * 0.001 ); // trDelta at least gives us the acceleration direction VectorNormalize2( tr->trDelta, result ); // get distance travelled at current time VectorMA( tr->trBase, phase * 0.5 * deltaTime * deltaTime, result, result ); break; case TR_DECCELERATE: // trDelta is the starting speed if ( atTime > tr->trTime + tr->trDuration ) { atTime = tr->trTime + tr->trDuration; } deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds // phase is the breaking constant phase = VectorLength( tr->trDelta ) / ( tr->trDuration * 0.001 ); // trDelta at least gives us the acceleration direction VectorNormalize2( tr->trDelta, result ); // get distance travelled at current time (without breaking) VectorMA( tr->trBase, deltaTime, tr->trDelta, v ); // subtract breaking force VectorMA( v, -phase * 0.5 * deltaTime * deltaTime, result, result ); break; case TR_SPLINE: if ( !( pSpline = BG_GetSplineData( splinePath, &backwards ) ) ) { return; } deltaTime = tr->trDuration ? ( atTime - tr->trTime ) / ( (float)tr->trDuration ) : 0; if ( deltaTime < 0.f ) { deltaTime = 0.f; } else if ( deltaTime > 1.f ) { deltaTime = 1.f; } if ( backwards ) { deltaTime = 1 - deltaTime; } /* if(pSpline->isStart) { deltaTime = 1 - sin((1 - deltaTime) * M_PI * 0.5f); } else if(pSpline->isEnd) { deltaTime = sin(deltaTime * M_PI * 0.5f); }*/ deltaTime2 = deltaTime; BG_CalculateSpline_r( pSpline, vec[0], vec[1], deltaTime ); if ( isAngle ) { qboolean dampin = qfalse; qboolean dampout = qfalse; float base1; if ( tr->trBase[0] ) { // int pos = 0; vec3_t result2; splinePath_t* pSp2 = pSpline; deltaTime2 += tr->trBase[0] / pSpline->length; if ( BG_TraverseSpline( &deltaTime2, &pSp2 ) ) { VectorSubtract( vec[1], vec[0], result ); VectorMA( vec[0], deltaTime, result, result ); BG_CalculateSpline_r( pSp2, vec[0], vec[1], deltaTime2 ); VectorSubtract( vec[1], vec[0], result2 ); VectorMA( vec[0], deltaTime2, result2, result2 ); if ( tr->trBase[0] < 0 ) { VectorSubtract( result, result2, result ); } else { VectorSubtract( result2, result, result ); } } else { VectorSubtract( vec[1], vec[0], result ); } } else { VectorSubtract( vec[1], vec[0], result ); } vectoangles( result, result ); base1 = tr->trBase[1]; if ( base1 >= 10000 || base1 < -10000 ) { dampin = qtrue; if ( base1 < 0 ) { base1 += 10000; } else { base1 -= 10000; } } if ( base1 >= 1000 || base1 < -1000 ) { dampout = qtrue; if ( base1 < 0 ) { base1 += 1000; } else { base1 -= 1000; } } if ( dampin && dampout ) { result[ROLL] = base1 + ( ( sin( ( ( deltaTime * 2 ) - 1 ) * M_PI * 0.5f ) + 1 ) * 0.5f * tr->trBase[2] ); } else if ( dampin ) { result[ROLL] = base1 + ( sin( deltaTime * M_PI * 0.5f ) * tr->trBase[2] ); } else if ( dampout ) { result[ROLL] = base1 + ( ( 1 - sin( ( 1 - deltaTime ) * M_PI * 0.5f ) ) * tr->trBase[2] ); } else { result[ROLL] = base1 + ( deltaTime * tr->trBase[2] ); } } else { VectorSubtract( vec[1], vec[0], result ); VectorMA( vec[0], deltaTime, result, result ); } break; case TR_LINEAR_PATH: if ( !( pSpline = BG_GetSplineData( splinePath, &backwards ) ) ) { return; } deltaTime = tr->trDuration ? ( atTime - tr->trTime ) / ( (float)tr->trDuration ) : 0; if ( deltaTime < 0.f ) { deltaTime = 0.f; } else if ( deltaTime > 1.f ) { deltaTime = 1.f; } if ( backwards ) { deltaTime = 1 - deltaTime; } if ( isAngle ) { int pos = floor( deltaTime * ( MAX_SPLINE_SEGMENTS ) ); float frac; if ( pos >= MAX_SPLINE_SEGMENTS ) { pos = MAX_SPLINE_SEGMENTS - 1; frac = pSpline->segments[pos].length; } else { frac = ( ( deltaTime * ( MAX_SPLINE_SEGMENTS ) ) - pos ) * pSpline->segments[pos].length; } if ( tr->trBase[0] ) { VectorMA( pSpline->segments[pos].start, frac, pSpline->segments[pos].v_norm, result ); VectorCopy( result, v ); BG_LinearPathOrigin2( tr->trBase[0], &pSpline, &deltaTime, v, backwards ); if ( tr->trBase[0] < 0 ) { VectorSubtract( v, result, result ); } else { VectorSubtract( result, v, result ); } vectoangles( result, result ); } else { vectoangles( pSpline->segments[pos].v_norm, result ); } } else { int pos = floor( deltaTime * ( MAX_SPLINE_SEGMENTS ) ); float frac; if ( pos >= MAX_SPLINE_SEGMENTS ) { pos = MAX_SPLINE_SEGMENTS - 1; frac = pSpline->segments[pos].length; } else { frac = ( ( deltaTime * ( MAX_SPLINE_SEGMENTS ) ) - pos ) * pSpline->segments[pos].length; } VectorMA( pSpline->segments[pos].start, frac, pSpline->segments[pos].v_norm, result ); } break; default: Com_Error( ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime ); break; } } /* ================ BG_EvaluateTrajectoryDelta For determining velocity at a given time ================ */ void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result, qboolean isAngle, int splineData ) { float deltaTime; float phase; switch ( tr->trType ) { case TR_STATIONARY: case TR_INTERPOLATE: VectorClear( result ); break; case TR_LINEAR: VectorCopy( tr->trDelta, result ); break; case TR_SINE: deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration; phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos phase *= 0.5; VectorScale( tr->trDelta, phase, result ); break; //----(SA) removed case TR_LINEAR_STOP: if ( atTime > tr->trTime + tr->trDuration ) { VectorClear( result ); return; } VectorCopy( tr->trDelta, result ); break; case TR_GRAVITY: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorCopy( tr->trDelta, result ); result[2] -= DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity... break; // Ridah case TR_GRAVITY_LOW: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorCopy( tr->trDelta, result ); result[2] -= ( DEFAULT_GRAVITY * 0.3 ) * deltaTime; // FIXME: local gravity... break; // done. //----(SA) case TR_GRAVITY_FLOAT: deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorCopy( tr->trDelta, result ); result[2] -= ( DEFAULT_GRAVITY * 0.2 ) * deltaTime; break; //----(SA) end // RF, acceleration case TR_ACCELERATE: // trDelta is eventual speed if ( atTime > tr->trTime + tr->trDuration ) { VectorClear( result ); return; } deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds phase = deltaTime / (float)tr->trDuration; VectorScale( tr->trDelta, deltaTime * deltaTime, result ); break; case TR_DECCELERATE: // trDelta is breaking force if ( atTime > tr->trTime + tr->trDuration ) { VectorClear( result ); return; } deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds VectorScale( tr->trDelta, deltaTime, result ); break; case TR_SPLINE: case TR_LINEAR_PATH: VectorClear( result ); break; default: Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime ); break; } } /* ============ BG_GetMarkDir used to find a good directional vector for a mark projection, which will be more likely to wrap around adjacent surfaces dir is the direction of the projectile or trace that has resulted in a surface being hit ============ */ void BG_GetMarkDir( const vec3_t dir, const vec3_t normal, vec3_t out ) { vec3_t ndir, lnormal; float minDot = 0.3; int x = 0; if ( dir[0] < 0.001 && dir[1] < 0.001 ) { VectorCopy( dir, out ); return; } if ( VectorLengthSquared( normal ) < SQR( 1.f ) ) { // this is needed to get rid of (0,0,0) normals (happens with entities?) VectorSet( lnormal, 0.f, 0.f, 1.f ); } else { //VectorCopy( normal, lnormal ); //VectorNormalizeFast( lnormal ); VectorNormalize2( normal, lnormal ); } VectorNegate( dir, ndir ); VectorNormalize( ndir ); if ( normal[2] > .8f ) { minDot = .7f; } // make sure it makrs the impact surface while ( DotProduct( ndir, lnormal ) < minDot && x < 10 ) { VectorMA( ndir, .5, lnormal, ndir ); VectorNormalize( ndir ); x++; } #ifdef GAMEDLL if ( x >= 10 ) { if ( g_developer.integer ) { Com_Printf( "BG_GetMarkDir loops: %i\n", x ); } } #endif // GAMEDLL VectorCopy( ndir, out ); } char *eventnames[] = { "EV_NONE", "EV_FOOTSTEP", "EV_FOOTSTEP_METAL", "EV_FOOTSTEP_WOOD", "EV_FOOTSTEP_GRASS", "EV_FOOTSTEP_GRAVEL", "EV_FOOTSTEP_ROOF", "EV_FOOTSTEP_SNOW", "EV_FOOTSTEP_CARPET", "EV_FOOTSPLASH", "EV_FOOTWADE", "EV_SWIM", "EV_STEP_4", "EV_STEP_8", "EV_STEP_12", "EV_STEP_16", "EV_FALL_SHORT", "EV_FALL_MEDIUM", "EV_FALL_FAR", "EV_FALL_NDIE", "EV_FALL_DMG_10", "EV_FALL_DMG_15", "EV_FALL_DMG_25", "EV_FALL_DMG_50", "EV_JUMP", "EV_WATER_TOUCH", "EV_WATER_LEAVE", "EV_WATER_UNDER", "EV_WATER_CLEAR", "EV_ITEM_PICKUP", "EV_ITEM_PICKUP_QUIET", "EV_GLOBAL_ITEM_PICKUP", "EV_NOAMMO", "EV_WEAPONSWITCHED", "EV_EMPTYCLIP", "EV_FILL_CLIP", "EV_MG42_FIXED", "EV_WEAP_OVERHEAT", "EV_CHANGE_WEAPON", "EV_CHANGE_WEAPON_2", "EV_FIRE_WEAPON", "EV_FIRE_WEAPONB", "EV_FIRE_WEAPON_LASTSHOT", "EV_NOFIRE_UNDERWATER", "EV_FIRE_WEAPON_MG42", "EV_FIRE_WEAPON_MOUNTEDMG42", "EV_ITEM_RESPAWN", "EV_ITEM_POP", "EV_PLAYER_TELEPORT_IN", "EV_PLAYER_TELEPORT_OUT", "EV_GRENADE_BOUNCE", "EV_GENERAL_SOUND", "EV_GENERAL_SOUND_VOLUME", "EV_GLOBAL_SOUND", "EV_GLOBAL_CLIENT_SOUND", "EV_GLOBAL_TEAM_SOUND", "EV_FX_SOUND", "EV_BULLET_HIT_FLESH", "EV_BULLET_HIT_WALL", "EV_MISSILE_HIT", "EV_MISSILE_MISS", "EV_RAILTRAIL", "EV_VENOM", "EV_BULLET", "EV_LOSE_HAT", "EV_PAIN", "EV_CROUCH_PAIN", "EV_DEATH1", "EV_DEATH2", "EV_DEATH3", "EV_OBITUARY", "EV_STOPSTREAMINGSOUND", "EV_POWERUP_QUAD", "EV_POWERUP_BATTLESUIT", "EV_POWERUP_REGEN", "EV_GIB_PLAYER", "EV_DEBUG_LINE", "EV_STOPLOOPINGSOUND", "EV_TAUNT", "EV_SMOKE", "EV_SPARKS", "EV_SPARKS_ELECTRIC", "EV_EXPLODE", "EV_RUBBLE", "EV_EFFECT", "EV_MORTAREFX", "EV_SPINUP", "EV_SNOW_ON", "EV_SNOW_OFF", "EV_MISSILE_MISS_SMALL", "EV_MISSILE_MISS_LARGE", "EV_MORTAR_IMPACT", "EV_MORTAR_MISS", "EV_SHARD", "EV_JUNK", "EV_EMITTER", "EV_OILPARTICLES", "EV_OILSLICK", "EV_OILSLICKREMOVE", "EV_MG42EFX", "EV_FLAKGUN1", "EV_FLAKGUN2", "EV_FLAKGUN3", "EV_FLAKGUN4", "EV_EXERT1", "EV_EXERT2", "EV_EXERT3", "EV_SNOWFLURRY", "EV_CONCUSSIVE", "EV_DUST", "EV_RUMBLE_EFX", "EV_GUNSPARKS", "EV_FLAMETHROWER_EFFECT", "EV_POPUP", "EV_POPUPBOOK", "EV_GIVEPAGE", "EV_MG42BULLET_HIT_FLESH", "EV_MG42BULLET_HIT_WALL", "EV_SHAKE", "EV_DISGUISE_SOUND", "EV_BUILDDECAYED_SOUND", "EV_FIRE_WEAPON_AAGUN", "EV_DEBRIS", "EV_ALERT_SPEAKER", "EV_POPUPMESSAGE", "EV_ARTYMESSAGE", "EV_AIRSTRIKEMESSAGE", "EV_MEDIC_CALL", "EV_MAX_EVENTS", }; /* =============== BG_AddPredictableEventToPlayerstate Handles the sequence numbers =============== */ void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ); void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) { #ifdef _DEBUG { char buf[256]; trap_Cvar_VariableStringBuffer( "showevents", buf, sizeof( buf ) ); if ( atof( buf ) != 0 ) { #ifdef QAGAME Com_Printf( " game event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount /*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm ); #else Com_Printf( "Cgame event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount /*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm ); #endif } } #endif ps->events[ps->eventSequence & ( MAX_EVENTS - 1 )] = newEvent; ps->eventParms[ps->eventSequence & ( MAX_EVENTS - 1 )] = eventParm; ps->eventSequence++; } // Gordon: would like to just inline this but would likely break qvm support #define SETUP_MOUNTEDGUN_STATUS( ps ) \ switch ( ps->persistant[PERS_HWEAPON_USE] ) { \ case 1: \ ps->eFlags |= EF_MG42_ACTIVE; \ ps->eFlags &= ~EF_AAGUN_ACTIVE; \ ps->powerups[PW_OPS_DISGUISED] = 0; \ break; \ case 2: \ ps->eFlags |= EF_AAGUN_ACTIVE; \ ps->eFlags &= ~EF_MG42_ACTIVE; \ ps->powerups[PW_OPS_DISGUISED] = 0; \ break; \ default: \ ps->eFlags &= ~EF_MG42_ACTIVE; \ ps->eFlags &= ~EF_AAGUN_ACTIVE; \ break; \ } /* ======================== BG_PlayerStateToEntityState This is done after each set of usercmd_t on the server, and after local prediction on the client ======================== */ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ) { int i; if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) { // || ps->pm_flags & PMF_LIMBO ) { // JPW NERVE limbo s->eType = ET_INVISIBLE; } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { s->eType = ET_INVISIBLE; } else { s->eType = ET_PLAYER; } s->number = ps->clientNum; s->pos.trType = TR_INTERPOLATE; VectorCopy( ps->origin, s->pos.trBase ); if ( snap ) { SnapVector( s->pos.trBase ); } s->apos.trType = TR_INTERPOLATE; VectorCopy( ps->viewangles, s->apos.trBase ); if ( snap ) { SnapVector( s->apos.trBase ); } if ( ps->movementDir > 128 ) { s->angles2[YAW] = (float)ps->movementDir - 256; } else { s->angles2[YAW] = ps->movementDir; } s->legsAnim = ps->legsAnim; s->torsoAnim = ps->torsoAnim; s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number // so corpses can also reference the proper config // Ridah, let clients know if this person is using a mounted weapon // so they don't show any client muzzle flashes if ( ps->eFlags & EF_MOUNTEDTANK ) { ps->eFlags &= ~EF_MG42_ACTIVE; ps->eFlags &= ~EF_AAGUN_ACTIVE; } else { SETUP_MOUNTEDGUN_STATUS( ps ); } s->eFlags = ps->eFlags; if ( ps->stats[STAT_HEALTH] <= 0 ) { s->eFlags |= EF_DEAD; } else { s->eFlags &= ~EF_DEAD; } // from MP if ( ps->externalEvent ) { s->event = ps->externalEvent; s->eventParm = ps->externalEventParm; } else if ( ps->entityEventSequence < ps->eventSequence ) { int seq; if ( ps->entityEventSequence < ps->eventSequence - MAX_EVENTS ) { ps->entityEventSequence = ps->eventSequence - MAX_EVENTS; } seq = ps->entityEventSequence & ( MAX_EVENTS - 1 ); s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 ); s->eventParm = ps->eventParms[ seq ]; ps->entityEventSequence++; } // end // Ridah, now using a circular list of events for all entities // add any new events that have been added to the playerState_t // (possibly overwriting entityState_t events) for ( i = ps->oldEventSequence; i != ps->eventSequence; i++ ) { s->events[s->eventSequence & ( MAX_EVENTS - 1 )] = ps->events[i & ( MAX_EVENTS - 1 )]; s->eventParms[s->eventSequence & ( MAX_EVENTS - 1 )] = ps->eventParms[i & ( MAX_EVENTS - 1 )]; s->eventSequence++; } ps->oldEventSequence = ps->eventSequence; s->weapon = ps->weapon; s->groundEntityNum = ps->groundEntityNum; s->powerups = 0; for ( i = 0 ; i < MAX_POWERUPS ; i++ ) { if ( ps->powerups[ i ] ) { s->powerups |= 1 << i; } } s->nextWeapon = ps->nextWeapon; // Ridah // s->loopSound = ps->loopSound; s->teamNum = ps->teamNum; s->aiState = ps->aiState; // xkan, 1/10/2003 } /* ======================== BG_PlayerStateToEntityStateExtraPolate This is done after each set of usercmd_t on the server, and after local prediction on the client ======================== */ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap ) { int i; if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) { // || ps->pm_flags & PMF_LIMBO ) { // JPW NERVE limbo s->eType = ET_INVISIBLE; } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { s->eType = ET_INVISIBLE; } else { s->eType = ET_PLAYER; } s->number = ps->clientNum; s->pos.trType = TR_LINEAR_STOP; VectorCopy( ps->origin, s->pos.trBase ); if ( snap ) { SnapVector( s->pos.trBase ); } // set the trDelta for flag direction and linear prediction VectorCopy( ps->velocity, s->pos.trDelta ); // set the time for linear prediction s->pos.trTime = time; // set maximum extra polation time s->pos.trDuration = 50; // 1000 / sv_fps (default = 20) s->apos.trType = TR_INTERPOLATE; VectorCopy( ps->viewangles, s->apos.trBase ); if ( snap ) { SnapVector( s->apos.trBase ); } s->angles2[YAW] = ps->movementDir; s->legsAnim = ps->legsAnim; s->torsoAnim = ps->torsoAnim; s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number // so corpses can also reference the proper config if ( ps->eFlags & EF_MOUNTEDTANK ) { ps->eFlags &= ~EF_MG42_ACTIVE; ps->eFlags &= ~EF_AAGUN_ACTIVE; } else { SETUP_MOUNTEDGUN_STATUS( ps ); } s->eFlags = ps->eFlags; if ( ps->stats[STAT_HEALTH] <= 0 ) { s->eFlags |= EF_DEAD; } else { s->eFlags &= ~EF_DEAD; } if ( ps->externalEvent ) { s->event = ps->externalEvent; s->eventParm = ps->externalEventParm; } else if ( ps->entityEventSequence < ps->eventSequence ) { int seq; if ( ps->entityEventSequence < ps->eventSequence - MAX_EVENTS ) { ps->entityEventSequence = ps->eventSequence - MAX_EVENTS; } seq = ps->entityEventSequence & ( MAX_EVENTS - 1 ); s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 ); s->eventParm = ps->eventParms[ seq ]; ps->entityEventSequence++; } // Ridah, now using a circular list of events for all entities // add any new events that have been added to the playerState_t // (possibly overwriting entityState_t events) for ( i = ps->oldEventSequence; i != ps->eventSequence; i++ ) { s->events[s->eventSequence & ( MAX_EVENTS - 1 )] = ps->events[i & ( MAX_EVENTS - 1 )]; s->eventParms[s->eventSequence & ( MAX_EVENTS - 1 )] = ps->eventParms[i & ( MAX_EVENTS - 1 )]; s->eventSequence++; } ps->oldEventSequence = ps->eventSequence; s->weapon = ps->weapon; s->groundEntityNum = ps->groundEntityNum; s->powerups = 0; for ( i = 0 ; i < MAX_POWERUPS ; i++ ) { if ( ps->powerups[ i ] ) { s->powerups |= 1 << i; } } s->nextWeapon = ps->nextWeapon; // Ridah s->teamNum = ps->teamNum; s->aiState = ps->aiState; // xkan, 1/10/2003 } // Gordon: some weapons are duplicated for code puposes.... just want to treat them as a single weapon_t BG_DuplicateWeapon( weapon_t weap ) { switch ( weap ) { case WP_M7: return WP_GPG40; case WP_GARAND_SCOPE: return WP_GARAND; case WP_K43_SCOPE: return WP_K43; case WP_GRENADE_PINEAPPLE: return WP_GRENADE_LAUNCHER; default: return weap; } } gitem_t* BG_ValidStatWeapon( weapon_t weap ) { weapon_t weap2; switch ( weap ) { case WP_MEDKIT: case WP_PLIERS: case WP_SMOKETRAIL: case WP_MEDIC_SYRINGE: case WP_SMOKE_BOMB: case WP_AMMO: return NULL; default: break; } if ( !BG_WeaponInWolfMP( weap ) ) { return NULL; } weap2 = BG_DuplicateWeapon( weap ); if ( weap != weap2 ) { return NULL; } return BG_FindItemForWeapon( weap ); } weapon_t BG_WeaponForMOD( int MOD ) { weapon_t i; for ( i = 0; i < WP_NUM_WEAPONS; i++ ) { if ( GetAmmoTableData( i )->mod == MOD ) { return i; } } return 0; } const char* rankSoundNames_Allies[NUM_EXPERIENCE_LEVELS] = { "", "allies_hq_promo_private", "allies_hq_promo_corporal", "allies_hq_promo_sergeant", "allies_hq_promo_lieutenant", "allies_hq_promo_captain", "allies_hq_promo_major", "allies_hq_promo_colonel", "allies_hq_promo_general_brigadier", "allies_hq_promo_general_lieutenant", "allies_hq_promo_general", }; const char* rankSoundNames_Axis[NUM_EXPERIENCE_LEVELS] = { "", "axis_hq_promo_private", "axis_hq_promo_corporal", "axis_hq_promo_sergeant", "axis_hq_promo_lieutenant", "axis_hq_promo_captain", "axis_hq_promo_major", "axis_hq_promo_colonel", "axis_hq_promo_general_major", "axis_hq_promo_general_lieutenant", "axis_hq_promo_general", }; const char* rankNames_Axis[NUM_EXPERIENCE_LEVELS] = { "Schutze", "Oberschutze", "Gefreiter", "Feldwebel", "Leutnant", "Hauptmann", "Major", "Oberst", "Generalmajor", "Generalleutnant", "General", }; const char* rankNames_Allies[NUM_EXPERIENCE_LEVELS] = { "Private", "Private 1st Class", "Corporal", "Sergeant", "Lieutenant", "Captain", "Major", "Colonel", "Brigadier General", "Lieutenant General", "General", }; const char* miniRankNames_Axis[NUM_EXPERIENCE_LEVELS] = { "Stz", "Otz", "Gfr", "Fwb", "Ltn", "Hpt", "Mjr", "Obs", "BGn", "LtG", "Gen", }; const char* miniRankNames_Allies[NUM_EXPERIENCE_LEVELS] = { "Pvt", "PFC", "Cpl", "Sgt", "Lt", "Cpt", "Maj", "Cnl", "GMj", "GLt", "Gen", }; /* ============= BG_Find_PathCorner ============= */ pathCorner_t *BG_Find_PathCorner( const char *match ) { int i; for ( i = 0 ; i < numPathCorners; i++ ) { if ( !Q_stricmp( pathCorners[i].name, match ) ) { return &pathCorners[i]; } } return NULL; } /* ============= BG_AddPathCorner ============= */ void BG_AddPathCorner( const char* name, vec3_t origin ) { if ( numPathCorners >= MAX_PATH_CORNERS ) { Com_Error( ERR_DROP, "MAX PATH CORNERS (%i) hit", MAX_PATH_CORNERS ); } VectorCopy( origin, pathCorners[numPathCorners].origin ); Q_strncpyz( pathCorners[numPathCorners].name, name, 64 ); numPathCorners++; } /* ============= BG_Find_Spline ============= */ splinePath_t *BG_Find_Spline( const char *match ) { int i; for ( i = 0 ; i < numSplinePaths; i++ ) { if ( !Q_stricmp( splinePaths[i].point.name, match ) ) { return &splinePaths[i]; } } return NULL; } splinePath_t* BG_AddSplinePath( const char* name, const char* target, vec3_t origin ) { splinePath_t* spline; if ( numSplinePaths >= MAX_SPLINE_PATHS ) { Com_Error( ERR_DROP, "MAX SPLINES (%i) hit", MAX_SPLINE_PATHS ); } spline = &splinePaths[numSplinePaths]; memset( spline, 0, sizeof( splinePath_t ) ); VectorCopy( origin, spline->point.origin ); Q_strncpyz( spline->point.name, name, 64 ); Q_strncpyz( spline->strTarget, target ? target : "", 64 ); spline->numControls = 0; numSplinePaths++; return spline; } void BG_AddSplineControl( splinePath_t* spline, const char* name ) { if ( spline->numControls >= MAX_SPLINE_CONTROLS ) { Com_Error( ERR_DROP, "MAX SPLINE CONTROLS (%i) hit", MAX_SPLINE_CONTROLS ); } Q_strncpyz( spline->controls[spline->numControls].name, name, 64 ); spline->numControls++; } float BG_SplineLength( splinePath_t* pSpline ) { float i; float granularity = 0.01f; float dist = 0; // float tension; vec3_t vec[2]; vec3_t lastPoint; vec3_t result; for ( i = 0; i <= 1.f; i += granularity ) { /* if(pSpline->isStart) { tension = 1 - sin((1 - i) * M_PI * 0.5f); } else if(pSpline->isEnd) { tension = sin(i * M_PI * 0.5f); } else { tension = i; }*/ BG_CalculateSpline_r( pSpline, vec[0], vec[1], i ); VectorSubtract( vec[1], vec[0], result ); VectorMA( vec[0], i, result, result ); if ( i != 0 ) { VectorSubtract( result, lastPoint, vec[0] ); dist += VectorLength( vec[0] ); } VectorCopy( result, lastPoint ); } return dist; } void BG_BuildSplinePaths() { int i, j; pathCorner_t* pnt; splinePath_t *spline, *st; for ( i = 0; i < numSplinePaths; i++ ) { spline = &splinePaths[i]; if ( *spline->strTarget ) { for ( j = 0; j < spline->numControls; j++ ) { pnt = BG_Find_PathCorner( spline->controls[j].name ); if ( !pnt ) { Com_Printf( "^1Cant find control point (%s) for spline (%s)\n", spline->controls[j].name, spline->point.name ); // Gordon: Just changing to a warning for now, easier for region compiles... continue; } else { VectorCopy( pnt->origin, spline->controls[j].origin ); } } st = BG_Find_Spline( spline->strTarget ); if ( !st ) { Com_Printf( "^1Cant find target point (%s) for spline (%s)\n", spline->strTarget, spline->point.name ); // Gordon: Just changing to a warning for now, easier for region compiles... continue; } spline->next = st; spline->length = BG_SplineLength( spline ); BG_ComputeSegments( spline ); } } for ( i = 0; i < numSplinePaths; i++ ) { spline = &splinePaths[i]; if ( spline->next ) { spline->next->prev = spline; } } } splinePath_t* BG_GetSplineData( int number, qboolean* backwards ) { if ( number < 0 ) { *backwards = qtrue; number = -number; } else { *backwards = qfalse; } number--; if ( number < 0 || number >= numSplinePaths ) { return NULL; } return &splinePaths[number]; } int BG_MaxAmmoForWeapon( weapon_t weaponNum, int *skill ) { switch ( weaponNum ) { //case WP_KNIFE: case WP_LUGER: case WP_COLT: case WP_STEN: case WP_SILENCER: case WP_CARBINE: case WP_KAR98: case WP_SILENCED_COLT: if ( skill[SK_LIGHT_WEAPONS] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + GetAmmoTableData( weaponNum )->maxclip ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; case WP_MP40: case WP_THOMPSON: if ( skill[SK_FIRST_AID] >= 1 || skill[SK_LIGHT_WEAPONS] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + GetAmmoTableData( weaponNum )->maxclip ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; case WP_M7: case WP_GPG40: if ( skill[SK_EXPLOSIVES_AND_CONSTRUCTION] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + 4 ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; case WP_GRENADE_PINEAPPLE: case WP_GRENADE_LAUNCHER: // FIXME: this is class dependant, not ammo table if ( skill[SK_EXPLOSIVES_AND_CONSTRUCTION] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + 4 ); } else if ( skill[SK_FIRST_AID] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + 1 ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; /*case WP_MOBILE_MG42: case WP_PANZERFAUST: case WP_FLAMETHROWER: if( skill[SK_HEAVY_WEAPONS] >= 1 ) return( GetAmmoTableData(weaponNum)->maxammo + GetAmmoTableData(weaponNum)->maxclip ); else return( GetAmmoTableData(weaponNum)->maxammo ); break; case WP_MORTAR: case WP_MORTAR_SET: if( skill[SK_HEAVY_WEAPONS] >= 1 ) return( GetAmmoTableData(weaponNum)->maxammo + 2 ); else return( GetAmmoTableData(weaponNum)->maxammo ); break;*/ case WP_MEDIC_SYRINGE: if ( skill[SK_FIRST_AID] >= 2 ) { return( GetAmmoTableData( weaponNum )->maxammo + 2 ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; case WP_GARAND: case WP_K43: case WP_FG42: if ( skill[SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS] >= 1 || skill[SK_LIGHT_WEAPONS] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + GetAmmoTableData( weaponNum )->maxclip ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; case WP_GARAND_SCOPE: case WP_K43_SCOPE: case WP_FG42SCOPE: if ( skill[SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS] >= 1 ) { return( GetAmmoTableData( weaponNum )->maxammo + GetAmmoTableData( weaponNum )->maxclip ); } else { return( GetAmmoTableData( weaponNum )->maxammo ); } break; default: return( GetAmmoTableData( weaponNum )->maxammo ); break; } } /* ================ BG_CreateRotationMatrix ================ */ void BG_CreateRotationMatrix( const vec3_t angles, vec3_t matrix[3] ) { AngleVectors( angles, matrix[0], matrix[1], matrix[2] ); VectorInverse( matrix[1] ); } /* ================ BG_TransposeMatrix ================ */ void BG_TransposeMatrix( const vec3_t matrix[3], vec3_t transpose[3] ) { int i, j; for ( i = 0; i < 3; i++ ) { for ( j = 0; j < 3; j++ ) { transpose[i][j] = matrix[j][i]; } } } /* ================ BG_RotatePoint ================ */ void BG_RotatePoint( vec3_t point, const vec3_t matrix[3] ) { vec3_t tvec; VectorCopy( point, tvec ); point[0] = DotProduct( matrix[0], tvec ); point[1] = DotProduct( matrix[1], tvec ); point[2] = DotProduct( matrix[2], tvec ); } /* ================ BG_AdjustAAGunMuzzleForBarrel ================ */ void BG_AdjustAAGunMuzzleForBarrel( vec_t* origin, vec_t* forward, vec_t* right, vec_t* up, int barrel ) { switch ( barrel ) { case 0: VectorMA( origin, 64, forward, origin ); VectorMA( origin, 20, right, origin ); VectorMA( origin, 40, up, origin ); break; case 1: VectorMA( origin, 64, forward, origin ); VectorMA( origin, 20, right, origin ); VectorMA( origin, 20, up, origin ); break; case 2: VectorMA( origin, 64, forward, origin ); VectorMA( origin, -20, right, origin ); VectorMA( origin, 40, up, origin ); break; case 3: VectorMA( origin, 64, forward, origin ); VectorMA( origin, -20, right, origin ); VectorMA( origin, 20, up, origin ); break; } } /* ================= PC_SourceWarning ================= */ void PC_SourceWarning( int handle, char *format, ... ) { int line; char filename[128]; va_list argptr; static char string[4096]; va_start( argptr, format ); Q_vsnprintf( string, sizeof( string ), format, argptr ); va_end( argptr ); filename[0] = '\0'; line = 0; trap_PC_SourceFileAndLine( handle, filename, &line ); Com_Printf( S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string ); } /* ================= PC_SourceError ================= */ void PC_SourceError( int handle, char *format, ... ) { int line; char filename[128]; va_list argptr; static char string[4096]; va_start( argptr, format ); Q_vsnprintf( string, sizeof( string ), format, argptr ); va_end( argptr ); filename[0] = '\0'; line = 0; trap_PC_SourceFileAndLine( handle, filename, &line ); #ifdef GAMEDLL Com_Error( ERR_DROP, S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string ); #else Com_Printf( S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string ); #endif } /* ================= PC_Float_Parse ================= */ qboolean PC_Float_Parse( int handle, float *f ) { pc_token_t token; int negative = qfalse; if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } if ( token.string[0] == '-' ) { if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } negative = qtrue; } if ( token.type != TT_NUMBER ) { PC_SourceError( handle, "expected float but found %s\n", token.string ); return qfalse; } if ( negative ) { *f = -token.floatvalue; } else { *f = token.floatvalue; } return qtrue; } /* ================= PC_Color_Parse ================= */ qboolean PC_Color_Parse( int handle, vec4_t *c ) { int i; float f; for ( i = 0; i < 4; i++ ) { if ( !PC_Float_Parse( handle, &f ) ) { return qfalse; } ( *c )[i] = f; } return qtrue; } /* ================= PC_Vec_Parse ================= */ qboolean PC_Vec_Parse( int handle, vec3_t *c ) { int i; float f; for ( i = 0; i < 3; i++ ) { if ( !PC_Float_Parse( handle, &f ) ) { return qfalse; } ( *c )[i] = f; } return qtrue; } /* ================= PC_Int_Parse ================= */ qboolean PC_Int_Parse( int handle, int *i ) { pc_token_t token; int negative = qfalse; if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } if ( token.string[0] == '-' ) { if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } negative = qtrue; } if ( token.type != TT_NUMBER ) { PC_SourceError( handle, "expected integer but found %s\n", token.string ); return qfalse; } *i = token.intvalue; if ( negative ) { *i = -*i; } return qtrue; } #ifdef GAMEDLL /* ================= PC_String_Parse ================= */ const char* PC_String_Parse( int handle ) { static char buf[MAX_TOKEN_CHARS]; pc_token_t token; if ( !trap_PC_ReadToken( handle, &token ) ) { return NULL; } Q_strncpyz( buf, token.string, MAX_TOKEN_CHARS ); return buf; } #else /* ================= PC_String_Parse ================= */ qboolean PC_String_Parse( int handle, const char **out ) { pc_token_t token; if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } *( out ) = String_Alloc( token.string ); return qtrue; } #endif /* ================= PC_String_ParseNoAlloc Same as one above, but uses a static buff and not the string memory pool ================= */ qboolean PC_String_ParseNoAlloc( int handle, char *out, size_t size ) { pc_token_t token; if ( !trap_PC_ReadToken( handle, &token ) ) { return qfalse; } Q_strncpyz( out, token.string, size ); return qtrue; } const char* bg_fireteamNames[MAX_FIRETEAMS / 2] = { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", }; const voteType_t voteToggles[] = { { "vote_allow_comp", CV_SVF_COMP }, { "vote_allow_gametype", CV_SVF_GAMETYPE }, { "vote_allow_kick", CV_SVF_KICK }, { "vote_allow_map", CV_SVF_MAP }, { "vote_allow_matchreset", CV_SVF_MATCHRESET }, { "vote_allow_mutespecs", CV_SVF_MUTESPECS }, { "vote_allow_nextmap", CV_SVF_NEXTMAP }, { "vote_allow_pub", CV_SVF_PUB }, { "vote_allow_referee", CV_SVF_REFEREE }, { "vote_allow_shuffleteamsxp", CV_SVF_SHUFFLETEAMS }, { "vote_allow_swapteams", CV_SVF_SWAPTEAMS }, { "vote_allow_friendlyfire", CV_SVF_FRIENDLYFIRE }, { "vote_allow_timelimit", CV_SVF_TIMELIMIT }, { "vote_allow_warmupdamage", CV_SVF_WARMUPDAMAGE }, { "vote_allow_antilag", CV_SVF_ANTILAG }, { "vote_allow_balancedteams", CV_SVF_BALANCEDTEAMS }, { "vote_allow_muting", CV_SVF_MUTING } }; int numVotesAvailable = sizeof( voteToggles ) / sizeof( voteType_t ); // consts to offset random reinforcement seeds const unsigned int aReinfSeeds[MAX_REINFSEEDS] = { 11, 3, 13, 7, 2, 5, 1, 17 }; // Weapon full names + headshot capability const weap_ws_t aWeaponInfo[WS_MAX] = { { qfalse, "KNIF", "Knife" }, // 0 { qtrue, "LUGR", "Luger" }, // 1 { qtrue, "COLT", "Colt" }, // 2 { qtrue, "MP40", "MP-40" }, // 3 { qtrue, "TMPS", "Thompson" }, // 4 { qtrue, "STEN", "Sten" }, // 5 { qtrue, "FG42", "FG-42" }, // 6 { qtrue, "PNZR", "Panzer" }, // 7 { qtrue, "FLAM", "F.Thrower" }, // 8 { qfalse, "GRND", "Grenade" }, // 9 { qfalse, "MRTR", "Mortar" }, // 10 { qfalse, "DYNA", "Dynamite" }, // 11 { qfalse, "ARST", "Airstrike" }, // 12 { qfalse, "ARTY", "Artillery" }, // 13 { qfalse, "SRNG", "Syringe" }, // 14 { qfalse, "SMOK", "SmokeScrn" }, // 15 { qfalse, "STCH", "Satchel" }, // 16 { qfalse, "GRLN", "G.Launchr" }, // 17 { qfalse, "LNMN", "Landmine" }, // 18 { qtrue, "MG42", "MG-42 Gun" }, // 19 { qtrue, "GARN", "Garand" }, // 20 { qtrue, "K-43", "K43 Rifle" } // 21 }; // Multiview: Convert weaponstate to simpler format int BG_simpleWeaponState( int ws ) { switch ( ws ) { case WEAPON_READY: case WEAPON_READYING: case WEAPON_RELAXING: return( WSTATE_IDLE ); case WEAPON_RAISING: case WEAPON_DROPPING: case WEAPON_DROPPING_TORELOAD: return( WSTATE_SWITCH ); case WEAPON_FIRING: case WEAPON_FIRINGALT: return( WSTATE_FIRE ); case WEAPON_RELOADING: return( WSTATE_RELOAD ); } return( WSTATE_IDLE ); } // Multiview: Reduce hint info to 2 bits. However, we can really // have up to 8 values, as some hints will have a 0 value for // cursorHintVal int BG_simpleHintsCollapse( int hint, int val ) { switch ( hint ) { case HINT_DISARM: if ( val > 0 ) { return( 0 ); } case HINT_BUILD: if ( val > 0 ) { return( 1 ); } case HINT_BREAKABLE: if ( val == 0 ) { return( 1 ); } case HINT_DOOR_ROTATING: case HINT_BUTTON: case HINT_MG42: if ( val == 0 ) { return( 2 ); } case HINT_BREAKABLE_DYNAMITE: if ( val == 0 ) { return( 3 ); } } return( 0 ); } // Multiview: Expand the hints. Because we map a couple hints // into a single value, we can't replicate the proper hint back // in all cases. int BG_simpleHintsExpand( int hint, int val ) { switch ( hint ) { case 0: return( ( val >= 0 ) ? HINT_DISARM : 0 ); case 1: return( ( val >= 0 ) ? HINT_BUILD : HINT_BREAKABLE ); case 2: return( ( val >= 0 ) ? HINT_BUILD : HINT_MG42 ); case 3: return( ( val >= 0 ) ? HINT_BUILD : HINT_BREAKABLE_DYNAMITE ); } return( 0 ); } // Real printable charater count int BG_drawStrlen( const char *str ) { int cnt = 0; while ( *str ) { if ( Q_IsColorString( str ) ) { str += 2; } else { cnt++; str++; } } return( cnt ); } // Copies a color string, with limit of real chars to print // in = reference buffer w/color // out = target buffer // str_max = max size of printable string // out_max = max size of target buffer // // Returns size of printable string int BG_colorstrncpyz( char *in, char *out, int str_max, int out_max ) { int str_len = 0; // current printable string size int out_len = 0; // current true string size const int in_len = strlen( in ); out_max--; while ( *in && out_len < out_max && str_len < str_max ) { if ( *in == '^' ) { if ( out_len + 2 >= in_len && out_len + 2 >= out_max ) { break; } *out++ = *in++; *out++ = *in++; out_len += 2; continue; } *out++ = *in++; str_len++; out_len++; } *out = 0; return( str_len ); } int BG_strRelPos( char *in, int index ) { int cPrintable = 0; const char *ref = in; while ( *ref && cPrintable < index ) { if ( Q_IsColorString( ref ) ) { ref += 2; } else { ref++; cPrintable++; } } return( ref - in ); } // strip colors and control codes, copying up to dwMaxLength-1 "good" chars and nul-terminating // returns the length of the cleaned string int BG_cleanName( const char *pszIn, char *pszOut, unsigned int dwMaxLength, qboolean fCRLF ) { const char *pInCopy = pszIn; const char *pszOutStart = pszOut; while ( *pInCopy && ( pszOut - pszOutStart < dwMaxLength - 1 ) ) { if ( *pInCopy == '^' ) { pInCopy += ( ( pInCopy[1] == 0 ) ? 1 : 2 ); } else if ( ( *pInCopy < 32 && ( !fCRLF || *pInCopy != '\n' ) ) || ( *pInCopy > 126 ) ) { pInCopy++; } else { *pszOut++ = *pInCopy++; } } *pszOut = 0; return( pszOut - pszOutStart ); } // Only used locally typedef struct { char *colorname; vec4_t *color; } colorTable_t; // Colors for crosshairs colorTable_t OSP_Colortable[] = { { "white", &colorWhite }, { "red", &colorRed }, { "green", &colorGreen }, { "blue", &colorBlue }, { "yellow", &colorYellow }, { "magenta", &colorMagenta }, { "cyan", &colorCyan }, { "orange", &colorOrange }, { "mdred", &colorMdRed }, { "mdgreen", &colorMdGreen }, { "dkgreen", &colorDkGreen }, { "mdcyan", &colorMdCyan }, { "mdyellow", &colorMdYellow }, { "mdorange", &colorMdOrange }, { "mdblue", &colorMdBlue }, { "ltgrey", &colorLtGrey }, { "mdgrey", &colorMdGrey }, { "dkgrey", &colorDkGrey }, { "black", &colorBlack }, { NULL, NULL } }; extern void trap_Cvar_Set( const char *var_name, const char *value ); void BG_setCrosshair( char *colString, float *col, float alpha, char *cvarName ) { char *s = colString; col[0] = 1.0f; col[1] = 1.0f; col[2] = 1.0f; col[3] = ( alpha > 1.0f ) ? 1.0f : ( alpha < 0.0f ) ? 0.0f : alpha; if ( *s == '0' && ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) { s += 2; //parse rrggbb if ( Q_IsHexColorString( s ) ) { col[0] = ( (float)( gethex( *( s ) ) * 16 + gethex( *( s + 1 ) ) ) ) / 255.00; col[1] = ( (float)( gethex( *( s + 2 ) ) * 16 + gethex( *( s + 3 ) ) ) ) / 255.00; col[2] = ( (float)( gethex( *( s + 4 ) ) * 16 + gethex( *( s + 5 ) ) ) ) / 255.00; return; } } else { int i = 0; while ( OSP_Colortable[i].colorname != NULL ) { if ( Q_stricmp( s, OSP_Colortable[i].colorname ) == 0 ) { col[0] = ( *OSP_Colortable[i].color )[0]; col[1] = ( *OSP_Colortable[i].color )[1]; col[2] = ( *OSP_Colortable[i].color )[2]; return; } i++; } } trap_Cvar_Set( cvarName, "White" ); } qboolean BG_isLightWeaponSupportingFastReload( int weapon ) { if ( weapon == WP_LUGER || weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON || weapon == WP_STEN || weapon == WP_SILENCER || weapon == WP_FG42 || weapon == WP_SILENCED_COLT ) { return qtrue; } return qfalse; } qboolean BG_IsScopedWeapon( int weapon ) { switch ( weapon ) { case WP_GARAND_SCOPE: case WP_K43_SCOPE: case WP_FG42SCOPE: return qtrue; } return qfalse; } /////////////////////////////////////////////////////////////////////////////// typedef struct locInfo_s { vec2_t gridStartCoord; vec2_t gridStep; } locInfo_t; static locInfo_t locInfo; void BG_InitLocations( vec2_t world_mins, vec2_t world_maxs ) { // keep this in sync with CG_DrawGrid locInfo.gridStep[0] = 1200.f; locInfo.gridStep[1] = 1200.f; // ensure minimal grid density while ( ( world_maxs[0] - world_mins[0] ) / locInfo.gridStep[0] < 7 ) locInfo.gridStep[0] -= 50.f; while ( ( world_mins[1] - world_maxs[1] ) / locInfo.gridStep[1] < 7 ) locInfo.gridStep[1] -= 50.f; locInfo.gridStartCoord[0] = world_mins[0] + .5f * ( ( ( ( world_maxs[0] - world_mins[0] ) / locInfo.gridStep[0] ) - ( (int)( ( world_maxs[0] - world_mins[0] ) / locInfo.gridStep[0] ) ) ) * locInfo.gridStep[0] ); locInfo.gridStartCoord[1] = world_mins[1] - .5f * ( ( ( ( world_mins[1] - world_maxs[1] ) / locInfo.gridStep[1] ) - ( (int)( ( world_mins[1] - world_maxs[1] ) / locInfo.gridStep[1] ) ) ) * locInfo.gridStep[1] ); } char *BG_GetLocationString( vec_t* pos ) { static char coord[6]; int x, y; coord[0] = '\0'; x = ( pos[0] - locInfo.gridStartCoord[0] ) / locInfo.gridStep[0]; y = ( locInfo.gridStartCoord[1] - pos[1] ) / locInfo.gridStep[1]; if ( x < 0 ) { x = 0; } if ( y < 0 ) { y = 0; } Com_sprintf( coord, sizeof( coord ), "%c,%i", 'A' + x, y ); return coord; } qboolean BG_BBoxCollision( vec3_t min1, vec3_t max1, vec3_t min2, vec3_t max2 ) { int i; for ( i = 0; i < 3; i++ ) { if ( min1[i] > max2[i] ) { return qfalse; } if ( min2[i] > max1[i] ) { return qfalse; } } return qtrue; } weapon_t bg_heavyWeapons[NUM_HEAVY_WEAPONS] = { WP_FLAMETHROWER, WP_MOBILE_MG42, WP_MOBILE_MG42_SET, WP_PANZERFAUST, WP_MORTAR, WP_MORTAR_SET }; ///////////////////////// int BG_FootstepForSurface( int surfaceFlags ) { if ( surfaceFlags & SURF_NOSTEPS ) { return FOOTSTEP_TOTAL; } if ( surfaceFlags & SURF_METAL ) { return FOOTSTEP_METAL; } if ( surfaceFlags & SURF_WOOD ) { return FOOTSTEP_WOOD; } if ( surfaceFlags & SURF_GRASS ) { return FOOTSTEP_GRASS; } if ( surfaceFlags & SURF_GRAVEL ) { return FOOTSTEP_GRAVEL; } if ( surfaceFlags & SURF_ROOF ) { return FOOTSTEP_ROOF; } if ( surfaceFlags & SURF_SNOW ) { return FOOTSTEP_SNOW; } if ( surfaceFlags & SURF_CARPET ) { return FOOTSTEP_CARPET; } if ( surfaceFlags & SURF_SPLASH ) { return FOOTSTEP_SPLASH; } return FOOTSTEP_NORMAL; } /* ============ Q_vsnprintf vsnprintf portability: C99 standard: vsnprintf returns the number of characters (excluding the trailing '\0') which would have been written to the final string if enough space had been available snprintf and vsnprintf do not write more than size bytes (including the trailing '\0') win32: _vsnprintf returns the number of characters written, not including the terminating null character, or a negative value if an output error occurs. If the number of characters to write exceeds count, then count characters are written and -1 is returned and no trailing '\0' is added. Q_vsnPrintf: always append a trailing '\0', returns number of characters written or returns -1 on failure or if the buffer would be overflowed. copied over from common.c implementation ============ */ int Q_vsnprintf( char *dest, int size, const char *fmt, va_list argptr ) { int ret; #ifdef _WIN32 #undef _vsnprintf ret = _vsnprintf( dest, size - 1, fmt, argptr ); #define _vsnprintf use_idStr_vsnPrintf #else #undef vsnprintf ret = vsnprintf( dest, size, fmt, argptr ); #define vsnprintf use_idStr_vsnPrintf #endif dest[size - 1] = '\0'; if ( ret < 0 || ret >= size ) { return -1; } return ret; }