diff options
Diffstat (limited to 'src/game/bg_misc.c')
-rw-r--r-- | src/game/bg_misc.c | 5733 |
1 files changed, 5733 insertions, 0 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c new file mode 100644 index 0000000..79a8e2a --- /dev/null +++ b/src/game/bg_misc.c @@ -0,0 +1,5733 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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 2 of the License, +or (at your option) any later version. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// bg_misc.c -- both games misc functions, all completely stateless + +#include "../qcommon/q_shared.h" +#include "bg_public.h" + +int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ); +void trap_FS_Read( void *buffer, int len, fileHandle_t f ); +void trap_FS_Write( const void *buffer, int len, fileHandle_t f ); +void trap_FS_FCloseFile( fileHandle_t f ); +void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t + +buildableAttributes_t bg_buildableList[ ] = +{ + { + BA_A_SPAWN, //int buildNum; + "eggpod", //char *buildName; + "Egg", //char *humanName; + "team_alien_spawn", //char *entityName; + { "models/buildables/eggpod/eggpod.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -15, -15, -15 }, //vec3_t mins; + { 15, 15, 15 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + ASPAWN_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ASPAWN_HEALTH, //int health; + ASPAWN_REGEN, //int regenRate; + ASPAWN_SPLASHDAMAGE, //int splashDamage; + ASPAWN_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + ASPAWN_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.5f, //float minNormal; + qtrue, //qboolean invertNormal; + qfalse, //qboolean creepTest; + ASPAWN_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_A_BARRICADE, //int buildNum; + "barricade", //char *buildName; + "Barricade", //char *humanName; + "team_alien_barricade",//char *entityName; + { "models/buildables/barricade/barricade.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -35, -35, -15 }, //vec3_t mins; + { 35, 35, 60 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + BARRICADE_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + BARRICADE_HEALTH, //int health; + BARRICADE_REGEN, //int regenRate; + BARRICADE_SPLASHDAMAGE,//int splashDamage; + BARRICADE_SPLASHRADIUS,//int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + BARRICADE_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.707f, //float minNormal; + qfalse, //qboolean invertNormal; + qtrue, //qboolean creepTest; + BARRICADE_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replaceable; + }, + { + BA_A_BOOSTER, //int buildNum; + "booster", //char *buildName; + "Booster", //char *humanName; + "team_alien_booster", //char *entityName; + { "models/buildables/booster/booster.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -26, -26, -9 }, //vec3_t mins; + { 26, 26, 9 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + BOOSTER_BP, //int buildPoints; + ( 1 << S2 )|( 1 << S3 ), //int stages + BOOSTER_HEALTH, //int health; + BOOSTER_REGEN, //int regenRate; + BOOSTER_SPLASHDAMAGE, //int splashDamage; + BOOSTER_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + BOOSTER_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.707f, //float minNormal; + qfalse, //qboolean invertNormal; + qtrue, //qboolean creepTest; + BOOSTER_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_A_ACIDTUBE, //int buildNum; + "acid_tube", //char *buildName; + "Acid Tube", //char *humanName; + "team_alien_acid_tube",//char *entityName; + { "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -25, -25, -25 }, //vec3_t mins; + { 25, 25, 25 }, //vec3_t maxs; + -15.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + ACIDTUBE_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ACIDTUBE_HEALTH, //int health; + ACIDTUBE_REGEN, //int regenRate; + ACIDTUBE_SPLASHDAMAGE, //int splashDamage; + ACIDTUBE_SPLASHRADIUS, //int splashRadius; + MOD_ATUBE, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 200, //int nextthink; + ACIDTUBE_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.0f, //float minNormal; + qtrue, //qboolean invertNormal; + qtrue, //qboolean creepTest; + ACIDTUBE_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_A_HIVE, //int buildNum; + "hive", //char *buildName; + "Hive", //char *humanName; + "team_alien_hive", //char *entityName; + { "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -35, -35, -25 }, //vec3_t mins; + { 35, 35, 25 }, //vec3_t maxs; + -15.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + HIVE_BP, //int buildPoints; + ( 1 << S3 ), //int stages + HIVE_HEALTH, //int health; + HIVE_REGEN, //int regenRate; + HIVE_SPLASHDAMAGE, //int splashDamage; + HIVE_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 500, //int nextthink; + HIVE_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_HIVE, //weapon_t turretProjType; + 0.0f, //float minNormal; + qtrue, //qboolean invertNormal; + qtrue, //qboolean creepTest; + HIVE_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_A_TRAPPER, //int buildNum; + "trapper", //char *buildName; + "Trapper", //char *humanName; + "team_alien_trapper", //char *entityName; + { "models/buildables/trapper/trapper.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -15, -15, -15 }, //vec3_t mins; + { 15, 15, 15 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + TRAPPER_BP, //int buildPoints; + ( 1 << S2 )|( 1 << S3 ), //int stages //NEEDS ADV BUILDER SO S2 AND UP + TRAPPER_HEALTH, //int health; + TRAPPER_REGEN, //int regenRate; + TRAPPER_SPLASHDAMAGE, //int splashDamage; + TRAPPER_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + TRAPPER_BT, //int buildTime; + qfalse, //qboolean usable; + TRAPPER_RANGE, //int turretRange; + TRAPPER_REPEAT, //int turretFireSpeed; + WP_LOCKBLOB_LAUNCHER, //weapon_t turretProjType; + 0.0f, //float minNormal; + qtrue, //qboolean invertNormal; + qtrue, //qboolean creepTest; + TRAPPER_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_A_OVERMIND, //int buildNum; + "overmind", //char *buildName; + "Overmind", //char *humanName; + "team_alien_overmind", //char *entityName; + { "models/buildables/overmind/overmind.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -45, -45, -15 }, //vec3_t mins; + { 45, 45, 95 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + OVERMIND_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + OVERMIND_HEALTH, //int health; + OVERMIND_REGEN, //int regenRate; + OVERMIND_SPLASHDAMAGE, //int splashDamage; + OVERMIND_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + OVERMIND_ATTACK_REPEAT,//int nextthink; + OVERMIND_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + OVERMIND_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qtrue, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_A_HOVEL, //int buildNum; + "hovel", //char *buildName; + "Hovel", //char *humanName; + "team_alien_hovel", //char *entityName; + { "models/buildables/hovel/hovel.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -50, -50, -20 }, //vec3_t mins; + { 50, 50, 20 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + HOVEL_BP, //int buildPoints; + ( 1 << S3 ), //int stages + HOVEL_HEALTH, //int health; + HOVEL_REGEN, //int regenRate; + HOVEL_SPLASHDAMAGE, //int splashDamage; + HOVEL_SPLASHRADIUS, //int splashRadius; + MOD_ASPAWN, //int meansOfDeath; + BIT_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 150, //int nextthink; + HOVEL_BT, //int buildTime; + qtrue, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qtrue, //qboolean creepTest; + HOVEL_CREEPSIZE, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qtrue, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_H_SPAWN, //int buildNum; + "telenode", //char *buildName; + "Telenode", //char *humanName; + "team_human_spawn", //char *entityName; + { "models/buildables/telenode/telenode.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -40, -40, -4 }, //vec3_t mins; + { 40, 40, 4 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + HSPAWN_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + HSPAWN_HEALTH, //int health; + 0, //int regenRate; + HSPAWN_SPLASHDAMAGE, //int splashDamage; + HSPAWN_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + HSPAWN_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_H_MEDISTAT, //int buildNum; + "medistat", //char *buildName; + "Medistation", //char *humanName; + "team_human_medistat", //char *entityName; + { "models/buildables/medistat/medistat.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -35, -35, -7 }, //vec3_t mins; + { 35, 35, 7 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + MEDISTAT_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + MEDISTAT_HEALTH, //int health; + 0, //int regenRate; + MEDISTAT_SPLASHDAMAGE, //int splashDamage; + MEDISTAT_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + MEDISTAT_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_H_MGTURRET, //int buildNum; + "mgturret", //char *buildName; + "Machinegun Turret", //char *humanName; + "team_human_mgturret", //char *entityName; + { "models/buildables/mgturret/turret_base.md3", + "models/buildables/mgturret/turret_barrel.md3", + "models/buildables/mgturret/turret_top.md3", 0 }, + 1.0f, //float modelScale; + { -25, -25, -20 }, //vec3_t mins; + { 25, 25, 20 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + MGTURRET_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + MGTURRET_HEALTH, //int health; + 0, //int regenRate; + MGTURRET_SPLASHDAMAGE, //int splashDamage; + MGTURRET_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 50, //int nextthink; + MGTURRET_BT, //int buildTime; + qfalse, //qboolean usable; + MGTURRET_RANGE, //int turretRange; + MGTURRET_REPEAT, //int turretFireSpeed; + WP_MGTURRET, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_H_TESLAGEN, //int buildNum; + "tesla", //char *buildName; + "Tesla Generator", //char *humanName; + "team_human_tesla", //char *entityName; + { "models/buildables/tesla/tesla.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -22, -22, -40 }, //vec3_t mins; + { 22, 22, 40 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + TESLAGEN_BP, //int buildPoints; + ( 1 << S3 ), //int stages + TESLAGEN_HEALTH, //int health; + 0, //int regenRate; + TESLAGEN_SPLASHDAMAGE, //int splashDamage; + TESLAGEN_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 150, //int nextthink; + TESLAGEN_BT, //int buildTime; + qfalse, //qboolean usable; + TESLAGEN_RANGE, //int turretRange; + TESLAGEN_REPEAT, //int turretFireSpeed; + WP_TESLAGEN, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qtrue, //qboolean dccTest; + qtrue, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qfalse, //qboolean replacable; + }, + { + BA_H_DCC, //int buildNum; + "dcc", //char *buildName; + "Defence Computer", //char *humanName; + "team_human_dcc", //char *entityName; + { "models/buildables/dcc/dcc.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -35, -35, -13 }, //vec3_t mins; + { 35, 35, 47 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + DC_BP, //int buildPoints; + ( 1 << S2 )|( 1 << S3 ), //int stages + DC_HEALTH, //int health; + 0, //int regenRate; + DC_SPLASHDAMAGE, //int splashDamage; + DC_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + DC_BT, //int buildTime; + qfalse, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_H_ARMOURY, //int buildNum; + "arm", //char *buildName; + "Armoury", //char *humanName; + "team_human_armoury", //char *entityName; + { "models/buildables/arm/arm.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -40, -40, -13 }, //vec3_t mins; + { 40, 40, 50 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + ARMOURY_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ARMOURY_HEALTH, //int health; + 0, //int regenRate; + ARMOURY_SPLASHDAMAGE, //int splashDamage; + ARMOURY_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + ARMOURY_BT, //int buildTime; + qtrue, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_H_REACTOR, //int buildNum; + "reactor", //char *buildName; + "Reactor", //char *humanName; + "team_human_reactor", //char *entityName; + { "models/buildables/reactor/reactor.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -50, -50, -15 }, //vec3_t mins; + { 50, 50, 95 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + REACTOR_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + REACTOR_HEALTH, //int health; + 0, //int regenRate; + REACTOR_SPLASHDAMAGE, //int splashDamage; + REACTOR_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + REACTOR_ATTACK_REPEAT, //int nextthink; + REACTOR_BT, //int buildTime; + qtrue, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qtrue, //qboolean reactorTest; + qtrue, //qboolean replacable; + }, + { + BA_H_REPEATER, //int buildNum; + "repeater", //char *buildName; + "Repeater", //char *humanName; + "team_human_repeater", //char *entityName; + { "models/buildables/repeater/repeater.md3", 0, 0, 0 }, + 1.0f, //float modelScale; + { -15, -15, -15 }, //vec3_t mins; + { 15, 15, 25 }, //vec3_t maxs; + 0.0f, //float zOffset; + TR_GRAVITY, //trType_t traj; + 0.0, //float bounce; + REPEATER_BP, //int buildPoints; + ( 1 << S2 )|( 1 << S3 ), //int stages + REPEATER_HEALTH, //int health; + 0, //int regenRate; + REPEATER_SPLASHDAMAGE, //int splashDamage; + REPEATER_SPLASHRADIUS, //int splashRadius; + MOD_HSPAWN, //int meansOfDeath; + BIT_HUMANS, //int team; + ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon; + BANIM_IDLE1, //int idleAnim; + 100, //int nextthink; + REPEATER_BT, //int buildTime; + qtrue, //qboolean usable; + 0, //int turretRange; + 0, //int turretFireSpeed; + WP_NONE, //weapon_t turretProjType; + 0.95f, //float minNormal; + qfalse, //qboolean invertNormal; + qfalse, //qboolean creepTest; + 0, //int creepSize; + qfalse, //qboolean dccTest; + qfalse, //qboolean transparentTest; + qfalse, //qboolean reactorTest; + qtrue, //qboolean replacable; + } +}; + +int bg_numBuildables = sizeof( bg_buildableList ) / sizeof( bg_buildableList[ 0 ] ); + +//separate from bg_buildableList to work around char struct init bug +buildableAttributeOverrides_t bg_buildableOverrideList[ BA_NUM_BUILDABLES ]; + +/* +============== +BG_FindBuildNumForName +============== +*/ +int BG_FindBuildNumForName( char *name ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( !Q_stricmp( bg_buildableList[ i ].buildName, name ) ) + return bg_buildableList[ i ].buildNum; + } + + //wimp out + return BA_NONE; +} + +/* +============== +BG_FindBuildNumForEntityName +============== +*/ +int BG_FindBuildNumForEntityName( char *name ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( !Q_stricmp( bg_buildableList[ i ].entityName, name ) ) + return bg_buildableList[ i ].buildNum; + } + + //wimp out + return BA_NONE; +} + +/* +============== +BG_FindNameForBuildNum +============== +*/ +char *BG_FindNameForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + return bg_buildableList[ i ].buildName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindHumanNameForBuildNum +============== +*/ +char *BG_FindHumanNameForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + return bg_buildableList[ i ].humanName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindEntityNameForBuildNum +============== +*/ +char *BG_FindEntityNameForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + return bg_buildableList[ i ].entityName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindModelsForBuildNum +============== +*/ +char *BG_FindModelsForBuildable( int bclass, int modelNum ) +{ + int i; + + if( bg_buildableOverrideList[ bclass ].models[ modelNum ][ 0 ] != 0 ) + return bg_buildableOverrideList[ bclass ].models[ modelNum ]; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + return bg_buildableList[ i ].models[ modelNum ]; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindModelScaleForBuildable +============== +*/ +float BG_FindModelScaleForBuildable( int bclass ) +{ + int i; + + if( bg_buildableOverrideList[ bclass ].modelScale != 0.0f ) + return bg_buildableOverrideList[ bclass ].modelScale; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + return bg_buildableList[ i ].modelScale; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelScaleForBuildable( %d )\n", bclass ); + return 1.0f; +} + +/* +============== +BG_FindBBoxForBuildable +============== +*/ +void BG_FindBBoxForBuildable( int bclass, vec3_t mins, vec3_t maxs ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + if( mins != NULL ) + { + VectorCopy( bg_buildableList[ i ].mins, mins ); + + if( VectorLength( bg_buildableOverrideList[ bclass ].mins ) ) + VectorCopy( bg_buildableOverrideList[ bclass ].mins, mins ); + } + + if( maxs != NULL ) + { + VectorCopy( bg_buildableList[ i ].maxs, maxs ); + + if( VectorLength( bg_buildableOverrideList[ bclass ].maxs ) ) + VectorCopy( bg_buildableOverrideList[ bclass ].maxs, maxs ); + } + + return; + } + } + + if( mins != NULL ) + VectorCopy( bg_buildableList[ 0 ].mins, mins ); + + if( maxs != NULL ) + VectorCopy( bg_buildableList[ 0 ].maxs, maxs ); +} + +/* +============== +BG_FindZOffsetForBuildable +============== +*/ +float BG_FindZOffsetForBuildable( int bclass ) +{ + int i; + + if( bg_buildableOverrideList[ bclass ].zOffset != 0.0f ) + return bg_buildableOverrideList[ bclass ].zOffset; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].zOffset; + } + } + + return 0.0f; +} + +/* +============== +BG_FindTrajectoryForBuildable +============== +*/ +trType_t BG_FindTrajectoryForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].traj; + } + } + + return TR_GRAVITY; +} + +/* +============== +BG_FindBounceForBuildable +============== +*/ +float BG_FindBounceForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].bounce; + } + } + + return 0.0; +} + +/* +============== +BG_FindBuildPointsForBuildable +============== +*/ +int BG_FindBuildPointsForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].buildPoints; + } + } + + return 1000; +} + +/* +============== +BG_FindStagesForBuildable +============== +*/ +qboolean BG_FindStagesForBuildable( int bclass, stage_t stage ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + if( bg_buildableList[ i ].stages & ( 1 << stage ) ) + return qtrue; + else + return qfalse; + } + } + + return qfalse; +} + +/* +============== +BG_FindHealthForBuildable +============== +*/ +int BG_FindHealthForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].health; + } + } + + return 1000; +} + +/* +============== +BG_FindRegenRateForBuildable +============== +*/ +int BG_FindRegenRateForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].regenRate; + } + } + + return 0; +} + +/* +============== +BG_FindSplashDamageForBuildable +============== +*/ +int BG_FindSplashDamageForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].splashDamage; + } + } + + return 50; +} + +/* +============== +BG_FindSplashRadiusForBuildable +============== +*/ +int BG_FindSplashRadiusForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].splashRadius; + } + } + + return 200; +} + +/* +============== +BG_FindMODForBuildable +============== +*/ +int BG_FindMODForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].meansOfDeath; + } + } + + return MOD_UNKNOWN; +} + +/* +============== +BG_FindTeamForBuildable +============== +*/ +int BG_FindTeamForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].team; + } + } + + return BIT_NONE; +} + +/* +============== +BG_FindBuildWeaponForBuildable +============== +*/ +weapon_t BG_FindBuildWeaponForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].buildWeapon; + } + } + + return BA_NONE; +} + +/* +============== +BG_FindAnimForBuildable +============== +*/ +int BG_FindAnimForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].idleAnim; + } + } + + return BANIM_IDLE1; +} + +/* +============== +BG_FindNextThinkForBuildable +============== +*/ +int BG_FindNextThinkForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].nextthink; + } + } + + return 100; +} + +/* +============== +BG_FindBuildTimeForBuildable +============== +*/ +int BG_FindBuildTimeForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].buildTime; + } + } + + return 10000; +} + +/* +============== +BG_FindUsableForBuildable +============== +*/ +qboolean BG_FindUsableForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].usable; + } + } + + return qfalse; +} + +/* +============== +BG_FindFireSpeedForBuildable +============== +*/ +int BG_FindFireSpeedForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].turretFireSpeed; + } + } + + return 1000; +} + +/* +============== +BG_FindRangeForBuildable +============== +*/ +int BG_FindRangeForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].turretRange; + } + } + + return 1000; +} + +/* +============== +BG_FindProjTypeForBuildable +============== +*/ +weapon_t BG_FindProjTypeForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].turretProjType; + } + } + + return WP_NONE; +} + +/* +============== +BG_FindMinNormalForBuildable +============== +*/ +float BG_FindMinNormalForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].minNormal; + } + } + + return 0.707f; +} + +/* +============== +BG_FindInvertNormalForBuildable +============== +*/ +qboolean BG_FindInvertNormalForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].invertNormal; + } + } + + return qfalse; +} + +/* +============== +BG_FindCreepTestForBuildable +============== +*/ +int BG_FindCreepTestForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].creepTest; + } + } + + return qfalse; +} + +/* +============== +BG_FindCreepSizeForBuildable +============== +*/ +int BG_FindCreepSizeForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].creepSize; + } + } + + return CREEP_BASESIZE; +} + +/* +============== +BG_FindDCCTestForBuildable +============== +*/ +int BG_FindDCCTestForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].dccTest; + } + } + + return qfalse; +} + +/* +============== +BG_FindUniqueTestForBuildable +============== +*/ +int BG_FindUniqueTestForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].reactorTest; + } + } + + return qfalse; +} + +/* +============== +BG_FindReplaceableTestForBuildable +============== +*/ +qboolean BG_FindReplaceableTestForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].replaceable; + } + } + return qfalse; +} + +/* +============== +BG_FindOverrideForBuildable +============== +*/ +static buildableAttributeOverrides_t *BG_FindOverrideForBuildable( int bclass ) +{ + return &bg_buildableOverrideList[ bclass ]; +} + +/* +============== +BG_FindTransparentTestForBuildable +============== +*/ +qboolean BG_FindTransparentTestForBuildable( int bclass ) +{ + int i; + + for( i = 0; i < bg_numBuildables; i++ ) + { + if( bg_buildableList[ i ].buildNum == bclass ) + { + return bg_buildableList[ i ].transparentTest; + } + } + return qfalse; +} + +/* +====================== +BG_ParseBuildableFile + +Parses a configuration file describing a builable +====================== +*/ +static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeOverrides_t *bao ) +{ + char *text_p; + int i; + int len; + char *token; + char text[ 20000 ]; + fileHandle_t f; + float scale; + + + // load the file + len = trap_FS_FOpenFile( filename, &f, FS_READ ); + if( len < 0 ) + return qfalse; + + if( len == 0 || len >= sizeof( text ) - 1 ) + { + trap_FS_FCloseFile( f ); + Com_Printf( S_COLOR_RED "ERROR: Buildable file %s is %s\n", filename, + len == 0 ? "empty" : "too long" ); + return qfalse; + } + + trap_FS_Read( text, len, f ); + text[ len ] = 0; + trap_FS_FCloseFile( f ); + + // parse the text + text_p = text; + + // read optional parameters + while( 1 ) + { + token = COM_Parse( &text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + break; + + if( !Q_stricmp( token, "model" ) ) + { + int index = 0; + + token = COM_Parse( &text_p ); + if( !token ) + break; + + index = atoi( token ); + + if( index < 0 ) + index = 0; + else if( index > 3 ) + index = 3; + + token = COM_Parse( &text_p ); + if( !token ) + break; + + Q_strncpyz( bao->models[ index ], token, sizeof( bao->models[ 0 ] ) ); + + continue; + } + else if( !Q_stricmp( token, "modelScale" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + scale = atof( token ); + + if( scale < 0.0f ) + scale = 0.0f; + + bao->modelScale = scale; + + continue; + } + else if( !Q_stricmp( token, "mins" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + bao->mins[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "maxs" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + bao->maxs[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "zOffset" ) ) + { + float offset; + + token = COM_Parse( &text_p ); + if( !token ) + break; + + offset = atof( token ); + + bao->zOffset = offset; + + continue; + } + + + Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token ); + return qfalse; + } + + return qtrue; +} + +/* +=============== +BG_InitBuildableOverrides + +Set any overrides specfied by file +=============== +*/ +void BG_InitBuildableOverrides( void ) +{ + int i; + buildableAttributeOverrides_t *bao; + + for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) + { + bao = BG_FindOverrideForBuildable( i ); + + BG_ParseBuildableFile( va( "overrides/buildables/%s.cfg", BG_FindNameForBuildable( i ) ), bao ); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +classAttributes_t bg_classList[ ] = +{ + { + PCL_NONE, //int classnum; + "spectator", //char *className; + "Spectator", //char *humanName; + "", //char *modelname; + 1.0f, //float modelScale; + "", //char *skinname; + 1.0f, //float shadowScale; + "", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -15, -15, -15 }, //vec3_t mins; + { 15, 15, 15 }, //vec3_t maxs; + { 15, 15, 15 }, //vec3_t crouchmaxs; + { -15, -15, -15 }, //vec3_t deadmins; + { 15, 15, 15 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + 0, //int health; + 0.0f, //float fallDamage; + 0, //int regenRate; + 0, //int abilities; + WP_NONE, //weapon_t startWeapon + 0.0f, //float buildDist; + 90, //int fov; + 0.000f, //float bob; + 1.0f, //float bobCycle; + 0, //int steptime; + 600, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 1.0f, //float knockbackScale; + { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + 0, //int cost; + 0 //int value; + }, + { + PCL_ALIEN_BUILDER0, //int classnum; + "builder", //char *className; + "Builder", //char *humanName; + "builder", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "alien_builder_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -15, -15, -20 }, //vec3_t mins; + { 15, 15, 20 }, //vec3_t maxs; + { 15, 15, 20 }, //vec3_t crouchmaxs; + { -15, -15, -4 }, //vec3_t deadmins; + { 15, 15, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + ABUILDER_HEALTH, //int health; + 0.2f, //float fallDamage; + ABUILDER_REGEN, //int regenRate; + SCA_TAKESFALLDAMAGE|SCA_FOVWARPS|SCA_ALIENSENSE,//int abilities; + WP_ABUILD, //weapon_t startWeapon + 95.0f, //float buildDist; + 80, //int fov; + 0.001f, //float bob; + 2.0f, //float bobCycle; + 150, //int steptime; + ABUILDER_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 195.0f, //float jumpMagnitude; + 1.0f, //float knockbackScale; + { PCL_ALIEN_BUILDER0_UPG, PCL_ALIEN_LEVEL0, PCL_NONE }, //int children[ 3 ]; + ABUILDER_COST, //int cost; + ABUILDER_VALUE //int value; + }, + { + PCL_ALIEN_BUILDER0_UPG, //int classnum; + "builderupg", //char *classname; + "Advanced Builder", //char *humanname; + "builder", //char *modelname; + 1.0f, //float modelScale; + "advanced", //char *skinname; + 1.0f, //float shadowScale; + "alien_builder_hud", //char *hudname; + ( 1 << S2 )|( 1 << S3 ), //int stages + { -20, -20, -20 }, //vec3_t mins; + { 20, 20, 20 }, //vec3_t maxs; + { 20, 20, 20 }, //vec3_t crouchmaxs; + { -20, -20, -4 }, //vec3_t deadmins; + { 20, 20, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + ABUILDER_UPG_HEALTH, //int health; + 0.0f, //float fallDamage; + ABUILDER_UPG_REGEN, //int regenRate; + SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; + WP_ABUILD2, //weapon_t startWeapon + 105.0f, //float buildDist; + 110, //int fov; + 0.001f, //float bob; + 2.0f, //float bobCycle; + 100, //int steptime; + ABUILDER_UPG_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 1.0f, //float knockbackScale; + { PCL_ALIEN_LEVEL0, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + ABUILDER_UPG_COST, //int cost; + ABUILDER_UPG_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL0, //int classnum; + "level0", //char *classname; + "Soldier", //char *humanname; + "jumper", //char *modelname; + 0.2f, //float modelScale; + "default", //char *skinname; + 0.3f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -15, -15, -15 }, //vec3_t mins; + { 15, 15, 15 }, //vec3_t maxs; + { 15, 15, 15 }, //vec3_t crouchmaxs; + { -15, -15, -4 }, //vec3_t deadmins; + { 15, 15, 4 }, //vec3_t deadmaxs; + -8.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + LEVEL0_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL0_REGEN, //int regenRate; + SCA_WALLCLIMBER|SCA_NOWEAPONDRIFT| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL0, //weapon_t startWeapon + 0.0f, //float buildDist; + 140, //int fov; + 0.0f, //float bob; + 2.5f, //float bobCycle; + 25, //int steptime; + LEVEL0_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 400.0f, //float stopSpeed; + 250.0f, //float jumpMagnitude; + 2.0f, //float knockbackScale; + { PCL_ALIEN_LEVEL1, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + LEVEL0_COST, //int cost; + LEVEL0_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL1, //int classnum; + "level1", //char *classname; + "Hydra", //char *humanname; + "spitter", //char *modelname; + 0.6f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -18, -18, -18 }, //vec3_t mins; + { 18, 18, 18 }, //vec3_t maxs; + { 18, 18, 18 }, //vec3_t crouchmaxs; + { -18, -18, -4 }, //vec3_t deadmins; + { 18, 18, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + LEVEL1_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL1_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT| + SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL1, //weapon_t startWeapon + 0.0f, //float buildDist; + 120, //int fov; + 0.001f, //float bob; + 1.8f, //float bobCycle; + 60, //int steptime; + LEVEL1_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 300.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 1.2f, //float knockbackScale; + { PCL_ALIEN_LEVEL2, PCL_ALIEN_LEVEL1_UPG, PCL_NONE }, //int children[ 3 ]; + LEVEL1_COST, //int cost; + LEVEL1_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL1_UPG, //int classnum; + "level1upg", //char *classname; + "Hydra Upgrade", //char *humanname; + "spitter", //char *modelname; + 0.7f, //float modelScale; + "blue", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S2 )|( 1 << S3 ), //int stages + { -20, -20, -20 }, //vec3_t mins; + { 20, 20, 20 }, //vec3_t maxs; + { 20, 20, 20 }, //vec3_t crouchmaxs; + { -20, -20, -4 }, //vec3_t deadmins; + { 20, 20, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 0, 0, //int viewheight, crouchviewheight; + LEVEL1_UPG_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL1_UPG_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT|SCA_FOVWARPS| + SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL1_UPG, //weapon_t startWeapon + 0.0f, //float buildDist; + 120, //int fov; + 0.001f, //float bob; + 1.8f, //float bobCycle; + 60, //int steptime; + LEVEL1_UPG_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 300.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 1.1f, //float knockbackScale; + { PCL_ALIEN_LEVEL2, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + LEVEL1_UPG_COST, //int cost; + LEVEL1_UPG_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL2, //int classnum; + "level2", //char *classname; + "Chimera", //char *humanname; + "tarantula", //char *modelname; + 0.75f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -22, -22, -22 }, //vec3_t mins; + { 22, 22, 22 }, //vec3_t maxs; + { 22, 22, 22 }, //vec3_t crouchmaxs; + { -22, -22, -4 }, //vec3_t deadmins; + { 22, 22, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 10, 10, //int viewheight, crouchviewheight; + LEVEL2_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL2_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT|SCA_WALLJUMPER| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL2, //weapon_t startWeapon + 0.0f, //float buildDist; + 90, //int fov; + 0.001f, //float bob; + 1.5f, //float bobCycle; + 80, //int steptime; + LEVEL2_SPEED, //float speed; + 10.0f, //float acceleration; + 2.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 400.0f, //float jumpMagnitude; + 0.8f, //float knockbackScale; + { PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL2_UPG, PCL_NONE }, //int children[ 3 ]; + LEVEL2_COST, //int cost; + LEVEL2_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL2_UPG, //int classnum; + "level2upg", //char *classname; + "Chimera Upgrade", //char *humanname; + "tarantula", //char *modelname; + 0.9f, //float modelScale; + "red", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S2 )|( 1 << S3 ), //int stages + { -24, -24, -24 }, //vec3_t mins; + { 24, 24, 24 }, //vec3_t maxs; + { 24, 24, 24 }, //vec3_t crouchmaxs; + { -24, -24, -4 }, //vec3_t deadmins; + { 24, 24, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 12, 12, //int viewheight, crouchviewheight; + LEVEL2_UPG_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL2_UPG_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT|SCA_WALLJUMPER| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL2_UPG, //weapon_t startWeapon + 0.0f, //float buildDist; + 90, //int fov; + 0.001f, //float bob; + 1.5f, //float bobCycle; + 80, //int steptime; + LEVEL2_UPG_SPEED, //float speed; + 10.0f, //float acceleration; + 2.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 400.0f, //float jumpMagnitude; + 0.7f, //float knockbackScale; + { PCL_ALIEN_LEVEL3, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + LEVEL2_UPG_COST, //int cost; + LEVEL2_UPG_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL3, //int classnum; + "level3", //char *classname; + "Dragoon", //char *humanname; + "prowl", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -32, -32, -21 }, //vec3_t mins; + { 32, 32, 21 }, //vec3_t maxs; + { 32, 32, 21 }, //vec3_t crouchmaxs; + { -32, -32, -4 }, //vec3_t deadmins; + { 32, 32, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 24, 24, //int viewheight, crouchviewheight; + LEVEL3_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL3_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL3, //weapon_t startWeapon + 0.0f, //float buildDist; + 110, //int fov; + 0.0005f, //float bob; + 1.3f, //float bobCycle; + 90, //int steptime; + LEVEL3_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 200.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 0.5f, //float knockbackScale; + { PCL_ALIEN_LEVEL4, PCL_ALIEN_LEVEL3_UPG, PCL_NONE }, //int children[ 3 ]; + LEVEL3_COST, //int cost; + LEVEL3_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL3_UPG, //int classnum; + "level3upg", //char *classname; + "Dragoon Upgrade", //char *humanname; + "prowl", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S3 ), //int stages + { -32, -32, -21 }, //vec3_t mins; + { 32, 32, 21 }, //vec3_t maxs; + { 32, 32, 21 }, //vec3_t crouchmaxs; + { -32, -32, -4 }, //vec3_t deadmins; + { 32, 32, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 27, 27, //int viewheight, crouchviewheight; + LEVEL3_UPG_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL3_UPG_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL3_UPG, //weapon_t startWeapon + 0.0f, //float buildDist; + 110, //int fov; + 0.0005f, //float bob; + 1.3f, //float bobCycle; + 90, //int steptime; + LEVEL3_UPG_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 200.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 0.4f, //float knockbackScale; + { PCL_ALIEN_LEVEL4, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + LEVEL3_UPG_COST, //int cost; + LEVEL3_UPG_VALUE //int value; + }, + { + PCL_ALIEN_LEVEL4, //int classnum; + "level4", //char *classname; + "Big Mofo", //char *humanname; + "mofo", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 2.0f, //float shadowScale; + "alien_general_hud", //char *hudname; + ( 1 << S3 ), //int stages + { -30, -30, -20 }, //vec3_t mins; + { 30, 30, 20 }, //vec3_t maxs; + { 30, 30, 20 }, //vec3_t crouchmaxs; + { -15, -15, -4 }, //vec3_t deadmins; + { 15, 15, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 35, 35, //int viewheight, crouchviewheight; + LEVEL4_HEALTH, //int health; + 0.0f, //float fallDamage; + LEVEL4_REGEN, //int regenRate; + SCA_NOWEAPONDRIFT| + SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ALEVEL4, //weapon_t startWeapon + 0.0f, //float buildDist; + 90, //int fov; + 0.001f, //float bob; + 1.1f, //float bobCycle; + 100, //int steptime; + LEVEL4_SPEED, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 170.0f, //float jumpMagnitude; + 0.1f, //float knockbackScale; + { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + LEVEL4_COST, //int cost; + LEVEL4_VALUE //int value; + }, + { + PCL_HUMAN, //int classnum; + "human_base", //char *classname; + "Human", //char *humanname; + "sarge", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "human_hud", //char *hudname; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + { -15, -15, -24 }, //vec3_t mins; + { 15, 15, 32 }, //vec3_t maxs; + { 15, 15, 16 }, //vec3_t crouchmaxs; + { -15, -15, -4 }, //vec3_t deadmins; + { 15, 15, 4 }, //vec3_t deadmaxs; + 0.0f, //float zOffset + 26, 12, //int viewheight, crouchviewheight; + 100, //int health; + 1.0f, //float fallDamage; + 0, //int regenRate; + SCA_TAKESFALLDAMAGE| + SCA_CANUSELADDERS, //int abilities; + WP_NONE, //special-cased in g_client.c //weapon_t startWeapon + 110.0f, //float buildDist; + 90, //int fov; + 0.002f, //float bob; + 1.0f, //float bobCycle; + 100, //int steptime; + 1.0f, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 220.0f, //float jumpMagnitude; + 1.0f, //float knockbackScale; + { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + 0, //int cost; + 0 //int value; + }, + { + PCL_HUMAN_BSUIT, //int classnum; + "human_bsuit", //char *classname; + "bsuit", //char *humanname; + "keel", //char *modelname; + 1.0f, //float modelScale; + "default", //char *skinname; + 1.0f, //float shadowScale; + "human_hud", //char *hudname; + ( 1 << S3 ), //int stages + { -15, -15, -38 }, //vec3_t mins; + { 15, 15, 38 }, //vec3_t maxs; + { 15, 15, 38 }, //vec3_t crouchmaxs; + { -15, -15, -4 }, //vec3_t deadmins; + { 15, 15, 4 }, //vec3_t deadmaxs; + -16.0f, //float zOffset + 35, 35, //int viewheight, crouchviewheight; + 100, //int health; + 1.0f, //float fallDamage; + 0, //int regenRate; + SCA_TAKESFALLDAMAGE| + SCA_CANUSELADDERS, //int abilities; + WP_NONE, //special-cased in g_client.c //weapon_t startWeapon + 110.0f, //float buildDist; + 90, //int fov; + 0.002f, //float bob; + 1.0f, //float bobCycle; + 100, //int steptime; + 1.0f, //float speed; + 10.0f, //float acceleration; + 1.0f, //float airAcceleration; + 6.0f, //float friction; + 100.0f, //float stopSpeed; + 270.0f, //float jumpMagnitude; + 1.0f, //float knockbackScale; + { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ]; + 0, //int cost; + 0 //int value; + }, +}; + +int bg_numPclasses = sizeof( bg_classList ) / sizeof( bg_classList[ 0 ] ); + +//separate from bg_classList to work around char struct init bug +classAttributeOverrides_t bg_classOverrideList[ PCL_NUM_CLASSES ]; + +/* +============== +BG_FindClassNumForName +============== +*/ +int BG_FindClassNumForName( char *name ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( !Q_stricmp( bg_classList[ i ].className, name ) ) + return bg_classList[ i ].classNum; + } + + //wimp out + return PCL_NONE; +} + +/* +============== +BG_FindNameForClassNum +============== +*/ +char *BG_FindNameForClassNum( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + return bg_classList[ i ].className; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindNameForClassNum\n" ); + //wimp out + return 0; +} + +/* +============== +BG_FindHumanNameForClassNum +============== +*/ +char *BG_FindHumanNameForClassNum( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].humanName[ 0 ] != 0 ) + return bg_classOverrideList[ pclass ].humanName; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + return bg_classList[ i ].humanName; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHumanNameForClassNum\n" ); + //wimp out + return 0; +} + +/* +============== +BG_FindModelNameForClass +============== +*/ +char *BG_FindModelNameForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].modelName[ 0 ] != 0 ) + return bg_classOverrideList[ pclass ].modelName; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + return bg_classList[ i ].modelName; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelNameForClass\n" ); + //note: must return a valid modelName! + return bg_classList[ 0 ].modelName; +} + +/* +============== +BG_FindModelScaleForClass +============== +*/ +float BG_FindModelScaleForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].modelScale != 0.0f ) + return bg_classOverrideList[ pclass ].modelScale; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].modelScale; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelScaleForClass( %d )\n", pclass ); + return 1.0f; +} + +/* +============== +BG_FindSkinNameForClass +============== +*/ +char *BG_FindSkinNameForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].skinName[ 0 ] != 0 ) + return bg_classOverrideList[ pclass ].skinName; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + return bg_classList[ i ].skinName; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSkinNameForClass\n" ); + //note: must return a valid modelName! + return bg_classList[ 0 ].skinName; +} + +/* +============== +BG_FindShadowScaleForClass +============== +*/ +float BG_FindShadowScaleForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].shadowScale != 0.0f ) + return bg_classOverrideList[ pclass ].shadowScale; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].shadowScale; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindShadowScaleForClass( %d )\n", pclass ); + return 1.0f; +} + +/* +============== +BG_FindHudNameForClass +============== +*/ +char *BG_FindHudNameForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].hudName[ 0 ] != 0 ) + return bg_classOverrideList[ pclass ].hudName; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + return bg_classList[ i ].hudName; + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHudNameForClass\n" ); + //note: must return a valid hudName! + return bg_classList[ 0 ].hudName; +} + +/* +============== +BG_FindStagesForClass +============== +*/ +qboolean BG_FindStagesForClass( int pclass, stage_t stage ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + if( bg_classList[ i ].stages & ( 1 << stage ) ) + return qtrue; + else + return qfalse; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStagesForClass\n" ); + return qfalse; +} + +/* +============== +BG_FindBBoxForClass +============== +*/ +void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + if( mins != NULL ) + { + VectorCopy( bg_classList[ i ].mins, mins ); + + if( VectorLength( bg_classOverrideList[ pclass ].mins ) ) + VectorCopy( bg_classOverrideList[ pclass ].mins, mins ); + } + + if( maxs != NULL ) + { + VectorCopy( bg_classList[ i ].maxs, maxs ); + + if( VectorLength( bg_classOverrideList[ pclass ].maxs ) ) + VectorCopy( bg_classOverrideList[ pclass ].maxs, maxs ); + } + + if( cmaxs != NULL ) + { + VectorCopy( bg_classList[ i ].crouchMaxs, cmaxs ); + + if( VectorLength( bg_classOverrideList[ pclass ].crouchMaxs ) ) + VectorCopy( bg_classOverrideList[ pclass ].crouchMaxs, cmaxs ); + } + + if( dmins != NULL ) + { + VectorCopy( bg_classList[ i ].deadMins, dmins ); + + if( VectorLength( bg_classOverrideList[ pclass ].deadMins ) ) + VectorCopy( bg_classOverrideList[ pclass ].deadMins, dmins ); + } + + if( dmaxs != NULL ) + { + VectorCopy( bg_classList[ i ].deadMaxs, dmaxs ); + + if( VectorLength( bg_classOverrideList[ pclass ].deadMaxs ) ) + VectorCopy( bg_classOverrideList[ pclass ].deadMaxs, dmaxs ); + } + + return; + } + } + + if( mins != NULL ) + VectorCopy( bg_classList[ 0 ].mins, mins ); + + if( maxs != NULL ) + VectorCopy( bg_classList[ 0 ].maxs, maxs ); + + if( cmaxs != NULL ) + VectorCopy( bg_classList[ 0 ].crouchMaxs, cmaxs ); + + if( dmins != NULL ) + VectorCopy( bg_classList[ 0 ].deadMins, dmins ); + + if( dmaxs != NULL ) + VectorCopy( bg_classList[ 0 ].deadMaxs, dmaxs ); +} + +/* +============== +BG_FindZOffsetForClass +============== +*/ +float BG_FindZOffsetForClass( int pclass ) +{ + int i; + + if( bg_classOverrideList[ pclass ].zOffset != 0.0f ) + return bg_classOverrideList[ pclass ].zOffset; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].zOffset; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindZOffsetForClass\n" ); + return 0.0f; +} + +/* +============== +BG_FindViewheightForClass +============== +*/ +void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight ) +{ + int i; + int vh = 0; + int cvh = 0; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + vh = bg_classList[ i ].viewheight; + cvh = bg_classList[ i ].crouchViewheight; + break; + } + } + + if( bg_classOverrideList[ pclass ].viewheight != 0 ) + vh = bg_classOverrideList[ pclass ].viewheight; + if( bg_classOverrideList[ pclass ].crouchViewheight != 0 ) + cvh = bg_classOverrideList[ pclass ].crouchViewheight; + + + if( vh == 0 ) + vh = bg_classList[ 0 ].viewheight; + if( cvh == 0 ) + cvh = bg_classList[ 0 ].crouchViewheight; + + if( viewheight != NULL ) + *viewheight = vh; + if( cViewheight != NULL ) + *cViewheight = cvh; +} + +/* +============== +BG_FindHealthForClass +============== +*/ +int BG_FindHealthForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].health; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHealthForClass\n" ); + return 100; +} + +/* +============== +BG_FindFallDamageForClass +============== +*/ +float BG_FindFallDamageForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].fallDamage; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFallDamageForClass\n" ); + return 100; +} + +/* +============== +BG_FindRegenRateForClass +============== +*/ +int BG_FindRegenRateForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].regenRate; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindRegenRateForClass\n" ); + return 0; +} + +/* +============== +BG_FindFovForClass +============== +*/ +int BG_FindFovForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].fov; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFovForClass\n" ); + return 90; +} + +/* +============== +BG_FindBobForClass +============== +*/ +float BG_FindBobForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].bob; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBobForClass\n" ); + return 0.002; +} + +/* +============== +BG_FindBobCycleForClass +============== +*/ +float BG_FindBobCycleForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].bobCycle; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBobCycleForClass\n" ); + return 1.0f; +} + +/* +============== +BG_FindSpeedForClass +============== +*/ +float BG_FindSpeedForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].speed; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSpeedForClass\n" ); + return 1.0f; +} + +/* +============== +BG_FindAccelerationForClass +============== +*/ +float BG_FindAccelerationForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].acceleration; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindAccelerationForClass\n" ); + return 10.0f; +} + +/* +============== +BG_FindAirAccelerationForClass +============== +*/ +float BG_FindAirAccelerationForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].airAcceleration; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindAirAccelerationForClass\n" ); + return 1.0f; +} + +/* +============== +BG_FindFrictionForClass +============== +*/ +float BG_FindFrictionForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].friction; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFrictionForClass\n" ); + return 6.0f; +} + +/* +============== +BG_FindStopSpeedForClass +============== +*/ +float BG_FindStopSpeedForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].stopSpeed; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStopSpeedForClass\n" ); + return 100.0f; +} + +/* +============== +BG_FindJumpMagnitudeForClass +============== +*/ +float BG_FindJumpMagnitudeForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].jumpMagnitude; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindJumpMagnitudeForClass\n" ); + return 270.0f; +} + +/* +============== +BG_FindKnockbackScaleForClass +============== +*/ +float BG_FindKnockbackScaleForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].knockbackScale; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindKnockbackScaleForClass\n" ); + return 1.0f; +} + +/* +============== +BG_FindSteptimeForClass +============== +*/ +int BG_FindSteptimeForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].steptime; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSteptimeForClass\n" ); + return 200; +} + +/* +============== +BG_ClassHasAbility +============== +*/ +qboolean BG_ClassHasAbility( int pclass, int ability ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return ( bg_classList[ i ].abilities & ability ); + } + } + + return qfalse; +} + +/* +============== +BG_FindStartWeaponForClass +============== +*/ +weapon_t BG_FindStartWeaponForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].startWeapon; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStartWeaponForClass\n" ); + return WP_NONE; +} + +/* +============== +BG_FindBuildDistForClass +============== +*/ +float BG_FindBuildDistForClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].buildDist; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBuildDistForClass\n" ); + return 0.0f; +} + +/* +============== +BG_ClassCanEvolveFromTo +============== +*/ +int BG_ClassCanEvolveFromTo( int fclass, int tclass, int credits, int num ) +{ + int i, j, cost; + + cost = BG_FindCostOfClass( tclass ); + + //base case + if( credits < cost ) + return -1; + + if( fclass == PCL_NONE || tclass == PCL_NONE ) + return -1; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == fclass ) + { + for( j = 0; j < 3; j++ ) + if( bg_classList[ i ].children[ j ] == tclass ) + return num + cost; + + for( j = 0; j < 3; j++ ) + { + int sub; + + cost = BG_FindCostOfClass( bg_classList[ i ].children[ j ] ); + sub = BG_ClassCanEvolveFromTo( bg_classList[ i ].children[ j ], + tclass, credits - cost, num + cost ); + if( sub >= 0 ) + return sub; + } + + return -1; //may as well return by this point + } + } + + return -1; +} + +/* +============== +BG_FindValueOfClass +============== +*/ +int BG_FindValueOfClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].value; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindValueOfClass\n" ); + return 0; +} + +/* +============== +BG_FindCostOfClass +============== +*/ +int BG_FindCostOfClass( int pclass ) +{ + int i; + + for( i = 0; i < bg_numPclasses; i++ ) + { + if( bg_classList[ i ].classNum == pclass ) + { + return bg_classList[ i ].cost; + } + } + + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindCostOfClass\n" ); + return 0; +} + +/* +============== +BG_FindOverrideForClass +============== +*/ +static classAttributeOverrides_t *BG_FindOverrideForClass( int pclass ) +{ + return &bg_classOverrideList[ pclass ]; +} + +/* +====================== +BG_ParseClassFile + +Parses a configuration file describing a class +====================== +*/ +static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides_t *cao ) +{ + char *text_p; + int i; + int len; + char *token; + char text[ 20000 ]; + fileHandle_t f; + float scale = 0.0f; + + + // load the file + len = trap_FS_FOpenFile( filename, &f, FS_READ ); + if( len < 0 ) + return qfalse; + + if( len == 0 || len >= sizeof( text ) - 1 ) + { + trap_FS_FCloseFile( f ); + Com_Printf( S_COLOR_RED "ERROR: Class file %s is %s\n", filename, + len == 0 ? "empty" : "too long" ); + return qfalse; + } + + trap_FS_Read( text, len, f ); + text[ len ] = 0; + trap_FS_FCloseFile( f ); + + // parse the text + text_p = text; + + // read optional parameters + while( 1 ) + { + token = COM_Parse( &text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + break; + + if( !Q_stricmp( token, "model" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + Q_strncpyz( cao->modelName, token, sizeof( cao->modelName ) ); + + continue; + } + else if( !Q_stricmp( token, "skin" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + Q_strncpyz( cao->skinName, token, sizeof( cao->skinName ) ); + + continue; + } + else if( !Q_stricmp( token, "hud" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + Q_strncpyz( cao->hudName, token, sizeof( cao->hudName ) ); + + continue; + } + else if( !Q_stricmp( token, "modelScale" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + scale = atof( token ); + + if( scale < 0.0f ) + scale = 0.0f; + + cao->modelScale = scale; + + continue; + } + else if( !Q_stricmp( token, "shadowScale" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + scale = atof( token ); + + if( scale < 0.0f ) + scale = 0.0f; + + cao->shadowScale = scale; + + continue; + } + else if( !Q_stricmp( token, "mins" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + cao->mins[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "maxs" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + cao->maxs[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "deadMins" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + cao->deadMins[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "deadMaxs" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + cao->deadMaxs[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "crouchMaxs" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + cao->crouchMaxs[ i ] = atof( token ); + } + + continue; + } + else if( !Q_stricmp( token, "viewheight" ) ) + { + token = COM_Parse( &text_p ); + cao->viewheight = atoi( token ); + continue; + } + else if( !Q_stricmp( token, "crouchViewheight" ) ) + { + token = COM_Parse( &text_p ); + cao->crouchViewheight = atoi( token ); + continue; + } + else if( !Q_stricmp( token, "zOffset" ) ) + { + float offset; + + token = COM_Parse( &text_p ); + if( !token ) + break; + + offset = atof( token ); + + cao->zOffset = offset; + + continue; + } + else if( !Q_stricmp( token, "name" ) ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + + Q_strncpyz( cao->humanName, token, sizeof( cao->humanName ) ); + + continue; + } + + + Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token ); + return qfalse; + } + + return qtrue; +} + +/* +=============== +BG_InitClassOverrides + +Set any overrides specfied by file +=============== +*/ +void BG_InitClassOverrides( void ) +{ + int i; + classAttributeOverrides_t *cao; + + for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) + { + cao = BG_FindOverrideForClass( i ); + + BG_ParseClassFile( va( "overrides/classes/%s.cfg", BG_FindNameForClassNum( i ) ), cao ); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +weaponAttributes_t bg_weapons[ ] = +{ + { + WP_BLASTER, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + 0, //int slots; + "blaster", //char *weaponName; + "Blaster", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + BLASTER_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + BLASTER_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_MACHINEGUN, //int weaponNum; + RIFLE_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "rifle", //char *weaponName; + "Rifle", //char *weaponHumanName; + RIFLE_CLIPSIZE, //int maxAmmo; + RIFLE_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + RIFLE_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + RIFLE_RELOAD, //int reloadTime; + RIFLE_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_SHOTGUN, //int weaponNum; + SHOTGUN_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "shotgun", //char *weaponName; + "Shotgun", //char *weaponHumanName; + SHOTGUN_SHELLS, //int maxAmmo; + SHOTGUN_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + SHOTGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + SHOTGUN_RELOAD, //int reloadTime; + SHOTGUN_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_FLAMER, //int weaponNum; + FLAMER_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "flamer", //char *weaponName; + "Flame Thrower", //char *weaponHumanName; + FLAMER_GAS, //int maxAmmo; + 0, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + FLAMER_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + FLAMER_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_CHAINGUN, //int weaponNum; + CHAINGUN_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "chaingun", //char *weaponName; + "Chaingun", //char *weaponHumanName; + CHAINGUN_BULLETS, //int maxAmmo; + 0, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + CHAINGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + CHAINGUN_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_MASS_DRIVER, //int weaponNum; + MDRIVER_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "mdriver", //char *weaponName; + "Mass Driver", //char *weaponHumanName; + MDRIVER_CLIPSIZE, //int maxAmmo; + MDRIVER_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + MDRIVER_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + MDRIVER_RELOAD, //int reloadTime; + MDRIVER_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qtrue, //qboolean canZoom; + 20.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_PULSE_RIFLE, //int weaponNum; + PRIFLE_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "prifle", //char *weaponName; + "Pulse Rifle", //char *weaponHumanName; + PRIFLE_CLIPS, //int maxAmmo; + PRIFLE_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + PRIFLE_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + PRIFLE_RELOAD, //int reloadTime; + PRIFLE_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_LUCIFER_CANNON, //int weaponNum; + LCANNON_PRICE, //int price; + ( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "lcannon", //char *weaponName; + "Lucifer Cannon", //char *weaponHumanName; + LCANNON_AMMO, //int maxAmmo; + 0, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + LCANNON_REPEAT, //int repeatRate1; + LCANNON_CHARGEREPEAT, //int repeatRate2; + 0, //int repeatRate3; + LCANNON_RELOAD, //int reloadTime; + LCANNON_K_SCALE, //float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_LAS_GUN, //int weaponNum; + LASGUN_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "lgun", //char *weaponName; + "Las Gun", //char *weaponHumanName; + LASGUN_AMMO, //int maxAmmo; + 0, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + LASGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + LASGUN_RELOAD, //int reloadTime; + LASGUN_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_PAIN_SAW, //int weaponNum; + PAINSAW_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "psaw", //char *weaponName; + "Pain Saw", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + PAINSAW_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + PAINSAW_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_GRENADE, //int weaponNum; + GRENADE_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_NONE, //int slots; + "grenade", //char *weaponName; + "Grenade", //char *weaponHumanName; + 1, //int maxAmmo; + 0, //int maxClips; + qfalse, //int infiniteAmmo; + qfalse, //int usesEnergy; + GRENADE_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + GRENADE_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_HBUILD, //int weaponNum; + HBUILD_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "ckit", //char *weaponName; + "Construction Kit", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + HBUILD_REPEAT, //int repeatRate1; + HBUILD_REPEAT, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + 0.0f, //float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qfalse, //qboolean longRanged; + HBUILD_DELAY, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_HBUILD2, //int weaponNum; + HBUILD2_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "ackit", //char *weaponName; + "Adv Construction Kit",//char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + HBUILD2_REPEAT, //int repeatRate1; + HBUILD2_REPEAT, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + 0.0f, //float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qfalse, //qboolean longRanged; + HBUILD2_DELAY, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_ABUILD, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "abuild", //char *weaponName; + "Alien build weapon", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + ABUILDER_BUILD_REPEAT,//int repeatRate1; + ABUILDER_BUILD_REPEAT,//int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + 0.0f, //float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qfalse, //qboolean longRanged; + ABUILDER_BASE_DELAY, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ABUILD2, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "abuildupg", //char *weaponName; + "Alien build weapon2",//char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + ABUILDER_BUILD_REPEAT,//int repeatRate1; + ABUILDER_CLAW_REPEAT, //int repeatRate2; + ABUILDER_BLOB_REPEAT, //int repeatRate3; + 0, //int reloadTime; + ABUILDER_CLAW_K_SCALE,//float knockbackScale; + qtrue, //qboolean hasAltMode; + qtrue, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qtrue, //qboolean purchasable; + qfalse, //qboolean longRanged; + ABUILDER_ADV_DELAY, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL0, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level0", //char *weaponName; + "Bite", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL0_BITE_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL0_BITE_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL1, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level1", //char *weaponName; + "Claws", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL1_CLAW_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL1_CLAW_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL1_UPG, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level1upg", //char *weaponName; + "Claws Upgrade", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL1_CLAW_U_REPEAT, //int repeatRate1; + LEVEL1_PCLOUD_REPEAT, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL1_CLAW_U_K_SCALE,//float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL2, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level2", //char *weaponName; + "Bite", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL2_CLAW_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL2_CLAW_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL2_UPG, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level2upg", //char *weaponName; + "Zap", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL2_CLAW_U_REPEAT, //int repeatRate1; + LEVEL2_AREAZAP_REPEAT,//int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL2_CLAW_U_K_SCALE,//float knockbackScale; + qtrue, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL3, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level3", //char *weaponName; + "Pounce", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL3_CLAW_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL3_CLAW_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL3_UPG, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level3upg", //char *weaponName; + "Pounce (upgrade)", //char *weaponHumanName; + 3, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL3_CLAW_U_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + LEVEL3_BOUNCEBALL_REPEAT,//int repeatRate3; + 0, //int reloadTime; + LEVEL3_CLAW_U_K_SCALE,//float knockbackScale; + qfalse, //qboolean hasAltMode; + qtrue, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qtrue, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_ALEVEL4, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "level4", //char *weaponName; + "Charge", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL4_CLAW_REPEAT, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + LEVEL4_CLAW_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_LOCKBLOB_LAUNCHER, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "lockblob", //char *weaponName; + "Lock Blob", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; + 0, //int reloadTime; + LOCKBLOB_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_HIVE, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "hive", //char *weaponName; + "Hive", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; + 0, //int reloadTime; + HIVE_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_ALIENS //WUTeam_t team; + }, + { + WP_MGTURRET, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "mgturret", //char *weaponName; + "Machinegun Turret", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + 0, //int repeatRate1; + 0, //int repeatRate2; + 0, //int repeatRate3; + 0, //int reloadTime; + MGTURRET_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + }, + { + WP_TESLAGEN, //int weaponNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_WEAPON, //int slots; + "teslagen", //char *weaponName; + "Tesla Generator", //char *weaponHumanName; + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qtrue, //int usesEnergy; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; + 0, //int reloadTime; + TESLAGEN_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; + qfalse, //qboolean hasThirdMode; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + 0, //int buildDelay; + WUT_HUMANS //WUTeam_t team; + } +}; + +int bg_numWeapons = sizeof( bg_weapons ) / sizeof( bg_weapons[ 0 ] ); + +/* +============== +BG_FindPriceForWeapon +============== +*/ +int BG_FindPriceForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].price; + } + } + + return 100; +} + +/* +============== +BG_FindStagesForWeapon +============== +*/ +qboolean BG_FindStagesForWeapon( int weapon, stage_t stage ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + if( bg_weapons[ i ].stages & ( 1 << stage ) ) + return qtrue; + else + return qfalse; + } + } + + return qfalse; +} + +/* +============== +BG_FindSlotsForWeapon +============== +*/ +int BG_FindSlotsForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].slots; + } + } + + return SLOT_WEAPON; +} + +/* +============== +BG_FindNameForWeapon +============== +*/ +char *BG_FindNameForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + return bg_weapons[ i ].weaponName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindWeaponNumForName +============== +*/ +int BG_FindWeaponNumForName( char *name ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( !Q_stricmp( bg_weapons[ i ].weaponName, name ) ) + return bg_weapons[ i ].weaponNum; + } + + //wimp out + return WP_NONE; +} + +/* +============== +BG_FindHumanNameForWeapon +============== +*/ +char *BG_FindHumanNameForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + return bg_weapons[ i ].weaponHumanName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindAmmoForWeapon +============== +*/ +void BG_FindAmmoForWeapon( int weapon, int *maxAmmo, int *maxClips ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + if( maxAmmo != NULL ) + *maxAmmo = bg_weapons[ i ].maxAmmo; + if( maxClips != NULL ) + *maxClips = bg_weapons[ i ].maxClips; + + //no need to keep going + break; + } + } +} + +/* +============== +BG_FindInfinteAmmoForWeapon +============== +*/ +qboolean BG_FindInfinteAmmoForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].infiniteAmmo; + } + } + + return qfalse; +} + +/* +============== +BG_FindUsesEnergyForWeapon +============== +*/ +qboolean BG_FindUsesEnergyForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].usesEnergy; + } + } + + return qfalse; +} + +/* +============== +BG_FindRepeatRate1ForWeapon +============== +*/ +int BG_FindRepeatRate1ForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + return bg_weapons[ i ].repeatRate1; + } + + return 1000; +} + +/* +============== +BG_FindRepeatRate2ForWeapon +============== +*/ +int BG_FindRepeatRate2ForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + return bg_weapons[ i ].repeatRate2; + } + + return 1000; +} + +/* +============== +BG_FindRepeatRate3ForWeapon +============== +*/ +int BG_FindRepeatRate3ForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + return bg_weapons[ i ].repeatRate3; + } + + return 1000; +} + +/* +============== +BG_FindReloadTimeForWeapon +============== +*/ +int BG_FindReloadTimeForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].reloadTime; + } + } + + return 1000; +} + +/* +============== +BG_FindKnockbackScaleForWeapon +============== +*/ +float BG_FindKnockbackScaleForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].knockbackScale; + } + } + + return 1.0f; +} + +/* +============== +BG_WeaponHasAltMode +============== +*/ +qboolean BG_WeaponHasAltMode( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].hasAltMode; + } + } + + return qfalse; +} + +/* +============== +BG_WeaponHasThirdMode +============== +*/ +qboolean BG_WeaponHasThirdMode( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].hasThirdMode; + } + } + + return qfalse; +} + +/* +============== +BG_WeaponCanZoom +============== +*/ +qboolean BG_WeaponCanZoom( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].canZoom; + } + } + + return qfalse; +} + +/* +============== +BG_FindZoomFovForWeapon +============== +*/ +float BG_FindZoomFovForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].zoomFov; + } + } + + return qfalse; +} + +/* +============== +BG_FindPurchasableForWeapon +============== +*/ +qboolean BG_FindPurchasableForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].purchasable; + } + } + + return qfalse; +} + +/* +============== +BG_FindLongRangeForWeapon +============== +*/ +qboolean BG_FindLongRangedForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].longRanged; + } + } + + return qfalse; +} + +/* +============== +BG_FindBuildDelayForWeapon +============== +*/ +int BG_FindBuildDelayForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].buildDelay; + } + } + + return 0; +} + +/* +============== +BG_FindTeamForWeapon +============== +*/ +WUTeam_t BG_FindTeamForWeapon( int weapon ) +{ + int i; + + for( i = 0; i < bg_numWeapons; i++ ) + { + if( bg_weapons[ i ].weaponNum == weapon ) + { + return bg_weapons[ i ].team; + } + } + + return WUT_NONE; +} + +//////////////////////////////////////////////////////////////////////////////// + +upgradeAttributes_t bg_upgrades[ ] = +{ + { + UP_LIGHTARMOUR, //int upgradeNum; + LIGHTARMOUR_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_TORSO|SLOT_ARMS|SLOT_LEGS, //int slots; + "larmour", //char *upgradeName; + "Light Armour", //char *upgradeHumanName; + "icons/iconu_larmour", + qtrue, //qboolean purchasable + qfalse, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_HELMET, //int upgradeNum; + HELMET_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_HEAD, //int slots; + "helmet", //char *upgradeName; + "Helmet", //char *upgradeHumanName; + "icons/iconu_helmet", + qtrue, //qboolean purchasable + qfalse, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_MEDKIT, //int upgradeNum; + MEDKIT_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_NONE, //int slots; + "medkit", //char *upgradeName; + "Medkit", //char *upgradeHumanName; + "icons/iconu_atoxin", + qfalse, //qboolean purchasable + qtrue, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_BATTPACK, //int upgradeNum; + BATTPACK_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_BACKPACK, //int slots; + "battpack", //char *upgradeName; + "Battery Pack", //char *upgradeHumanName; + "icons/iconu_battpack", + qtrue, //qboolean purchasable + qfalse, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_JETPACK, //int upgradeNum; + JETPACK_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_BACKPACK, //int slots; + "jetpack", //char *upgradeName; + "Jet Pack", //char *upgradeHumanName; + "icons/iconu_jetpack", + qtrue, //qboolean purchasable + qtrue, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_BATTLESUIT, //int upgradeNum; + BSUIT_PRICE, //int price; + ( 1 << S3 ), //int stages + SLOT_HEAD|SLOT_TORSO|SLOT_ARMS|SLOT_LEGS|SLOT_BACKPACK, //int slots; + "bsuit", //char *upgradeName; + "Battlesuit", //char *upgradeHumanName; + "icons/iconu_bsuit", + qtrue, //qboolean purchasable + qfalse, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_GRENADE, //int upgradeNum; + GRENADE_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ),//int stages + SLOT_NONE, //int slots; + "gren", //char *upgradeName; + "Grenade", //char *upgradeHumanName; + 0, + qtrue, //qboolean purchasable + qtrue, //qboolean usable + WUT_HUMANS //WUTeam_t team; + }, + { + UP_AMMO, //int upgradeNum; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + SLOT_NONE, //int slots; + "ammo", //char *upgradeName; + "Ammunition", //char *upgradeHumanName; + 0, + qtrue, //qboolean purchasable + qfalse, //qboolean usable + WUT_HUMANS //WUTeam_t team; + } +}; + +int bg_numUpgrades = sizeof( bg_upgrades ) / sizeof( bg_upgrades[ 0 ] ); + +/* +============== +BG_FindPriceForUpgrade +============== +*/ +int BG_FindPriceForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + { + return bg_upgrades[ i ].price; + } + } + + return 100; +} + +/* +============== +BG_FindStagesForUpgrade +============== +*/ +qboolean BG_FindStagesForUpgrade( int upgrade, stage_t stage ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + { + if( bg_upgrades[ i ].stages & ( 1 << stage ) ) + return qtrue; + else + return qfalse; + } + } + + return qfalse; +} + +/* +============== +BG_FindSlotsForUpgrade +============== +*/ +int BG_FindSlotsForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + { + return bg_upgrades[ i ].slots; + } + } + + return SLOT_NONE; +} + +/* +============== +BG_FindNameForUpgrade +============== +*/ +char *BG_FindNameForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + return bg_upgrades[ i ].upgradeName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindUpgradeNumForName +============== +*/ +int BG_FindUpgradeNumForName( char *name ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( !Q_stricmp( bg_upgrades[ i ].upgradeName, name ) ) + return bg_upgrades[ i ].upgradeNum; + } + + //wimp out + return UP_NONE; +} + +/* +============== +BG_FindHumanNameForUpgrade +============== +*/ +char *BG_FindHumanNameForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + return bg_upgrades[ i ].upgradeHumanName; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindIconForUpgrade +============== +*/ +char *BG_FindIconForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + return bg_upgrades[ i ].icon; + } + + //wimp out + return 0; +} + +/* +============== +BG_FindPurchasableForUpgrade +============== +*/ +qboolean BG_FindPurchasableForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + return bg_upgrades[ i ].purchasable; + } + + return qfalse; +} + +/* +============== +BG_FindUsableForUpgrade +============== +*/ +qboolean BG_FindUsableForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + return bg_upgrades[ i ].usable; + } + + return qfalse; +} + +/* +============== +BG_FindTeamForUpgrade +============== +*/ +WUTeam_t BG_FindTeamForUpgrade( int upgrade ) +{ + int i; + + for( i = 0; i < bg_numUpgrades; i++ ) + { + if( bg_upgrades[ i ].upgradeNum == upgrade ) + { + return bg_upgrades[ i ].team; + } + } + + return WUT_NONE; +} + +//////////////////////////////////////////////////////////////////////////////// + +/* +================ +BG_EvaluateTrajectory + +================ +*/ +void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) +{ + float deltaTime; + float phase; + + switch( tr->trType ) + { + case TR_STATIONARY: + case TR_INTERPOLATE: + 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; + + 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; + + case TR_BUOYANCY: + 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; + + 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 ) +{ + 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; + + 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; + + case TR_BUOYANCY: + deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds + VectorCopy( tr->trDelta, result ); + result[ 2 ] += DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity... + break; + + default: + Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime ); + break; + } +} + +char *eventnames[ ] = +{ + "EV_NONE", + + "EV_FOOTSTEP", + "EV_FOOTSTEP_METAL", + "EV_FOOTSTEP_SQUELCH", + "EV_FOOTSPLASH", + "EV_FOOTWADE", + "EV_SWIM", + + "EV_STEP_4", + "EV_STEP_8", + "EV_STEP_12", + "EV_STEP_16", + + "EV_STEPDN_4", + "EV_STEPDN_8", + "EV_STEPDN_12", + "EV_STEPDN_16", + + "EV_FALL_SHORT", + "EV_FALL_MEDIUM", + "EV_FALL_FAR", + "EV_FALLING", + + "EV_JUMP", + "EV_WATER_TOUCH", // foot touches + "EV_WATER_LEAVE", // foot leaves + "EV_WATER_UNDER", // head touches + "EV_WATER_CLEAR", // head leaves + + "EV_NOAMMO", + "EV_CHANGE_WEAPON", + "EV_FIRE_WEAPON", + "EV_FIRE_WEAPON2", + "EV_FIRE_WEAPON3", + + "EV_PLAYER_RESPAWN", //TA: for fovwarp effects + "EV_PLAYER_TELEPORT_IN", + "EV_PLAYER_TELEPORT_OUT", + + "EV_GRENADE_BOUNCE", // eventParm will be the soundindex + + "EV_GENERAL_SOUND", + "EV_GLOBAL_SOUND", // no attenuation + + "EV_BULLET_HIT_FLESH", + "EV_BULLET_HIT_WALL", + + "EV_SHOTGUN", + + "EV_MISSILE_HIT", + "EV_MISSILE_MISS", + "EV_MISSILE_MISS_METAL", + "EV_TESLATRAIL", + "EV_BULLET", // otherEntity is the shooter + + "EV_LEV1_GRAB", + "EV_LEV4_CHARGE_PREPARE", + "EV_LEV4_CHARGE_START", + + "EV_PAIN", + "EV_DEATH1", + "EV_DEATH2", + "EV_DEATH3", + "EV_OBITUARY", + + "EV_GIB_PLAYER", // gib a previously living player + + "EV_BUILD_CONSTRUCT", //TA + "EV_BUILD_DESTROY", //TA + "EV_BUILD_DELAY", //TA: can't build yet + "EV_BUILD_REPAIR", //TA: repairing buildable + "EV_BUILD_REPAIRED", //TA: buildable has full health + "EV_HUMAN_BUILDABLE_EXPLOSION", + "EV_ALIEN_BUILDABLE_EXPLOSION", + "EV_ALIEN_ACIDTUBE", + + "EV_MEDKIT_USED", + + "EV_ALIEN_EVOLVE", + "EV_ALIEN_EVOLVE_FAILED", + + "EV_DEBUG_LINE", + "EV_STOPLOOPINGSOUND", + "EV_TAUNT", + + "EV_OVERMIND_ATTACK", //TA: overmind under attack + "EV_OVERMIND_DYING", //TA: overmind close to death + "EV_OVERMIND_SPAWNS", //TA: overmind needs spawns + + "EV_DCC_ATTACK", //TA: dcc under attack + + "EV_RPTUSE_SOUND" //TA: trigger a sound +}; + +/* +=============== +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_PS_EVENTS - 1 ) ] = newEvent; + ps->eventParms[ ps->eventSequence & ( MAX_PS_EVENTS - 1 ) ] = eventParm; + ps->eventSequence++; +} + + +/* +======================== +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_type == PM_FREEZE ) + s->eType = ET_INVISIBLE; + else if( ps->persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) + 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 ); + + //set the trDelta for flag direction + VectorCopy( ps->velocity, s->pos.trDelta ); + + s->apos.trType = TR_INTERPOLATE; + VectorCopy( ps->viewangles, s->apos.trBase ); + + if( snap ) + SnapVector( s->apos.trBase ); + + //TA: i need for other things :) + //s->angles2[YAW] = ps->movementDir; + s->time2 = 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 + s->eFlags = ps->eFlags; + if( ps->stats[STAT_HEALTH] <= 0 ) + s->eFlags |= EF_DEAD; + else + s->eFlags &= ~EF_DEAD; + + if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED ) + s->eFlags |= EF_BLOBLOCKED; + else + s->eFlags &= ~EF_BLOBLOCKED; + + 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_PS_EVENTS ) + ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS; + + seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 ); + s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 ); + s->eventParm = ps->eventParms[ seq ]; + ps->entityEventSequence++; + } + + s->weapon = ps->weapon; + s->groundEntityNum = ps->groundEntityNum; + + //store items held and active items in modelindex and modelindex2 + s->modelindex = 0; + s->modelindex2 = 0; + for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_InventoryContainsUpgrade( i, ps->stats ) ) + { + s->modelindex |= 1 << i; + + if( BG_UpgradeIsActive( i, ps->stats ) ) + s->modelindex2 |= 1 << i; + } + } + + //TA: use powerups field to store team/class info: + s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); + + //TA: have to get the surfNormal thru somehow... + VectorCopy( ps->grapplePoint, s->angles2 ); + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) + s->eFlags |= EF_WALLCLIMBCEILING; + + s->loopSound = ps->loopSound; + s->generic1 = ps->generic1; + + if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES ) + s->generic1 = WPM_PRIMARY; + + s->otherEntityNum = ps->otherEntityNum; +} + + +/* +======================== +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_type == PM_FREEZE ) + s->eType = ET_INVISIBLE; + else if( ps->persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) + 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 ); + + //TA: i need for other things :) + //s->angles2[YAW] = ps->movementDir; + s->time2 = 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 + s->eFlags = ps->eFlags; + + if( ps->stats[STAT_HEALTH] <= 0 ) + s->eFlags |= EF_DEAD; + else + s->eFlags &= ~EF_DEAD; + + if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED ) + s->eFlags |= EF_BLOBLOCKED; + else + s->eFlags &= ~EF_BLOBLOCKED; + + 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_PS_EVENTS ) + ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS; + + seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 ); + s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 ); + s->eventParm = ps->eventParms[ seq ]; + ps->entityEventSequence++; + } + + s->weapon = ps->weapon; + s->groundEntityNum = ps->groundEntityNum; + + //store items held and active items in modelindex and modelindex2 + s->modelindex = 0; + s->modelindex2 = 0; + + for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_InventoryContainsUpgrade( i, ps->stats ) ) + { + s->modelindex |= 1 << i; + + if( BG_UpgradeIsActive( i, ps->stats ) ) + s->modelindex2 |= 1 << i; + } + } + + //TA: use powerups field to store team/class info: + s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); + + //TA: have to get the surfNormal thru somehow... + VectorCopy( ps->grapplePoint, s->angles2 ); + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) + s->eFlags |= EF_WALLCLIMBCEILING; + + s->loopSound = ps->loopSound; + s->generic1 = ps->generic1; + + if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES ) + s->generic1 = WPM_PRIMARY; + + s->otherEntityNum = ps->otherEntityNum; +} + +/* +======================== +BG_UnpackAmmoArray + +Extract the ammo quantity from the array +======================== +*/ +void BG_UnpackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int *ammo, int *clips ) +{ + int ammoarray[ 32 ]; + int i; + + for( i = 0; i <= 15; i++ ) + ammoarray[ i ] = psAmmo[ i ]; + + for( i = 16; i <= 31; i++ ) + ammoarray[ i ] = psAmmo2[ i - 16 ]; + + if( ammo != NULL ) + *ammo = ammoarray[ weapon ] & 0x0FFF; + + if( clips != NULL ) + *clips = ( ammoarray[ weapon ] >> 12 ) & 0x0F; +} + +/* +======================== +BG_PackAmmoArray + +Pack the ammo quantity into the array +======================== +*/ +void BG_PackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int ammo, int clips ) +{ + int weaponvalue; + + weaponvalue = ammo | ( clips << 12 ); + + if( weapon <= 15 ) + psAmmo[ weapon ] = weaponvalue; + else if( weapon >= 16 ) + psAmmo2[ weapon - 16 ] = weaponvalue; +} + +/* +======================== +BG_WeaponIsFull + +Check if a weapon has full ammo +======================== +*/ +qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] ) +{ + int maxAmmo, maxClips; + int ammo, clips; + + BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); + BG_UnpackAmmoArray( weapon, psAmmo, psAmmo2, &ammo, &clips ); + + if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) ) + maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); + + return ( maxAmmo == ammo ) && ( maxClips == clips ); +} + +/* +======================== +BG_AddWeaponToInventory + +Give a player a weapon +======================== +*/ +void BG_AddWeaponToInventory( int weapon, int stats[ ] ) +{ + int weaponList; + + weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 ); + + weaponList |= ( 1 << weapon ); + + stats[ STAT_WEAPONS ] = weaponList & 0x0000FFFF; + stats[ STAT_WEAPONS2 ] = ( weaponList & 0xFFFF0000 ) >> 16; + + if( stats[ STAT_SLOTS ] & BG_FindSlotsForWeapon( weapon ) ) + Com_Printf( S_COLOR_YELLOW "WARNING: Held items conflict with weapon %d\n", weapon ); + + stats[ STAT_SLOTS ] |= BG_FindSlotsForWeapon( weapon ); +} + +/* +======================== +BG_RemoveWeaponToInventory + +Take a weapon from a player +======================== +*/ +void BG_RemoveWeaponFromInventory( int weapon, int stats[ ] ) +{ + int weaponList; + + weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 ); + + weaponList &= ~( 1 << weapon ); + + stats[ STAT_WEAPONS ] = weaponList & 0x0000FFFF; + stats[ STAT_WEAPONS2 ] = ( weaponList & 0xFFFF0000 ) >> 16; + + stats[ STAT_SLOTS ] &= ~BG_FindSlotsForWeapon( weapon ); +} + +/* +======================== +BG_InventoryContainsWeapon + +Does the player hold a weapon? +======================== +*/ +qboolean BG_InventoryContainsWeapon( int weapon, int stats[ ] ) +{ + int weaponList; + + weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 ); + + return( weaponList & ( 1 << weapon ) ); +} + +/* +======================== +BG_AddUpgradeToInventory + +Give the player an upgrade +======================== +*/ +void BG_AddUpgradeToInventory( int item, int stats[ ] ) +{ + stats[ STAT_ITEMS ] |= ( 1 << item ); + + if( stats[ STAT_SLOTS ] & BG_FindSlotsForUpgrade( item ) ) + Com_Printf( S_COLOR_YELLOW "WARNING: Held items conflict with upgrade %d\n", item ); + + stats[ STAT_SLOTS ] |= BG_FindSlotsForUpgrade( item ); +} + +/* +======================== +BG_RemoveUpgradeFromInventory + +Take an upgrade from the player +======================== +*/ +void BG_RemoveUpgradeFromInventory( int item, int stats[ ] ) +{ + stats[ STAT_ITEMS ] &= ~( 1 << item ); + + stats[ STAT_SLOTS ] &= ~BG_FindSlotsForUpgrade( item ); +} + +/* +======================== +BG_InventoryContainsUpgrade + +Does the player hold an upgrade? +======================== +*/ +qboolean BG_InventoryContainsUpgrade( int item, int stats[ ] ) +{ + return( stats[ STAT_ITEMS ] & ( 1 << item ) ); +} + +/* +======================== +BG_ActivateUpgrade + +Activates an upgrade +======================== +*/ +void BG_ActivateUpgrade( int item, int stats[ ] ) +{ + stats[ STAT_ACTIVEITEMS ] |= ( 1 << item ); +} + +/* +======================== +BG_DeactivateUpgrade + +Deactivates an upgrade +======================== +*/ +void BG_DeactivateUpgrade( int item, int stats[ ] ) +{ + stats[ STAT_ACTIVEITEMS ] &= ~( 1 << item ); +} + +/* +======================== +BG_UpgradeIsActive + +Is this upgrade active? +======================== +*/ +qboolean BG_UpgradeIsActive( int item, int stats[ ] ) +{ + return( stats[ STAT_ACTIVEITEMS ] & ( 1 << item ) ); +} + +/* +=============== +BG_RotateAxis + +Shared axis rotation function +=============== +*/ +qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ], + vec3_t outAxis[ 3 ], qboolean inverse, qboolean ceiling ) +{ + vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; + vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; + vec3_t localNormal, xNormal; + float rotAngle; + + //the grapplePoint being a surfNormal rotation Normal hack... see above :) + if( ceiling ) + { + VectorCopy( ceilingNormal, localNormal ); + VectorCopy( surfNormal, xNormal ); + } + else + { + //cross the reference normal and the surface normal to get the rotation axis + VectorCopy( surfNormal, localNormal ); + CrossProduct( localNormal, refNormal, xNormal ); + VectorNormalize( xNormal ); + } + + //can't rotate with no rotation vector + if( VectorLength( xNormal ) != 0.0f ) + { + rotAngle = RAD2DEG( acos( DotProduct( localNormal, refNormal ) ) ); + + if( inverse ) + rotAngle = -rotAngle; + + AngleNormalize180( rotAngle ); + + //hmmm could get away with only one rotation and some clever stuff later... but i'm lazy + RotatePointAroundVector( outAxis[ 0 ], xNormal, inAxis[ 0 ], -rotAngle ); + RotatePointAroundVector( outAxis[ 1 ], xNormal, inAxis[ 1 ], -rotAngle ); + RotatePointAroundVector( outAxis[ 2 ], xNormal, inAxis[ 2 ], -rotAngle ); + } + else + return qfalse; + + return qtrue; +} + +/* +=============== +BG_PositionBuildableRelativeToPlayer + +Find a place to build a buildable +=============== +*/ +void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps, + const vec3_t mins, const vec3_t maxs, + void (*trace)( trace_t *, const vec3_t, const vec3_t, + const vec3_t, const vec3_t, int, int ), + vec3_t outOrigin, vec3_t outAngles, trace_t *tr ) +{ + vec3_t forward, entityOrigin, targetOrigin; + vec3_t angles, playerOrigin, playerNormal; + float buildDist; + + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) + { + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) + VectorSet( playerNormal, 0.0f, 0.0f, -1.0f ); + else + VectorCopy( ps->grapplePoint, playerNormal ); + } + else + VectorSet( playerNormal, 0.0f, 0.0f, 1.0f ); + + VectorCopy( ps->viewangles, angles ); + VectorCopy( ps->origin, playerOrigin ); + buildDist = BG_FindBuildDistForClass( ps->stats[ STAT_PCLASS ] ); + + AngleVectors( angles, forward, NULL, NULL ); + ProjectPointOnPlane( forward, forward, playerNormal ); + VectorNormalize( forward ); + + VectorMA( playerOrigin, buildDist, forward, entityOrigin ); + + VectorCopy( entityOrigin, targetOrigin ); + + //so buildings can be placed facing slopes + VectorMA( entityOrigin, 32, playerNormal, entityOrigin ); + + //so buildings drop to floor + VectorMA( targetOrigin, -128, playerNormal, targetOrigin ); + + (*trace)( tr, entityOrigin, mins, maxs, targetOrigin, ps->clientNum, MASK_PLAYERSOLID ); + VectorCopy( tr->endpos, entityOrigin ); + VectorMA( entityOrigin, 0.1f, playerNormal, outOrigin ); + vectoangles( forward, outAngles ); +} + +/* +=============== +BG_GetValueOfEquipment + +Returns the equipment value of some human player's gear +=============== +*/ + int BG_GetValueOfEquipment( playerState_t *ps ) { + int i, worth = 0; + + for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_InventoryContainsUpgrade( i, ps->stats ) ) + worth += BG_FindPriceForUpgrade( i ); + } + + for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) + { + if( BG_InventoryContainsWeapon( i, ps->stats ) ) + worth += BG_FindPriceForWeapon( i ); + } + + return worth; + } +/* +=============== +BG_GetValueOfHuman + +Returns the kills value of some human player +=============== +*/ +int BG_GetValueOfHuman( playerState_t *ps ) +{ + float portion = BG_GetValueOfEquipment( ps ) / (float)HUMAN_MAXED; + + + if( portion < 0.01f ) + portion = 0.01f; + else if( portion > 1.0f ) + portion = 1.0f; + + return ceil( ALIEN_MAX_SINGLE_KILLS * portion ); +} + +/* +=============== +atof_neg + +atof with an allowance for negative values +=============== +*/ +float atof_neg( char *token, qboolean allowNegative ) +{ + float value; + + value = atof( token ); + + if( !allowNegative && value < 0.0f ) + value = 1.0f; + + return value; +} + +/* +=============== +atoi_neg + +atoi with an allowance for negative values +=============== +*/ +int atoi_neg( char *token, qboolean allowNegative ) +{ + int value; + + value = atoi( token ); + + if( !allowNegative && value < 0 ) + value = 1; + + return value; +} + +/* +=============== +BG_ParseCSVEquipmentList +=============== +*/ +void BG_ParseCSVEquipmentList( const char *string, weapon_t *weapons, int weaponsSize, + upgrade_t *upgrades, int upgradesSize ) +{ + char buffer[ MAX_STRING_CHARS ]; + int i = 0, j = 0; + char *p, *q; + qboolean EOS = qfalse; + + Q_strncpyz( buffer, string, MAX_STRING_CHARS ); + + p = q = buffer; + + while( *p != '\0' ) + { + //skip to first , or EOS + while( *p != ',' && *p != '\0' ) + p++; + + if( *p == '\0' ) + EOS = qtrue; + + *p = '\0'; + + //strip leading whitespace + while( *q == ' ' ) + q++; + + if( weaponsSize ) + weapons[ i ] = BG_FindWeaponNumForName( q ); + + if( upgradesSize ) + upgrades[ j ] = BG_FindUpgradeNumForName( q ); + + if( weaponsSize && weapons[ i ] == WP_NONE && + upgradesSize && upgrades[ j ] == UP_NONE ) + Com_Printf( S_COLOR_YELLOW "WARNING: unknown equipment %s\n", q ); + else if( weaponsSize && weapons[ i ] != WP_NONE ) + i++; + else if( upgradesSize && upgrades[ j ] != UP_NONE ) + j++; + + if( !EOS ) + { + p++; + q = p; + } + else + break; + + if( i == ( weaponsSize - 1 ) || j == ( upgradesSize - 1 ) ) + break; + } + + if( weaponsSize ) + weapons[ i ] = WP_NONE; + + if( upgradesSize ) + upgrades[ j ] = UP_NONE; +} + +/* +=============== +BG_ParseCSVClassList +=============== +*/ +void BG_ParseCSVClassList( const char *string, pClass_t *classes, int classesSize ) +{ + char buffer[ MAX_STRING_CHARS ]; + int i = 0; + char *p, *q; + qboolean EOS = qfalse; + + Q_strncpyz( buffer, string, MAX_STRING_CHARS ); + + p = q = buffer; + + while( *p != '\0' ) + { + //skip to first , or EOS + while( *p != ',' && *p != '\0' ) + p++; + + if( *p == '\0' ) + EOS = qtrue; + + *p = '\0'; + + //strip leading whitespace + while( *q == ' ' ) + q++; + + classes[ i ] = BG_FindClassNumForName( q ); + + if( classes[ i ] == PCL_NONE ) + Com_Printf( S_COLOR_YELLOW "WARNING: unknown class %s\n", q ); + else + i++; + + if( !EOS ) + { + p++; + q = p; + } + else + break; + } + + classes[ i ] = PCL_NONE; +} + +/* +=============== +BG_ParseCSVBuildableList +=============== +*/ +void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int buildablesSize ) +{ + char buffer[ MAX_STRING_CHARS ]; + int i = 0; + char *p, *q; + qboolean EOS = qfalse; + + Q_strncpyz( buffer, string, MAX_STRING_CHARS ); + + p = q = buffer; + + while( *p != '\0' ) + { + //skip to first , or EOS + while( *p != ',' && *p != '\0' ) + p++; + + if( *p == '\0' ) + EOS = qtrue; + + *p = '\0'; + + //strip leading whitespace + while( *q == ' ' ) + q++; + + buildables[ i ] = BG_FindBuildNumForName( q ); + + if( buildables[ i ] == BA_NONE ) + Com_Printf( S_COLOR_YELLOW "WARNING: unknown buildable %s\n", q ); + else + i++; + + if( !EOS ) + { + p++; + q = p; + } + else + break; + } + + buildables[ i ] = BA_NONE; +} + +/* +============ +BG_UpgradeClassAvailable +============ +*/ +qboolean BG_UpgradeClassAvailable( playerState_t *ps ) +{ + int i; + char buffer[ MAX_STRING_CHARS ]; + stage_t currentStage; + + trap_Cvar_VariableStringBuffer( "g_alienStage", buffer, MAX_STRING_CHARS ); + currentStage = atoi( buffer ); + + for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) + { + if( BG_ClassCanEvolveFromTo( ps->stats[ STAT_PCLASS ], i, + ps->persistant[ PERS_CREDIT ], 0 ) >= 0 && + BG_FindStagesForClass( i, currentStage ) && + BG_ClassIsAllowed( i ) ) + { + return qtrue; + } + } + + return qfalse; +} + +typedef struct gameElements_s +{ + buildable_t buildables[ BA_NUM_BUILDABLES ]; + pClass_t classes[ PCL_NUM_CLASSES ]; + weapon_t weapons[ WP_NUM_WEAPONS ]; + upgrade_t upgrades[ UP_NUM_UPGRADES ]; +} gameElements_t; + +static gameElements_t bg_disabledGameElements; + +/* +============ +BG_InitAllowedGameElements +============ +*/ +void BG_InitAllowedGameElements( void ) +{ + char cvar[ MAX_CVAR_VALUE_STRING ]; + + trap_Cvar_VariableStringBuffer( "g_disabledEquipment", + cvar, MAX_CVAR_VALUE_STRING ); + + BG_ParseCSVEquipmentList( cvar, + bg_disabledGameElements.weapons, WP_NUM_WEAPONS, + bg_disabledGameElements.upgrades, UP_NUM_UPGRADES ); + + trap_Cvar_VariableStringBuffer( "g_disabledClasses", + cvar, MAX_CVAR_VALUE_STRING ); + + BG_ParseCSVClassList( cvar, + bg_disabledGameElements.classes, PCL_NUM_CLASSES ); + + trap_Cvar_VariableStringBuffer( "g_disabledBuildables", + cvar, MAX_CVAR_VALUE_STRING ); + + BG_ParseCSVBuildableList( cvar, + bg_disabledGameElements.buildables, BA_NUM_BUILDABLES ); +} + +/* +============ +BG_WeaponIsAllowed +============ +*/ +qboolean BG_WeaponIsAllowed( weapon_t weapon ) +{ + int i; + + for( i = 0; i < WP_NUM_WEAPONS && + bg_disabledGameElements.weapons[ i ] != WP_NONE; i++ ) + { + if( bg_disabledGameElements.weapons[ i ] == weapon ) + return qfalse; + } + + return qtrue; +} + +/* +============ +BG_UpgradeIsAllowed +============ +*/ +qboolean BG_UpgradeIsAllowed( upgrade_t upgrade ) +{ + int i; + + for( i = 0; i < UP_NUM_UPGRADES && + bg_disabledGameElements.upgrades[ i ] != UP_NONE; i++ ) + { + if( bg_disabledGameElements.upgrades[ i ] == upgrade ) + return qfalse; + } + + return qtrue; +} + +/* +============ +BG_ClassIsAllowed +============ +*/ +qboolean BG_ClassIsAllowed( pClass_t class ) +{ + int i; + + for( i = 0; i < PCL_NUM_CLASSES && + bg_disabledGameElements.classes[ i ] != PCL_NONE; i++ ) + { + if( bg_disabledGameElements.classes[ i ] == class ) + return qfalse; + } + + return qtrue; +} + +/* +============ +BG_BuildableIsAllowed +============ +*/ +qboolean BG_BuildableIsAllowed( buildable_t buildable ) +{ + int i; + + for( i = 0; i < BA_NUM_BUILDABLES && + bg_disabledGameElements.buildables[ i ] != BA_NONE; i++ ) + { + if( bg_disabledGameElements.buildables[ i ] == buildable ) + return qfalse; + } + + return qtrue; +} + +/* +============ +BG_ClientListTest +============ +*/ +qboolean BG_ClientListTest( clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return qfalse; + if( clientNum < 32 ) + return ( ( list->lo & ( 1 << clientNum ) ) != 0 ); + else + return ( ( list->hi & ( 1 << ( clientNum - 32 ) ) ) != 0 ); +} + +/* +============ +BG_ClientListAdd +============ +*/ +void BG_ClientListAdd( clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return; + if( clientNum < 32 ) + list->lo |= ( 1 << clientNum ); + else + list->hi |= ( 1 << ( clientNum - 32 ) ); +} + +/* +============ +BG_ClientListRemove +============ +*/ +void BG_ClientListRemove( clientList_t *list, int clientNum ) +{ + if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) + return; + if( clientNum < 32 ) + list->lo &= ~( 1 << clientNum ); + else + list->hi &= ~( 1 << ( clientNum - 32 ) ); +} + +/* +============ +BG_ClientListString +============ +*/ +char *BG_ClientListString( clientList_t *list ) +{ + static char s[ 17 ]; + + s[ 0 ] = '\0'; + if( !list ) + return s; + Com_sprintf( s, sizeof( s ), "%08x%08x", list->hi, list->lo ); + return s; +} + +/* +============ +BG_ClientListParse +============ +*/ +void BG_ClientListParse( clientList_t *list, const char *s ) +{ + if( !list ) + return; + list->lo = 0; + list->hi = 0; + if( !s ) + return; + if( strlen( s ) != 16 ) + return; + sscanf( s, "%x%x", &list->hi, &list->lo ); +} + + |