diff options
Diffstat (limited to 'src/game/bg_misc.c')
-rw-r--r-- | src/game/bg_misc.c | 4714 |
1 files changed, 1475 insertions, 3239 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index fd50509..e30a754 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -1,13 +1,14 @@ /* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2006 Tim Angus +Copyright (C) 2000-2013 Darklegion Development +Copyright (C) 2015-2019 GrangerHub 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, +published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Tremulous is distributed in the hope that it will be @@ -16,45 +17,44 @@ 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 +along with Tremulous; if not, see <https://www.gnu.org/licenses/> + =========================================================================== */ // bg_misc.c -- both games misc functions, all completely stateless -#include "../qcommon/q_shared.h" +#include "qcommon/q_shared.h" #include "bg_public.h" -int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ); +int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, enum FS_Mode 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 +void trap_FS_Seek( fileHandle_t f, long offset, enum FS_Origin origin ); // fsOrigin_t +int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize ); -buildableAttributes_t bg_buildableList[ ] = +static const buildableAttributes_t bg_buildableList[ ] = { { - BA_A_SPAWN, //int buildNum; - "eggpod", //char *buildName; + BA_A_SPAWN, //int number; + "eggpod", //char *name; "Egg", //char *humanName; + "The most basic alien structure. It allows aliens to spawn " + "and protect the Overmind. Without any of these, the Overmind " + "is left nearly defenseless and defeat is imminent.", "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 + ( 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; ASPAWN_BT, //int buildTime; @@ -68,70 +68,66 @@ buildableAttributes_t bg_buildableList[ ] = ASPAWN_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + ASPAWN_VALUE, //int value; }, { - 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; + BA_A_OVERMIND, //int number; + "overmind", //char *name; + "Overmind", //char *humanName; + "A collective consciousness that controls all the alien structures " + "in its vicinity. It must be protected at all costs, since its " + "death will render alien structures defenseless.", + "team_alien_overmind", //char *entityName; 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; + 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; - 100, //int nextthink; - BARRICADE_BT, //int buildTime; + OVERMIND_ATTACK_REPEAT, //int nextthink; + OVERMIND_BT, //int buildTime; qfalse, //qboolean usable; 0, //int turretRange; 0, //int turretFireSpeed; WP_NONE, //weapon_t turretProjType; - 0.707f, //float minNormal; + 0.95f, //float minNormal; qfalse, //qboolean invertNormal; - qtrue, //qboolean creepTest; - BARRICADE_CREEPSIZE, //int creepSize; + qfalse, //qboolean creepTest; + OVERMIND_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replaceable; + qtrue, //qboolean uniqueTest; + OVERMIND_VALUE, //int value; }, { - 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; + BA_A_BARRICADE, //int number; + "barricade", //char *name; + "Barricade", //char *humanName; + "Used to obstruct corridors and doorways, hindering humans from " + "threatening the spawns and Overmind. Barricades will shrink " + "to allow aliens to pass over them, however.", + "team_alien_barricade", //char *entityName; 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; + 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; - BOOSTER_BT, //int buildTime; + BARRICADE_BT, //int buildTime; qfalse, //qboolean usable; 0, //int turretRange; 0, //int turretFireSpeed; @@ -139,33 +135,31 @@ buildableAttributes_t bg_buildableList[ ] = 0.707f, //float minNormal; qfalse, //qboolean invertNormal; qtrue, //qboolean creepTest; - BOOSTER_CREEPSIZE, //int creepSize; + BARRICADE_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; - qtrue, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qtrue, //qboolean replacable; + qfalse, //qboolean transparentTest; + qfalse, //qboolean uniqueTest; + BARRICADE_VALUE, //int value; }, { - BA_A_ACIDTUBE, //int buildNum; - "acid_tube", //char *buildName; + BA_A_ACIDTUBE, //int number; + "acid_tube", //char *name; "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; + "Ejects lethal poisonous acid at an approaching human. These " + "are highly effective when used in conjunction with a trapper " + "to hold the victim in place.", + "team_alien_acid_tube", //char *entityName; TR_GRAVITY, //trType_t traj; 0.0, //float bounce; ACIDTUBE_BP, //int buildPoints; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 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; + MOD_ASPAWN, //int meansOfDeath; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 200, //int nextthink; ACIDTUBE_BT, //int buildTime; @@ -179,67 +173,28 @@ buildableAttributes_t bg_buildableList[ ] = ACIDTUBE_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + ACIDTUBE_VALUE, //int value; }, { - 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; + BA_A_TRAPPER, //int number; + "trapper", //char *name; "Trapper", //char *humanName; + "Fires a blob of adhesive spit at any non-alien in its line of " + "sight. This hinders their movement, making them an easy target " + "for other defensive structures or aliens.", "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 + ( 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; TRAPPER_BT, //int buildTime; @@ -253,104 +208,98 @@ buildableAttributes_t bg_buildableList[ ] = TRAPPER_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; qtrue, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + TRAPPER_VALUE, //int value; }, { - 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; + BA_A_BOOSTER, //int number; + "booster", //char *name; + "Booster", //char *humanName; + "Laces the attacks of any alien that touches it with a poison " + "that will gradually deal damage to any humans exposed to it. " + "The booster also increases the rate of health regeneration for " + "any nearby aliens.", + "team_alien_booster", //char *entityName; 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; + 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; - OVERMIND_ATTACK_REPEAT,//int nextthink; - OVERMIND_BT, //int buildTime; + 100, //int nextthink; + BOOSTER_BT, //int buildTime; qfalse, //qboolean usable; 0, //int turretRange; 0, //int turretFireSpeed; WP_NONE, //weapon_t turretProjType; - 0.95f, //float minNormal; + 0.707f, //float minNormal; qfalse, //qboolean invertNormal; - qfalse, //qboolean creepTest; - OVERMIND_CREEPSIZE, //int creepSize; + qtrue, //qboolean creepTest; + BOOSTER_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; - qfalse, //qboolean transparentTest; - qtrue, //qboolean reactorTest; - qtrue, //qboolean replacable; + qtrue, //qboolean transparentTest; + qfalse, //qboolean uniqueTest; + BOOSTER_VALUE, //int value; }, { - 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; + BA_A_HIVE, //int number; + "hive", //char *name; + "Hive", //char *humanName; + "Houses millions of tiny insectoid aliens. When a human " + "approaches this structure, the insectoids attack.", + "team_alien_hive", //char *entityName; 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; + 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; + TEAM_ALIENS, //int team; + ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; - 150, //int nextthink; - HOVEL_BT, //int buildTime; - qtrue, //qboolean usable; + 500, //int nextthink; + HIVE_BT, //int buildTime; + qfalse, //qboolean usable; 0, //int turretRange; 0, //int turretFireSpeed; - WP_NONE, //weapon_t turretProjType; - 0.95f, //float minNormal; - qfalse, //qboolean invertNormal; + WP_HIVE, //weapon_t turretProjType; + 0.0f, //float minNormal; + qtrue, //qboolean invertNormal; qtrue, //qboolean creepTest; - HOVEL_CREEPSIZE, //int creepSize; + HIVE_CREEPSIZE, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qtrue, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + HIVE_VALUE, //int value; }, { - BA_H_SPAWN, //int buildNum; - "telenode", //char *buildName; + BA_H_SPAWN, //int number; + "telenode", //char *name; "Telenode", //char *humanName; + "The most basic human structure. It provides a means for humans " + "to enter the battle arena. Without any of these the humans " + "cannot spawn and defeat is imminent.", "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 + ( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; HSPAWN_BT, //int buildTime; @@ -364,69 +313,28 @@ buildableAttributes_t bg_buildableList[ ] = 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; + qfalse, //qboolean uniqueTest; + HSPAWN_VALUE, //int value; }, { - BA_H_MGTURRET, //int buildNum; - "mgturret", //char *buildName; + BA_H_MGTURRET, //int number; + "mgturret", //char *name; "Machinegun Turret", //char *humanName; + "Automated base defense that is effective against large targets " + "but slow to begin firing. Should always be " + "backed up by physical support.", "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 + ( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 50, //int nextthink; MGTURRET_BT, //int buildTime; @@ -440,30 +348,28 @@ buildableAttributes_t bg_buildableList[ ] = 0, //int creepSize; qfalse, //qboolean dccTest; qtrue, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + MGTURRET_VALUE, //int value; }, { - BA_H_TESLAGEN, //int buildNum; - "tesla", //char *buildName; + BA_H_TESLAGEN, //int number; + "tesla", //char *name; "Tesla Generator", //char *humanName; + "A structure equipped with a strong electrical attack that fires " + "instantly and always hits its target. It is effective against smaller " + "aliens and for consolidating basic defense.", "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 + ( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 150, //int nextthink; TESLAGEN_BT, //int buildTime; @@ -475,32 +381,65 @@ buildableAttributes_t bg_buildableList[ ] = qfalse, //qboolean invertNormal; qfalse, //qboolean creepTest; 0, //int creepSize; - qtrue, //qboolean dccTest; + qfalse, //qboolean dccTest; qtrue, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qfalse, //qboolean replacable; + qfalse, //qboolean uniqueTest; + TESLAGEN_VALUE, //int value; }, { - BA_H_DCC, //int buildNum; - "dcc", //char *buildName; + BA_H_ARMOURY, //int number; + "arm", //char *name; + "Armoury", //char *humanName; + "An essential part of the human base, providing a means " + "to upgrade the basic human equipment. A range of upgrades " + "and weapons are available for sale from the armoury.", + "team_human_armoury", //char *entityName; + 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //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 uniqueTest; + ARMOURY_VALUE, //int value; + }, + { + BA_H_DCC, //int number; + "dcc", //char *name; "Defence Computer", //char *humanName; + "A structure that enables self-repair functionality in " + "human structures. Each Defence Computer built increases " + "repair rate slightly.", "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 + ( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; DC_BT, //int buildTime; @@ -514,34 +453,33 @@ buildableAttributes_t bg_buildableList[ ] = 0, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qtrue, //qboolean replacable; + qfalse, //qboolean uniqueTest; + DC_VALUE, //int value; }, { - 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; + BA_H_MEDISTAT, //int number; + "medistat", //char *name; + "Medistation", //char *humanName; + "A structure that automatically restores " + "the health and stamina of any human that stands on it. " + "It may only be used by one person at a time. This structure " + "also issues medkits.", + "team_human_medistat", //char *entityName; 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; + MEDISTAT_BP, //int buildPoints; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; + MEDISTAT_HEALTH, //int health; 0, //int regenRate; - ARMOURY_SPLASHDAMAGE, //int splashDamage; - ARMOURY_SPLASHRADIUS, //int splashRadius; + 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; - ARMOURY_BT, //int buildTime; - qtrue, //qboolean usable; + MEDISTAT_BT, //int buildTime; + qfalse, //qboolean usable; 0, //int turretRange; 0, //int turretFireSpeed; WP_NONE, //weapon_t turretProjType; @@ -550,33 +488,31 @@ buildableAttributes_t bg_buildableList[ ] = qfalse, //qboolean creepTest; 0, //int creepSize; qfalse, //qboolean dccTest; - qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qtrue, //qboolean replacable; + qtrue, //qboolean transparentTest; + qfalse, //qboolean uniqueTest; + MEDISTAT_VALUE, //int value; }, { - BA_H_REACTOR, //int buildNum; - "reactor", //char *buildName; + BA_H_REACTOR, //int number; + "reactor", //char *name; "Reactor", //char *humanName; + "All structures except the telenode rely on a reactor to operate. " + "The reactor provides power for all the human structures either " + "directly or via repeaters. Only one reactor can be built at a time.", "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 + ( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; - REACTOR_ATTACK_REPEAT, //int nextthink; + REACTOR_ATTACK_DCC_REPEAT, //int nextthink; REACTOR_BT, //int buildTime; qtrue, //qboolean usable; 0, //int turretRange; @@ -588,30 +524,28 @@ buildableAttributes_t bg_buildableList[ ] = 0, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qtrue, //qboolean reactorTest; - qtrue, //qboolean replacable; + qtrue, //qboolean uniqueTest; + REACTOR_VALUE, //int value; }, { - BA_H_REPEATER, //int buildNum; - "repeater", //char *buildName; + BA_H_REPEATER, //int number; + "repeater", //char *name; "Repeater", //char *humanName; + "A power distributor that transmits power from the reactor " + "to remote locations, so that bases may be built far " + "from the reactor.", "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 + ( 1 << S1 )|( 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; + TEAM_HUMANS, //int team; + ( 1 << WP_HBUILD ), //weapon_t buildWeapon; BANIM_IDLE1, //int idleAnim; 100, //int nextthink; REPEATER_BT, //int buildTime; @@ -625,757 +559,115 @@ buildableAttributes_t bg_buildableList[ ] = 0, //int creepSize; qfalse, //qboolean dccTest; qfalse, //qboolean transparentTest; - qfalse, //qboolean reactorTest; - qtrue, //qboolean replacable; + qfalse, //qboolean uniqueTest; + REPEATER_VALUE, //int value; } }; -int bg_numBuildables = sizeof( bg_buildableList ) / sizeof( bg_buildableList[ 0 ] ); +size_t bg_numBuildables = ARRAY_LEN( bg_buildableList ); -//separate from bg_buildableList to work around char struct init bug -buildableAttributeOverrides_t bg_buildableOverrideList[ BA_NUM_BUILDABLES ]; +static const buildableAttributes_t nullBuildable = { 0 }; /* ============== -BG_FindBuildNumForName +BG_BuildableByName ============== */ -int BG_FindBuildNumForName( char *name ) +const buildableAttributes_t *BG_BuildableByName( const char *name ) { int i; for( i = 0; i < bg_numBuildables; i++ ) { - if( !Q_stricmp( bg_buildableList[ i ].buildName, name ) ) - return bg_buildableList[ i ].buildNum; + if( !Q_stricmp( bg_buildableList[ i ].name, name ) ) + return &bg_buildableList[ i ]; } - //wimp out - return BA_NONE; + return &nullBuildable; } /* ============== -BG_FindBuildNumForEntityName +BG_BuildableByEntityName ============== */ -int BG_FindBuildNumForEntityName( char *name ) +const buildableAttributes_t *BG_BuildableByEntityName( const char *name ) { int i; for( i = 0; i < bg_numBuildables; i++ ) { if( !Q_stricmp( bg_buildableList[ i ].entityName, name ) ) - return bg_buildableList[ i ].buildNum; + return &bg_buildableList[ i ]; } - //wimp out - return BA_NONE; + return &nullBuildable; } /* ============== -BG_FindNameForBuildNum +BG_Buildable ============== */ -char *BG_FindNameForBuildable( int bclass ) +const buildableAttributes_t *BG_Buildable( buildable_t buildable ) { - 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; + return ( buildable > BA_NONE && buildable < BA_NUM_BUILDABLES ) ? + &bg_buildableList[ buildable - 1 ] : &nullBuildable; } /* ============== -BG_FindEntityNameForBuildNum +BG_BuildableAllowedInStage ============== */ -char *BG_FindEntityNameForBuildable( int bclass ) +qboolean BG_BuildableAllowedInStage( buildable_t buildable, + stage_t stage ) { - int i; - - for( i = 0; i < bg_numBuildables; i++ ) - { - if( bg_buildableList[ i ].buildNum == bclass ) - return bg_buildableList[ i ].entityName; - } + int stages = BG_Buildable( buildable )->stages; - //wimp out - return 0; + if( stages & ( 1 << stage ) ) + return qtrue; + else + return qfalse; } -/* -============== -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; -} +static buildableConfig_t bg_buildableConfigList[ BA_NUM_BUILDABLES ]; /* ============== -BG_FindModelScaleForBuildable +BG_BuildableConfig ============== */ -float BG_FindModelScaleForBuildable( int bclass ) +buildableConfig_t *BG_BuildableConfig( buildable_t buildable ) { - 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; + return &bg_buildableConfigList[ buildable ]; } /* ============== -BG_FindBBoxForBuildable +BG_BuildableBoundingBox ============== */ -void BG_FindBBoxForBuildable( int bclass, vec3_t mins, vec3_t maxs ) +void BG_BuildableBoundingBox( buildable_t buildable, + 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; - } - } + buildableConfig_t *buildableConfig = BG_BuildableConfig( buildable ); if( mins != NULL ) - VectorCopy( bg_buildableList[ 0 ].mins, mins ); + VectorCopy( buildableConfig->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 WP_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; + VectorCopy( buildableConfig->maxs, maxs ); } /* ====================== BG_ParseBuildableFile -Parses a configuration file describing a builable +Parses a configuration file describing a buildable ====================== */ -static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeOverrides_t *bao ) +static qboolean BG_ParseBuildableFile( const char *filename, buildableConfig_t *bc ) { char *text_p; int i; @@ -1384,12 +676,24 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO char text[ 20000 ]; fileHandle_t f; float scale; + int defined = 0; + enum + { + MODEL = 1 << 0, + MODELSCALE = 1 << 1, + MINS = 1 << 2, + MAXS = 1 << 3, + ZOFFSET = 1 << 4 + }; // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); if( len < 0 ) + { + Com_Printf( S_COLOR_RED "ERROR: Buildable file %s doesn't exist\n", filename ); return qfalse; + } if( len == 0 || len >= sizeof( text ) - 1 ) { @@ -1436,8 +740,9 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO if( !token ) break; - Q_strncpyz( bao->models[ index ], token, sizeof( bao->models[ 0 ] ) ); + Q_strncpyz( bc->models[ index ], token, sizeof( bc->models[ 0 ] ) ); + defined |= MODEL; continue; } else if( !Q_stricmp( token, "modelScale" ) ) @@ -1451,8 +756,9 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO if( scale < 0.0f ) scale = 0.0f; - bao->modelScale = scale; + bc->modelScale = scale; + defined |= MODELSCALE; continue; } else if( !Q_stricmp( token, "mins" ) ) @@ -1463,9 +769,10 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO if( !token ) break; - bao->mins[ i ] = atof( token ); + bc->mins[ i ] = atof( token ); } + defined |= MINS; continue; } else if( !Q_stricmp( token, "maxs" ) ) @@ -1476,9 +783,10 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO if( !token ) break; - bao->maxs[ i ] = atof( token ); + bc->maxs[ i ] = atof( token ); } + defined |= MAXS; continue; } else if( !Q_stricmp( token, "zOffset" ) ) @@ -1491,8 +799,9 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO offset = atof( token ); - bao->zOffset = offset; + bc->zOffset = offset; + defined |= ZOFFSET; continue; } @@ -1501,59 +810,62 @@ static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeO return qfalse; } + if( !( defined & MODEL ) ) token = "model"; + else if( !( defined & MODELSCALE ) ) token = "modelScale"; + else if( !( defined & MINS ) ) token = "mins"; + else if( !( defined & MAXS ) ) token = "maxs"; + else if( !( defined & ZOFFSET ) ) token = "zOffset"; + else token = ""; + + if( strlen( token ) > 0 ) + { + Com_Printf( S_COLOR_RED "ERROR: %s not defined in %s\n", + token, filename ); + return qfalse; + } + return qtrue; } /* =============== -BG_InitBuildableOverrides - -Set any overrides specfied by file +BG_InitBuildableConfigs =============== */ -void BG_InitBuildableOverrides( void ) +void BG_InitBuildableConfigs( void ) { - int i; - buildableAttributeOverrides_t *bao; + int i; + buildableConfig_t *bc; for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) { - bao = BG_FindOverrideForBuildable( i ); + bc = BG_BuildableConfig( i ); + Com_Memset( bc, 0, sizeof( buildableConfig_t ) ); - BG_ParseBuildableFile( va( "overrides/buildables/%s.cfg", BG_FindNameForBuildable( i ) ), bao ); + BG_ParseBuildableFile( va( "configs/buildables/%s.cfg", + BG_Buildable( i )->name ), bc ); } } //////////////////////////////////////////////////////////////////////////////// -classAttributes_t bg_classList[ ] = +static const 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; + PCL_NONE, //int number; + "spectator", //char *name; + "", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 0, //int health; 0.0f, //float fallDamage; - 0, //int regenRate; + 0.0f, //float regenRate; 0, //int abilities; - WP_NONE, //weapon_t startWeapon + WP_NONE, //weapon_t startWeapon; 0.0f, //float buildDist; 90, //int fov; 0.000f, //float bob; 1.0f, //float bobCycle; + 0.0f, //float landBob; 0, //int steptime; 600, //float speed; 10.0f, //float acceleration; @@ -1567,31 +879,21 @@ classAttributes_t bg_classList[ ] = 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; + PCL_ALIEN_BUILDER0, //int number; + "builder", //char *name; + "Responsible for building and maintaining all the alien structures. " + "Has a weak melee slash attack.", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + ABUILDER_REGEN, //float regenRate; + SCA_TAKESFALLDAMAGE|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; + WP_ABUILD, //weapon_t startWeapon; 95.0f, //float buildDist; - 80, //int fov; + 110, //int fov; 0.001f, //float bob; 2.0f, //float bobCycle; + 4.5f, //float landBob; 150, //int steptime; ABUILDER_SPEED, //float speed; 10.0f, //float acceleration; @@ -1600,36 +902,27 @@ classAttributes_t bg_classList[ ] = 100.0f, //float stopSpeed; 195.0f, //float jumpMagnitude; 1.0f, //float knockbackScale; - { PCL_ALIEN_BUILDER0_UPG, PCL_ALIEN_LEVEL0, PCL_NONE }, //int children[ 3 ]; + { 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; + PCL_ALIEN_BUILDER0_UPG, //int number; + "builderupg", //char *name; + "Similar to the base Granger, except that in addition to " + "being able to build structures it has a spit attack " + "that slows victims and the ability to crawl on walls.", + ( 1 << S2 )|( 1 << S3 ), //int stages; 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 + 0.2f, //float fallDamage; + ABUILDER_UPG_REGEN, //float regenRate; + SCA_TAKESFALLDAMAGE|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; + 4.5f, //float landBob; 100, //int steptime; ABUILDER_UPG_SPEED, //float speed; 10.0f, //float acceleration; @@ -1643,32 +936,21 @@ classAttributes_t bg_classList[ ] = 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; + PCL_ALIEN_LEVEL0, //int number; + "level0", //char *name; + "Has a lethal reflexive bite and the ability to crawl on " + "walls and ceilings.", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL0_REGEN, //float regenRate; + SCA_WALLCLIMBER|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; + 0.0f, //float landBob; 25, //int steptime; LEVEL0_SPEED, //float speed; 10.0f, //float acceleration; @@ -1682,188 +964,138 @@ classAttributes_t bg_classList[ ] = 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; + PCL_ALIEN_LEVEL1, //int number; + "level1", //char *name; + "A support class able to crawl on walls and ceilings. Its melee " + "attack is most effective when combined with the ability to grab " + "and hold its victims in place. Provides a weak healing aura " + "that accelerates the healing rate of nearby aliens.", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL1_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 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; + 310.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_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; + PCL_ALIEN_LEVEL1_UPG, //int number; + "level1upg", //char *name; + "In addition to the basic Basilisk abilities, the Advanced " + "Basilisk sprays a poisonous gas which disorients any " + "nearby humans. Has a strong healing aura that " + "that accelerates the healing rate of nearby aliens.", + ( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL1_UPG_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 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; + 310.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; + PCL_ALIEN_LEVEL2, //int number; + "level2", //char *name; + "Has a melee attack and the ability to jump off walls. This " + "allows the Marauder to gather great speed in enclosed areas.", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL2_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 80, //int steptime; LEVEL2_SPEED, //float speed; 10.0f, //float acceleration; - 2.0f, //float airAcceleration; + 3.0f, //float airAcceleration; 6.0f, //float friction; 100.0f, //float stopSpeed; - 400.0f, //float jumpMagnitude; + 380.0f, //float jumpMagnitude; 0.8f, //float knockbackScale; - { PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL2_UPG, PCL_NONE }, //int children[ 3 ]; + { 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; + PCL_ALIEN_LEVEL2_UPG, //int number; + "level2upg", //char *name; + "The Advanced Marauder has all the abilities of the basic Marauder " + "with the addition of an area effect electric shock attack.", + ( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL2_UPG_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 80, //int steptime; LEVEL2_UPG_SPEED, //float speed; 10.0f, //float acceleration; - 2.0f, //float airAcceleration; + 3.0f, //float airAcceleration; 6.0f, //float friction; 100.0f, //float stopSpeed; - 400.0f, //float jumpMagnitude; + 380.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; + PCL_ALIEN_LEVEL3, //int number; + "level3", //char *name; + "Possesses a melee attack and the pounce ability, which may " + "be used as both an attack and a means to reach remote " + "locations inaccessible from the ground.", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL3_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 90, //int steptime; LEVEL3_SPEED, //float speed; 10.0f, //float acceleration; @@ -1872,37 +1104,27 @@ classAttributes_t bg_classList[ ] = 200.0f, //float stopSpeed; 270.0f, //float jumpMagnitude; 0.5f, //float knockbackScale; - { PCL_ALIEN_LEVEL4, PCL_ALIEN_LEVEL3_UPG, PCL_NONE }, //int children[ 3 ]; + { 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; + PCL_ALIEN_LEVEL3_UPG, //int number; + "level3upg", //char *name; + "In addition to the basic Dragoon abilities, the Advanced " + "Dragoon has 3 barbs which may be used to attack humans " + "from a distance.", + ( 1 << S2 )|( 1 << S3 ), //int stages; 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 + LEVEL3_UPG_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 90, //int steptime; LEVEL3_UPG_SPEED, //float speed; 10.0f, //float acceleration; @@ -1916,32 +1138,23 @@ classAttributes_t bg_classList[ ] = 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; + PCL_ALIEN_LEVEL4, //int number; + "level4", //char *name; + "A large alien with a strong melee attack, this class can " + "also charge at enemy humans and structures, inflicting " + "great damage. Any humans or their structures caught under " + "a falling Tyrant will be crushed by its weight.", + ( 1 << S3 ), //int stages; 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 + LEVEL4_REGEN, //float regenRate; + 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; + 0.0f, //float landBob; 100, //int steptime; LEVEL4_SPEED, //float speed; 10.0f, //float acceleration; @@ -1955,32 +1168,20 @@ classAttributes_t bg_classList[ ] = 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; + PCL_HUMAN, //int number; + "human_base", //char *name; + "", + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; 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 + 0.0f, //float 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; + 8.0f, //float landBob; 100, //int steptime; 1.0f, //float speed; 10.0f, //float acceleration; @@ -1991,684 +1192,120 @@ classAttributes_t bg_classList[ ] = 1.0f, //float knockbackScale; { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ]; 0, //int cost; - 0 //int value; + ALIEN_CREDITS_PER_KILL //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; + PCL_HUMAN_BSUIT, //int number; + "human_bsuit", //char *name; + "", + ( 1 << S3 ), //int stages; 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 + 0.0f, //float 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; + 5.0f, //float landBob; 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; + 220.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; + ALIEN_CREDITS_PER_KILL //int value; } +}; - 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; +size_t bg_numClasses = ARRAY_LEN( bg_classList ); - 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; -} +static const classAttributes_t nullClass = { 0 }; /* ============== -BG_FindModelScaleForClass +BG_ClassByName ============== */ -float BG_FindModelScaleForClass( int pclass ) +const classAttributes_t *BG_ClassByName( const char *name ) { int i; - if( bg_classOverrideList[ pclass ].modelScale != 0.0f ) - return bg_classOverrideList[ pclass ].modelScale; - - for( i = 0; i < bg_numPclasses; i++ ) + for( i = 0; i < bg_numClasses; i++ ) { - if( bg_classList[ i ].classNum == pclass ) - { - return bg_classList[ i ].modelScale; - } + if( !Q_stricmp( bg_classList[ i ].name, name ) ) + return &bg_classList[ i ]; } - Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelScaleForClass( %d )\n", pclass ); - return 1.0f; + return &nullClass; } /* ============== -BG_FindSkinNameForClass +BG_Class ============== */ -char *BG_FindSkinNameForClass( int pclass ) +const classAttributes_t *BG_Class( class_t class ) { - 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; + return ( class >= PCL_NONE && class < PCL_NUM_CLASSES ) ? + &bg_classList[ class ] : &nullClass; } /* ============== -BG_FindShadowScaleForClass +BG_ClassAllowedInStage ============== */ -float BG_FindShadowScaleForClass( int pclass ) +qboolean BG_ClassAllowedInStage( class_t class, + stage_t stage ) { - int i; + int stages = BG_Class( class )->stages; - 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; + return stages & ( 1 << stage ); } -/* -============== -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; -} +static classConfig_t bg_classConfigList[ PCL_NUM_CLASSES ]; /* ============== -BG_FindStagesForClass +BG_ClassConfig ============== */ -qboolean BG_FindStagesForClass( int pclass, stage_t stage ) +classConfig_t *BG_ClassConfig( class_t class ) { - 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; + return &bg_classConfigList[ class ]; } /* ============== -BG_FindBBoxForClass +BG_ClassBoundingBox ============== */ -void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs ) +void BG_ClassBoundingBox( class_t class, + 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; - } - } + classConfig_t *classConfig = BG_ClassConfig( class ); if( mins != NULL ) - VectorCopy( bg_classList[ 0 ].mins, mins ); + VectorCopy( classConfig->mins, mins ); if( maxs != NULL ) - VectorCopy( bg_classList[ 0 ].maxs, maxs ); + VectorCopy( classConfig->maxs, maxs ); if( cmaxs != NULL ) - VectorCopy( bg_classList[ 0 ].crouchMaxs, cmaxs ); + VectorCopy( classConfig->crouchMaxs, cmaxs ); if( dmins != NULL ) - VectorCopy( bg_classList[ 0 ].deadMins, dmins ); + VectorCopy( classConfig->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; + VectorCopy( classConfig->deadMaxs, dmaxs ); } /* @@ -2676,61 +1313,11 @@ int BG_FindSteptimeForClass( int pclass ) 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 ) +qboolean BG_ClassHasAbility( class_t class, int ability ) { - int i; + int abilities = BG_Class( class )->abilities; - 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; + return abilities & ability; } /* @@ -2738,95 +1325,78 @@ float BG_FindBuildDistForClass( int pclass ) BG_ClassCanEvolveFromTo ============== */ -int BG_ClassCanEvolveFromTo( int fclass, int tclass, int credits, int num ) +int BG_ClassCanEvolveFromTo( class_t fclass, + class_t tclass, + int credits, int stage, + int cost ) { - int i, j, cost; - - cost = BG_FindCostOfClass( tclass ); + int i, j, best, value; - //base case - if( credits < cost ) + if( credits < cost || fclass == PCL_NONE || tclass == PCL_NONE || + fclass == tclass ) return -1; - if( fclass == PCL_NONE || tclass == PCL_NONE ) - return -1; - - for( i = 0; i < bg_numPclasses; i++ ) + for( i = 0; i < bg_numClasses; i++ ) { - if( bg_classList[ i ].classNum == fclass ) - { - for( j = 0; j < 3; j++ ) - if( bg_classList[ i ].children[ j ] == tclass ) - return num + cost; + if( bg_classList[ i ].number != fclass ) + continue; - for( j = 0; j < 3; j++ ) - { - int sub; + best = credits + 1; + for( j = 0; j < 3; j++ ) + { + int thruClass, evolveCost; + + thruClass = bg_classList[ i ].children[ j ]; + if( thruClass == PCL_NONE || !BG_ClassAllowedInStage( thruClass, stage ) || + !BG_ClassIsAllowed( thruClass ) ) + continue; - 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; - } + evolveCost = BG_Class( thruClass )->cost * ALIEN_CREDITS_PER_KILL; + if( thruClass == tclass ) + value = cost + evolveCost; + else + value = BG_ClassCanEvolveFromTo( thruClass, tclass, credits, stage, + cost + evolveCost ); - return -1; //may as well return by this point + if( value >= 0 && value < best ) + best = value; } + + return best <= credits ? best : -1; } + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_ClassCanEvolveFromTo\n" ); return -1; } /* ============== -BG_FindValueOfClass +BG_AlienCanEvolve ============== */ -int BG_FindValueOfClass( int pclass ) +qboolean BG_AlienCanEvolve( class_t class, int credits, int stage ) { - int i; + int i, j, tclass; - for( i = 0; i < bg_numPclasses; i++ ) + for( i = 0; i < bg_numClasses; 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; + if( bg_classList[ i ].number != class ) + continue; - for( i = 0; i < bg_numPclasses; i++ ) - { - if( bg_classList[ i ].classNum == pclass ) + for( j = 0; j < 3; j++ ) { - return bg_classList[ i ].cost; + tclass = bg_classList[ i ].children[ j ]; + if( tclass != PCL_NONE && BG_ClassAllowedInStage( tclass, stage ) && + BG_ClassIsAllowed( tclass ) && + credits >= BG_Class( tclass )->cost * ALIEN_CREDITS_PER_KILL ) + return qtrue; } - } - Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindCostOfClass\n" ); - return 0; -} + return qfalse; + } -/* -============== -BG_FindOverrideForClass -============== -*/ -static classAttributeOverrides_t *BG_FindOverrideForClass( int pclass ) -{ - return &bg_classOverrideList[ pclass ]; + Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_AlienCanEvolve\n" ); + return qfalse; } /* @@ -2836,7 +1406,7 @@ BG_ParseClassFile Parses a configuration file describing a class ====================== */ -static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides_t *cao ) +static qboolean BG_ParseClassFile( const char *filename, classConfig_t *cc ) { char *text_p; int i; @@ -2845,7 +1415,25 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides char text[ 20000 ]; fileHandle_t f; float scale = 0.0f; - + int defined = 0; + enum + { + MODEL = 1 << 0, + SKIN = 1 << 1, + HUD = 1 << 2, + MODELSCALE = 1 << 3, + SHADOWSCALE = 1 << 4, + MINS = 1 << 5, + MAXS = 1 << 6, + DEADMINS = 1 << 7, + DEADMAXS = 1 << 8, + CROUCHMAXS = 1 << 9, + VIEWHEIGHT = 1 << 10, + CVIEWHEIGHT = 1 << 11, + ZOFFSET = 1 << 12, + NAME = 1 << 13, + SHOULDEROFFSETS = 1 << 14 + }; // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); @@ -2884,8 +1472,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - Q_strncpyz( cao->modelName, token, sizeof( cao->modelName ) ); + Q_strncpyz( cc->modelName, token, sizeof( cc->modelName ) ); + defined |= MODEL; continue; } else if( !Q_stricmp( token, "skin" ) ) @@ -2894,8 +1483,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - Q_strncpyz( cao->skinName, token, sizeof( cao->skinName ) ); + Q_strncpyz( cc->skinName, token, sizeof( cc->skinName ) ); + defined |= SKIN; continue; } else if( !Q_stricmp( token, "hud" ) ) @@ -2904,8 +1494,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - Q_strncpyz( cao->hudName, token, sizeof( cao->hudName ) ); + Q_strncpyz( cc->hudName, token, sizeof( cc->hudName ) ); + defined |= HUD; continue; } else if( !Q_stricmp( token, "modelScale" ) ) @@ -2919,8 +1510,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( scale < 0.0f ) scale = 0.0f; - cao->modelScale = scale; + cc->modelScale = scale; + defined |= MODELSCALE; continue; } else if( !Q_stricmp( token, "shadowScale" ) ) @@ -2934,8 +1526,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( scale < 0.0f ) scale = 0.0f; - cao->shadowScale = scale; + cc->shadowScale = scale; + defined |= SHADOWSCALE; continue; } else if( !Q_stricmp( token, "mins" ) ) @@ -2946,9 +1539,10 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - cao->mins[ i ] = atof( token ); + cc->mins[ i ] = atof( token ); } + defined |= MINS; continue; } else if( !Q_stricmp( token, "maxs" ) ) @@ -2959,9 +1553,10 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - cao->maxs[ i ] = atof( token ); + cc->maxs[ i ] = atof( token ); } + defined |= MAXS; continue; } else if( !Q_stricmp( token, "deadMins" ) ) @@ -2972,9 +1567,10 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - cao->deadMins[ i ] = atof( token ); + cc->deadMins[ i ] = atof( token ); } + defined |= DEADMINS; continue; } else if( !Q_stricmp( token, "deadMaxs" ) ) @@ -2985,9 +1581,10 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - cao->deadMaxs[ i ] = atof( token ); + cc->deadMaxs[ i ] = atof( token ); } + defined |= DEADMAXS; continue; } else if( !Q_stricmp( token, "crouchMaxs" ) ) @@ -2998,21 +1595,24 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - cao->crouchMaxs[ i ] = atof( token ); + cc->crouchMaxs[ i ] = atof( token ); } + defined |= CROUCHMAXS; continue; } else if( !Q_stricmp( token, "viewheight" ) ) { token = COM_Parse( &text_p ); - cao->viewheight = atoi( token ); + cc->viewheight = atoi( token ); + defined |= VIEWHEIGHT; continue; } else if( !Q_stricmp( token, "crouchViewheight" ) ) { token = COM_Parse( &text_p ); - cao->crouchViewheight = atoi( token ); + cc->crouchViewheight = atoi( token ); + defined |= CVIEWHEIGHT; continue; } else if( !Q_stricmp( token, "zOffset" ) ) @@ -3025,8 +1625,9 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides offset = atof( token ); - cao->zOffset = offset; + cc->zOffset = offset; + defined |= ZOFFSET; continue; } else if( !Q_stricmp( token, "name" ) ) @@ -3035,275 +1636,341 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides if( !token ) break; - Q_strncpyz( cao->humanName, token, sizeof( cao->humanName ) ); + Q_strncpyz( cc->humanName, token, sizeof( cc->humanName ) ); + defined |= NAME; continue; } + else if( !Q_stricmp( token, "shoulderOffsets" ) ) + { + for( i = 0; i <= 2; i++ ) + { + token = COM_Parse( &text_p ); + if( !token ) + break; + cc->shoulderOffsets[ i ] = atof( token ); + } + + defined |= SHOULDEROFFSETS; + continue; + } Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token ); return qfalse; } + if( !( defined & MODEL ) ) token = "model"; + else if( !( defined & SKIN ) ) token = "skin"; + else if( !( defined & HUD ) ) token = "hud"; + else if( !( defined & MODELSCALE ) ) token = "modelScale"; + else if( !( defined & SHADOWSCALE ) ) token = "shadowScale"; + else if( !( defined & MINS ) ) token = "mins"; + else if( !( defined & MAXS ) ) token = "maxs"; + else if( !( defined & DEADMINS ) ) token = "deadMins"; + else if( !( defined & DEADMAXS ) ) token = "deadMaxs"; + else if( !( defined & CROUCHMAXS ) ) token = "crouchMaxs"; + else if( !( defined & VIEWHEIGHT ) ) token = "viewheight"; + else if( !( defined & CVIEWHEIGHT ) ) token = "crouchViewheight"; + else if( !( defined & ZOFFSET ) ) token = "zOffset"; + else if( !( defined & NAME ) ) token = "name"; + else if( !( defined & SHOULDEROFFSETS ) ) token = "shoulderOffsets"; + else token = ""; + + if( strlen( token ) > 0 ) + { + Com_Printf( S_COLOR_RED "ERROR: %s not defined in %s\n", + token, filename ); + return qfalse; + } + return qtrue; } /* =============== -BG_InitClassOverrides - -Set any overrides specfied by file +BG_InitClassConfigs =============== */ -void BG_InitClassOverrides( void ) +void BG_InitClassConfigs( void ) { - int i; - classAttributeOverrides_t *cao; + int i; + classConfig_t *cc; - for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) + for( i = PCL_NONE; i < PCL_NUM_CLASSES; i++ ) { - cao = BG_FindOverrideForClass( i ); + cc = BG_ClassConfig( i ); - BG_ParseClassFile( va( "overrides/classes/%s.cfg", BG_FindNameForClassNum( i ) ), cao ); + BG_ParseClassFile( va( "configs/classes/%s.cfg", + BG_Class( i )->name ), cc ); } } //////////////////////////////////////////////////////////////////////////////// -weaponAttributes_t bg_weapons[ ] = +static const weaponAttributes_t bg_weapons[ ] = { { - WP_BLASTER, //int weaponNum; + WP_ALEVEL0, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages - 0, //int slots; - "blaster", //char *weaponName; - "Blaster", //char *weaponHumanName; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; + SLOT_WEAPON, //int slots; + "level0", //char *name; + "Bite", //char *humanName; + "", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - BLASTER_REPEAT, //int repeatRate1; + LEVEL0_BITE_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - BLASTER_K_SCALE, //float knockbackScale; + LEVEL0_BITE_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; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_t team; }, { - WP_MACHINEGUN, //int weaponNum; - RIFLE_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL1, //int number; + 0, //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; + "level1", //char *name; + "Claws", //char *humanName; + "", + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - RIFLE_REPEAT, //int repeatRate1; + LEVEL1_CLAW_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - RIFLE_RELOAD, //int reloadTime; - RIFLE_K_SCALE, //float knockbackScale; + 0, //int reloadTime; + LEVEL1_CLAW_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; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_t team; }, { - WP_SHOTGUN, //int weaponNum; - SHOTGUN_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL1_UPG, //int number; + 0, //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; + "level1upg", //char *name; + "Claws Upgrade", //char *humanName; + "", + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - SHOTGUN_REPEAT, //int repeatRate1; - 0, //int repeatRate2; + LEVEL1_CLAW_U_REPEAT, //int repeatRate1; + LEVEL1_PCLOUD_REPEAT, //int repeatRate2; 0, //int repeatRate3; - SHOTGUN_RELOAD, //int reloadTime; - SHOTGUN_K_SCALE, //float knockbackScale; - qfalse, //qboolean hasAltMode; + 0, //int reloadTime; + LEVEL1_CLAW_U_K_SCALE, //float knockbackScale; + qtrue, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qtrue, //qboolean purchasable; + qfalse, //qboolean purchasable; qtrue, //qboolean longRanged; - 0, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + TEAM_ALIENS //team_t team; }, { - WP_FLAMER, //int weaponNum; - FLAMER_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL2, //int number; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "flamer", //char *weaponName; - "Flame Thrower", //char *weaponHumanName; - FLAMER_GAS, //int maxAmmo; + "level2", //char *name; + "Bite", //char *humanName; + "", + 0, //int maxAmmo; 0, //int maxClips; - qfalse, //int infiniteAmmo; + qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - FLAMER_REPEAT, //int repeatRate1; + LEVEL2_CLAW_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - FLAMER_K_SCALE, //float knockbackScale; + LEVEL2_CLAW_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; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_t team; }, { - WP_CHAINGUN, //int weaponNum; - CHAINGUN_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL2_UPG, //int number; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "chaingun", //char *weaponName; - "Chaingun", //char *weaponHumanName; - CHAINGUN_BULLETS, //int maxAmmo; + "level2upg", //char *name; + "Zap", //char *humanName; + "", + 0, //int maxAmmo; 0, //int maxClips; - qfalse, //int infiniteAmmo; + qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - CHAINGUN_REPEAT, //int repeatRate1; - 0, //int repeatRate2; + LEVEL2_CLAW_U_REPEAT, //int repeatRate1; + LEVEL2_AREAZAP_REPEAT, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - CHAINGUN_K_SCALE, //float knockbackScale; - qfalse, //qboolean hasAltMode; + LEVEL2_CLAW_U_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; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_t team; }, { - WP_MASS_DRIVER, //int weaponNum; - MDRIVER_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL3, //int number; + 0, //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; + "level3", //char *name; + "Pounce", //char *humanName; + "", + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL3_CLAW_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - MDRIVER_RELOAD, //int reloadTime; - MDRIVER_K_SCALE, //float knockbackScale; + 0, //int reloadTime; + LEVEL3_CLAW_K_SCALE, //float knockbackScale; qfalse, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; - qtrue, //qboolean canZoom; - 20.0f, //float zoomFov; - qtrue, //qboolean purchasable; + qfalse, //qboolean canZoom; + 90.0f, //float zoomFov; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_t team; + }, + { + WP_ALEVEL3_UPG, //int number; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; + SLOT_WEAPON, //int slots; + "level3upg", //char *name; + "Pounce (upgrade)", //char *humanName; + "", + 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_HUMANS //WUTeam_t team; + TEAM_ALIENS //team_t team; }, { - WP_PULSE_RIFLE, //int weaponNum; - PRIFLE_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + WP_ALEVEL4, //int number; + 0, //int price; + ( 1 << S1 )|( 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; + "level4", //char *name; + "Charge", //char *humanName; + "", + 0, //int maxAmmo; + 0, //int maxClips; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + LEVEL4_CLAW_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - PRIFLE_RELOAD, //int reloadTime; - PRIFLE_K_SCALE, //float knockbackScale; + 0, //int reloadTime; + LEVEL4_CLAW_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; + qfalse, //qboolean purchasable; + qfalse, //qboolean longRanged; + TEAM_ALIENS //team_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; + WP_BLASTER, //int number; + 0, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; + 0, //int slots; + "blaster", //char *name; + "Blaster", //char *humanName; + "", + 0, //int maxAmmo; 0, //int maxClips; - qfalse, //int infiniteAmmo; - qtrue, //int usesEnergy; - LCANNON_REPEAT, //int repeatRate1; - LCANNON_CHARGEREPEAT, //int repeatRate2; + qtrue, //int infiniteAmmo; + qfalse, //int usesEnergy; + BLASTER_REPEAT, //int repeatRate1; + 0, //int repeatRate2; 0, //int repeatRate3; - LCANNON_RELOAD, //int reloadTime; - LCANNON_K_SCALE, //float knockbackScale; - qtrue, //qboolean hasAltMode; + 0, //int reloadTime; + BLASTER_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qtrue, //qboolean purchasable; + qfalse, //qboolean purchasable; qtrue, //qboolean longRanged; - 0, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + TEAM_HUMANS //team_t team; }, { - WP_LAS_GUN, //int weaponNum; - LASGUN_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_MACHINEGUN, //int number; + RIFLE_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; + "rifle", //char *name; + "Rifle", //char *humanName; + "Basic weapon. Cased projectile weapon, with a slow clip based " + "reload system.", + RIFLE_CLIPSIZE, //int maxAmmo; + RIFLE_MAXCLIPS, //int maxClips; qfalse, //int infiniteAmmo; - qtrue, //int usesEnergy; - LASGUN_REPEAT, //int repeatRate1; + qfalse, //int usesEnergy; + RIFLE_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - LASGUN_RELOAD, //int reloadTime; - LASGUN_K_SCALE, //float knockbackScale; + 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; + TEAM_HUMANS //team_t team; }, { - WP_PAIN_SAW, //int weaponNum; + WP_PAIN_SAW, //int number; PAINSAW_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "psaw", //char *weaponName; - "Pain Saw", //char *weaponHumanName; + "psaw", //char *name; + "Pain Saw", //char *humanName; + "Similar to a chainsaw, but instead of a chain it has an " + "electric arc capable of dealing a great deal of damage at " + "close range.", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; @@ -3319,1173 +1986,609 @@ weaponAttributes_t bg_weapons[ ] = 90.0f, //float zoomFov; qtrue, //qboolean purchasable; qfalse, //qboolean longRanged; - 0, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + TEAM_HUMANS //team_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; + WP_SHOTGUN, //int number; + SHOTGUN_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; + SLOT_WEAPON, //int slots; + "shotgun", //char *name; + "Shotgun", //char *humanName; + "Close range weapon that is useful against larger foes. " + "It has a slow repeat rate, but can be devastatingly " + "effective.", + SHOTGUN_SHELLS, //int maxAmmo; + SHOTGUN_MAXCLIPS, //int maxClips; qfalse, //int infiniteAmmo; qfalse, //int usesEnergy; - GRENADE_REPEAT, //int repeatRate1; + SHOTGUN_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - 0, //int reloadTime; - GRENADE_K_SCALE, //float knockbackScale; + SHOTGUN_RELOAD, //int reloadTime; + SHOTGUN_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; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_HBUILD, //int weaponNum; - HBUILD_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_LAS_GUN, //int number; + LASGUN_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; + "lgun", //char *name; + "Las Gun", //char *humanName; + "Slightly more powerful than the basic rifle, rapidly fires " + "small packets of energy.", + LASGUN_AMMO, //int maxAmmo; 0, //int maxClips; - qtrue, //int infiniteAmmo; - qfalse, //int usesEnergy; - HBUILD_REPEAT, //int repeatRate1; - HBUILD_REPEAT, //int repeatRate2; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + LASGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; 0, //int repeatRate3; - 0, //int reloadTime; - 0.0f, //float knockbackScale; - qtrue, //qboolean hasAltMode; + 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; - qfalse, //qboolean longRanged; - HBUILD_DELAY, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_HBUILD2, //int weaponNum; - HBUILD2_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + WP_MASS_DRIVER, //int number; + MDRIVER_PRICE, //int price; + ( 1 << S1 )|( 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; + "mdriver", //char *name; + "Mass Driver", //char *humanName; + "A portable particle accelerator which causes minor nuclear " + "reactions at the point of impact. It has a very large " + "payload, but fires slowly.", + MDRIVER_CLIPSIZE, //int maxAmmo; + MDRIVER_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + MDRIVER_REPEAT, //int repeatRate1; + 0, //int repeatRate2; 0, //int repeatRate3; - 0, //int reloadTime; - 0.0f, //float knockbackScale; - qtrue, //qboolean hasAltMode; + MDRIVER_RELOAD, //int reloadTime; + MDRIVER_K_SCALE, //float knockbackScale; + qfalse, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; - qfalse, //qboolean canZoom; - 90.0f, //float zoomFov; + qtrue, //qboolean canZoom; + 20.0f, //float zoomFov; qtrue, //qboolean purchasable; - qfalse, //qboolean longRanged; - HBUILD2_DELAY, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_ABUILD, //int weaponNum; - 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_CHAINGUN, //int number; + CHAINGUN_PRICE, //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; + "chaingun", //char *name; + "Chaingun", //char *humanName; + "Belt drive, cased projectile weapon. It has a high repeat " + "rate but a wide firing angle and is therefore relatively " + "inaccurate.", + CHAINGUN_BULLETS, //int maxAmmo; 0, //int maxClips; - qtrue, //int infiniteAmmo; + qfalse, //int infiniteAmmo; qfalse, //int usesEnergy; - ABUILDER_BUILD_REPEAT,//int repeatRate1; - ABUILDER_BUILD_REPEAT,//int repeatRate2; + CHAINGUN_REPEAT, //int repeatRate1; + 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - 0.0f, //float knockbackScale; - qtrue, //qboolean hasAltMode; + CHAINGUN_K_SCALE, //float knockbackScale; + qfalse, //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; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_ALEVEL0, //int weaponNum; - 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_FLAMER, //int number; + FLAMER_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level0", //char *weaponName; - "Bite", //char *weaponHumanName; - 0, //int maxAmmo; + "flamer", //char *name; + "Flame Thrower", //char *humanName; + "Sprays fire at its target. It is powered by compressed " + "gas. The relatively low rate of fire means this weapon is most " + "effective against static targets.", + FLAMER_GAS, //int maxAmmo; 0, //int maxClips; - qtrue, //int infiniteAmmo; + qfalse, //int infiniteAmmo; qfalse, //int usesEnergy; - LEVEL0_BITE_REPEAT, //int repeatRate1; + FLAMER_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - LEVEL0_BITE_K_SCALE, //float knockbackScale; + FLAMER_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; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_ALEVEL1, //int weaponNum; - 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_PULSE_RIFLE, //int number; + PRIFLE_PRICE, //int price; + ( 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; + "prifle", //char *name; + "Pulse Rifle", //char *humanName; + "An energy weapon that fires rapid pulses of concentrated energy.", + PRIFLE_CLIPS, //int maxAmmo; + PRIFLE_MAXCLIPS, //int maxClips; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + PRIFLE_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; - 0, //int reloadTime; - LEVEL1_CLAW_K_SCALE, //float knockbackScale; + PRIFLE_RELOAD, //int reloadTime; + PRIFLE_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; + qtrue, //qboolean purchasable; + qtrue, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_ALEVEL1_UPG, //int weaponNum; - 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_LUCIFER_CANNON, //int number; + LCANNON_PRICE, //int price; + ( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level1upg", //char *weaponName; - "Claws Upgrade", //char *weaponHumanName; - 0, //int maxAmmo; + "lcannon", //char *name; + "Lucifer Cannon", //char *humanName; + "Blaster technology scaled up to deliver devastating power. " + "Primary fire must be charged before firing. It has a quick " + "secondary attack that does not require charging.", + LCANNON_AMMO, //int maxAmmo; 0, //int maxClips; - qtrue, //int infiniteAmmo; - qfalse, //int usesEnergy; - LEVEL1_CLAW_U_REPEAT, //int repeatRate1; - LEVEL1_PCLOUD_REPEAT, //int repeatRate2; + qfalse, //int infiniteAmmo; + qtrue, //int usesEnergy; + LCANNON_REPEAT, //int repeatRate1; + LCANNON_SECONDARY_REPEAT, //int repeatRate2; 0, //int repeatRate3; - 0, //int reloadTime; - LEVEL1_CLAW_U_K_SCALE,//float knockbackScale; + LCANNON_RELOAD, //int reloadTime; + LCANNON_K_SCALE, //float knockbackScale; qtrue, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qfalse, //qboolean purchasable; + qtrue, //qboolean purchasable; qtrue, //qboolean longRanged; - 0, //int buildDelay; - WUT_ALIENS //WUTeam_t team; + TEAM_HUMANS //team_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; + WP_GRENADE, //int number; + GRENADE_PRICE, //int price; + ( 1 << S2 )|( 1 << S3 ), //int stages; + SLOT_NONE, //int slots; + "grenade", //char *name; + "Grenade", //char *humanName; + "", + 1, //int maxAmmo; 0, //int maxClips; - qtrue, //int infiniteAmmo; + qfalse, //int infiniteAmmo; qfalse, //int usesEnergy; - LEVEL2_CLAW_REPEAT, //int repeatRate1; + GRENADE_REPEAT, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - LEVEL2_CLAW_K_SCALE, //float knockbackScale; + 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_ALIENS //WUTeam_t team; + TEAM_HUMANS //team_t team; }, { - WP_ALEVEL2_UPG, //int weaponNum; + WP_LOCKBLOB_LAUNCHER, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level2upg", //char *weaponName; - "Zap", //char *weaponHumanName; + "lockblob", //char *name; + "Lock Blob", //char *humanName; + "", 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; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; 0, //int reloadTime; - LEVEL2_CLAW_U_K_SCALE,//float knockbackScale; - qtrue, //qboolean hasAltMode; + 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; + TEAM_ALIENS //team_t team; }, { - WP_ALEVEL3, //int weaponNum; + WP_HIVE, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level3", //char *weaponName; - "Pounce", //char *weaponHumanName; + "hive", //char *name; + "Hive", //char *humanName; + "", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - LEVEL3_CLAW_REPEAT, //int repeatRate1; - 0, //int repeatRate2; - 0, //int repeatRate3; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; 0, //int reloadTime; - LEVEL3_CLAW_K_SCALE, //float knockbackScale; + 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; + TEAM_ALIENS //team_t team; }, { - WP_ALEVEL3_UPG, //int weaponNum; + WP_TESLAGEN, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level3upg", //char *weaponName; - "Pounce (upgrade)", //char *weaponHumanName; - 3, //int maxAmmo; + "teslagen", //char *name; + "Tesla Generator", //char *humanName; + "", + 0, //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; + qtrue, //int usesEnergy; + 500, //int repeatRate1; + 500, //int repeatRate2; + 500, //int repeatRate3; 0, //int reloadTime; - LEVEL3_CLAW_U_K_SCALE,//float knockbackScale; + TESLAGEN_K_SCALE, //float knockbackScale; qfalse, //qboolean hasAltMode; - qtrue, //qboolean hasThirdMode; + qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; qfalse, //qboolean purchasable; - qtrue, //qboolean longRanged; - 0, //int buildDelay; - WUT_ALIENS //WUTeam_t team; + qfalse, //qboolean longRanged; + TEAM_HUMANS //team_t team; }, { - WP_ALEVEL4, //int weaponNum; + WP_MGTURRET, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "level4", //char *weaponName; - "Charge", //char *weaponHumanName; + "mgturret", //char *name; + "Machinegun Turret", //char *humanName; + "", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - LEVEL4_CLAW_REPEAT, //int repeatRate1; + 0, //int repeatRate1; 0, //int repeatRate2; 0, //int repeatRate3; 0, //int reloadTime; - LEVEL4_CLAW_K_SCALE, //float knockbackScale; + 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_ALIENS //WUTeam_t team; + TEAM_HUMANS //team_t team; }, { - WP_LOCKBLOB_LAUNCHER, //int weaponNum; + WP_ABUILD, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "lockblob", //char *weaponName; - "Lock Blob", //char *weaponHumanName; + "abuild", //char *name; + "Alien build weapon", //char *humanName; + "", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - 500, //int repeatRate1; - 500, //int repeatRate2; - 500, //int repeatRate3; + ABUILDER_BUILD_REPEAT, //int repeatRate1; + ABUILDER_CLAW_REPEAT, //int repeatRate2; + 0, //int repeatRate3; 0, //int reloadTime; - LOCKBLOB_K_SCALE, //float knockbackScale; - qfalse, //qboolean hasAltMode; + ABUILDER_CLAW_K_SCALE, //float knockbackScale; + qtrue, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qfalse, //qboolean purchasable; + qtrue, //qboolean purchasable; qfalse, //qboolean longRanged; - 0, //int buildDelay; - WUT_ALIENS //WUTeam_t team; + TEAM_ALIENS //team_t team; }, { - WP_HIVE, //int weaponNum; + WP_ABUILD2, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "hive", //char *weaponName; - "Hive", //char *weaponHumanName; + "abuildupg", //char *name; + "Alien build weapon2", //char *humanName; + "", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - 500, //int repeatRate1; - 500, //int repeatRate2; - 500, //int repeatRate3; + ABUILDER_BUILD_REPEAT, //int repeatRate1; + ABUILDER_CLAW_REPEAT, //int repeatRate2; + ABUILDER_BLOB_REPEAT, //int repeatRate3; 0, //int reloadTime; - HIVE_K_SCALE, //float knockbackScale; - qfalse, //qboolean hasAltMode; - qfalse, //qboolean hasThirdMode; + ABUILDER_CLAW_K_SCALE, //float knockbackScale; + qtrue, //qboolean hasAltMode; + qtrue, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qfalse, //qboolean purchasable; + qtrue, //qboolean purchasable; qfalse, //qboolean longRanged; - 0, //int buildDelay; - WUT_ALIENS //WUTeam_t team; + TEAM_ALIENS //team_t team; }, { - WP_MGTURRET, //int weaponNum; - 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + WP_HBUILD, //int number; + HBUILD_PRICE, //int price; + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_WEAPON, //int slots; - "mgturret", //char *weaponName; - "Machinegun Turret", //char *weaponHumanName; + "ckit", //char *name; + "Construction Kit", //char *humanName; + "Used for building structures. This includes " + "spawns, power and basic defense. More structures become " + "available with new stages.", 0, //int maxAmmo; 0, //int maxClips; qtrue, //int infiniteAmmo; qfalse, //int usesEnergy; - 0, //int repeatRate1; + HBUILD_REPEAT, //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; + 0.0f, //float knockbackScale; + qtrue, //qboolean hasAltMode; qfalse, //qboolean hasThirdMode; qfalse, //qboolean canZoom; 90.0f, //float zoomFov; - qfalse, //qboolean purchasable; + qtrue, //qboolean purchasable; qfalse, //qboolean longRanged; - 0, //int buildDelay; - WUT_HUMANS //WUTeam_t team; + TEAM_HUMANS //team_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; - } - } +size_t bg_numWeapons = ARRAY_LEN( bg_weapons ); - return 100; -} +static const weaponAttributes_t nullWeapon = { 0 }; /* ============== -BG_FindStagesForWeapon +BG_WeaponByName ============== */ -qboolean BG_FindStagesForWeapon( int weapon, stage_t stage ) +const weaponAttributes_t *BG_WeaponByName( const char *name ) { int i; for( i = 0; i < bg_numWeapons; i++ ) { - if( bg_weapons[ i ].weaponNum == weapon ) + if( !Q_stricmp( bg_weapons[ i ].name, name ) ) { - if( bg_weapons[ i ].stages & ( 1 << stage ) ) - return qtrue; - else - return qfalse; + return &bg_weapons[ i ]; } } - 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; + return &nullWeapon; } /* ============== -BG_FindWeaponNumForName +BG_Weapon ============== */ -int BG_FindWeaponNumForName( char *name ) +const weaponAttributes_t *BG_Weapon( weapon_t weapon ) { - 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; + return ( weapon > WP_NONE && weapon < WP_NUM_WEAPONS ) ? + &bg_weapons[ weapon - 1 ] : &nullWeapon; } /* ============== -BG_FindHumanNameForWeapon +BG_WeaponAllowedInStage ============== */ -char *BG_FindHumanNameForWeapon( int weapon ) +qboolean BG_WeaponAllowedInStage( weapon_t weapon, stage_t stage ) { - int i; - - for( i = 0; i < bg_numWeapons; i++ ) - { - if( bg_weapons[ i ].weaponNum == weapon ) - return bg_weapons[ i ].weaponHumanName; - } + int stages = BG_Weapon( weapon )->stages; - //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; + return stages & ( 1 << stage ); } //////////////////////////////////////////////////////////////////////////////// -upgradeAttributes_t bg_upgrades[ ] = +static const upgradeAttributes_t bg_upgrades[ ] = { { - UP_LIGHTARMOUR, //int upgradeNum; + UP_LIGHTARMOUR, //int number; LIGHTARMOUR_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_TORSO|SLOT_ARMS|SLOT_LEGS, //int slots; - "larmour", //char *upgradeName; - "Light Armour", //char *upgradeHumanName; + "larmour", //char *name; + "Light Armour", //char *humanName; + "Protective armour that helps to defend against light alien melee " + "attacks.", "icons/iconu_larmour", - qtrue, //qboolean purchasable - qfalse, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qfalse, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_HELMET, //int upgradeNum; + UP_HELMET, //int number; HELMET_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_HEAD, //int slots; - "helmet", //char *upgradeName; - "Helmet", //char *upgradeHumanName; + "helmet", //char *name; + "Helmet", //char *humanName; + "In addition to protecting your head, the helmet provides a " + "scanner indicating the presence of any friendly or hostile " + "lifeforms and structures in your immediate vicinity.", "icons/iconu_helmet", - qtrue, //qboolean purchasable - qfalse, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qfalse, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_MEDKIT, //int upgradeNum; + UP_MEDKIT, //int number; MEDKIT_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_NONE, //int slots; - "medkit", //char *upgradeName; - "Medkit", //char *upgradeHumanName; + "medkit", //char *name; + "Medkit", //char *humanName; + "", "icons/iconu_atoxin", - qfalse, //qboolean purchasable - qtrue, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qfalse, //qboolean purchasable; + qtrue, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_BATTPACK, //int upgradeNum; + UP_BATTPACK, //int number; BATTPACK_PRICE, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_BACKPACK, //int slots; - "battpack", //char *upgradeName; - "Battery Pack", //char *upgradeHumanName; + "battpack", //char *name; + "Battery Pack", //char *humanName; + "Back-mounted battery pack that permits storage of one and a half " + "times the normal energy capacity for energy weapons.", "icons/iconu_battpack", - qtrue, //qboolean purchasable - qfalse, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qfalse, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_JETPACK, //int upgradeNum; + UP_JETPACK, //int number; JETPACK_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_BACKPACK, //int slots; - "jetpack", //char *upgradeName; - "Jet Pack", //char *upgradeHumanName; + "jetpack", //char *name; + "Jet Pack", //char *humanName; + "Back-mounted jet pack that enables the user to fly to remote " + "locations. It is very useful against alien spawns in hard " + "to reach spots.", "icons/iconu_jetpack", - qtrue, //qboolean purchasable - qtrue, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qtrue, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_BATTLESUIT, //int upgradeNum; + UP_BATTLESUIT, //int number; 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; + ( 1 << S3 ), //int stages; + SLOT_HEAD|SLOT_TORSO|SLOT_ARMS|SLOT_LEGS|SLOT_BACKPACK, //int slots; + "bsuit", //char *name; + "Battlesuit", //char *humanName; + "A full body armour that is highly effective at repelling alien attacks. " + "It allows the user to enter hostile situations with a greater degree " + "of confidence.", "icons/iconu_bsuit", - qtrue, //qboolean purchasable - qfalse, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qfalse, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_GRENADE, //int upgradeNum; + UP_GRENADE, //int number; GRENADE_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ),//int stages + ( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_NONE, //int slots; - "gren", //char *upgradeName; - "Grenade", //char *upgradeHumanName; + "gren", //char *name; + "Grenade", //char *humanName; + "A small incendinary device ideal for damaging tightly packed " + "alien structures. Has a five second timer.", 0, - qtrue, //qboolean purchasable - qtrue, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qtrue, //qboolean usable; + TEAM_HUMANS //team_t team; }, { - UP_AMMO, //int upgradeNum; + UP_AMMO, //int number; 0, //int price; - ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages; SLOT_NONE, //int slots; - "ammo", //char *upgradeName; - "Ammunition", //char *upgradeHumanName; + "ammo", //char *name; + "Ammunition", //char *humanName; + "Ammunition for the currently held weapon.", 0, - qtrue, //qboolean purchasable - qfalse, //qboolean usable - WUT_HUMANS //WUTeam_t team; + qtrue, //qboolean purchasable; + qfalse, //qboolean usable; + TEAM_HUMANS //team_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; - } - } +size_t bg_numUpgrades = ARRAY_LEN( bg_upgrades ); - return 100; -} +static const upgradeAttributes_t nullUpgrade = { 0 }; /* ============== -BG_FindStagesForUpgrade +BG_UpgradeByName ============== */ -qboolean BG_FindStagesForUpgrade( int upgrade, stage_t stage ) +const upgradeAttributes_t *BG_UpgradeByName( const char *name ) { int i; for( i = 0; i < bg_numUpgrades; i++ ) { - if( bg_upgrades[ i ].upgradeNum == upgrade ) + if( !Q_stricmp( bg_upgrades[ i ].name, name ) ) { - if( bg_upgrades[ i ].stages & ( 1 << stage ) ) - return qtrue; - else - return qfalse; + return &bg_upgrades[ i ]; } } - return qfalse; + return &nullUpgrade; } /* ============== -BG_FindSlotsForUpgrade +BG_Upgrade ============== */ -int BG_FindSlotsForUpgrade( int upgrade ) +const upgradeAttributes_t *BG_Upgrade( upgrade_t upgrade ) { - int i; - - for( i = 0; i < bg_numUpgrades; i++ ) - { - if( bg_upgrades[ i ].upgradeNum == upgrade ) - { - return bg_upgrades[ i ].slots; - } - } - - return SLOT_NONE; + return ( upgrade > UP_NONE && upgrade < UP_NUM_UPGRADES ) ? + &bg_upgrades[ upgrade - 1 ] : &nullUpgrade; } /* ============== -BG_FindNameForUpgrade +BG_UpgradeAllowedInStage ============== */ -char *BG_FindNameForUpgrade( int upgrade ) +qboolean BG_UpgradeAllowedInStage( upgrade_t upgrade, stage_t stage ) { - int i; - - for( i = 0; i < bg_numUpgrades; i++ ) - { - if( bg_upgrades[ i ].upgradeNum == upgrade ) - return bg_upgrades[ i ].upgradeName; - } + int stages = BG_Upgrade( upgrade )->stages; - //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; + return stages & ( 1 << stage ); } //////////////////////////////////////////////////////////////////////////////// @@ -4574,12 +2677,12 @@ void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t resu case TR_SINE: deltaTime = ( atTime - tr->trTime ) / (float)tr->trDuration; phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos - phase *= 0.5; + phase *= 2 * M_PI * 1000 / (float)tr->trDuration; VectorScale( tr->trDelta, phase, result ); break; case TR_LINEAR_STOP: - if( atTime > tr->trTime + tr->trDuration ) + if( atTime > tr->trTime + tr->trDuration || atTime < tr->trTime ) { VectorClear( result ); return; @@ -4643,7 +2746,7 @@ char *eventnames[ ] = "EV_FIRE_WEAPON2", "EV_FIRE_WEAPON3", - "EV_PLAYER_RESPAWN", //TA: for fovwarp effects + "EV_PLAYER_RESPAWN", // for fovwarp effects "EV_PLAYER_TELEPORT_IN", "EV_PLAYER_TELEPORT_OUT", @@ -4656,6 +2759,7 @@ char *eventnames[ ] = "EV_BULLET_HIT_WALL", "EV_SHOTGUN", + "EV_MASS_DRIVER", "EV_MISSILE_HIT", "EV_MISSILE_MISS", @@ -4664,8 +2768,8 @@ char *eventnames[ ] = "EV_BULLET", // otherEntity is the shooter "EV_LEV1_GRAB", - "EV_LEV4_CHARGE_PREPARE", - "EV_LEV4_CHARGE_START", + "EV_LEV4_TRAMPLE_PREPARE", + "EV_LEV4_TRAMPLE_START", "EV_PAIN", "EV_DEATH1", @@ -4673,13 +2777,13 @@ char *eventnames[ ] = "EV_DEATH3", "EV_OBITUARY", - "EV_GIB_PLAYER", // gib a previously living player + "EV_GIB_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_BUILD_CONSTRUCT", + "EV_BUILD_DESTROY", + "EV_BUILD_DELAY", // can't build yet + "EV_BUILD_REPAIR", // repairing buildable + "EV_BUILD_REPAIRED", // buildable has full health "EV_HUMAN_BUILDABLE_EXPLOSION", "EV_ALIEN_BUILDABLE_EXPLOSION", "EV_ALIEN_ACIDTUBE", @@ -4693,17 +2797,33 @@ char *eventnames[ ] = "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_OVERMIND_ATTACK", // overmind under attack + "EV_OVERMIND_DYING", // overmind close to death + "EV_OVERMIND_SPAWNS", // overmind needs spawns + + "EV_DCC_ATTACK", // dcc under attack - "EV_DCC_ATTACK", //TA: dcc under attack + "EV_MGTURRET_SPINUP", // trigger a sound - "EV_RPTUSE_SOUND" //TA: trigger a sound + "EV_RPTUSE_SOUND", // trigger a sound + "EV_LEV2_ZAP" }; /* =============== +BG_EventName +=============== +*/ +const char *BG_EventName( int num ) +{ + if( num < 0 || num >= ARRAY_LEN( eventnames ) ) + return "UNKNOWN"; + + return eventnames[ num ]; +} + +/* +=============== BG_AddPredictableEventToPlayerstate Handles the sequence numbers @@ -4714,19 +2834,21 @@ void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bu void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) { -#ifdef _DEBUG +#ifdef DEBUG_EVENTS { char buf[ 256 ]; trap_Cvar_VariableStringBuffer( "showevents", buf, sizeof( buf ) ); if( atof( buf ) != 0 ) { -#ifdef QAGAME +#ifdef GAME Com_Printf( " game event svt %5d -> %5d: num = %20s parm %d\n", - ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[ newEvent ], eventParm); + ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, + BG_EventName( 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); + ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, + BG_EventName( newEvent ), eventParm ); #endif } } @@ -4751,7 +2873,7 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean 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 ) + else if( ps->persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT ) s->eType = ET_INVISIBLE; else s->eType = ET_PLAYER; @@ -4773,11 +2895,10 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean 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->weaponAnim = ps->weaponAnim; s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number // so corpses can also reference the proper config s->eFlags = ps->eFlags; @@ -4827,12 +2948,10 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean } // use misc field to store team/class info: - s->misc = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); + s->misc = ps->stats[ STAT_TEAM ] | ( ps->stats[ STAT_CLASS ] << 8 ); - //TA: have to get the surfNormal thru somehow... + // have to get the surfNormal through 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; @@ -4840,7 +2959,7 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES ) s->generic1 = WPM_PRIMARY; - s->otherEntityNum = ps->otherEntityNum; + s->otherEntityNum = ps->otherEntityNum; } @@ -4858,7 +2977,7 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s 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 ) + else if( ps->persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT ) s->eType = ET_INVISIBLE; else s->eType = ET_PLAYER; @@ -4883,11 +3002,10 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s 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->weaponAnim = ps->weaponAnim; s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number // so corpses can also reference the proper config s->eFlags = ps->eFlags; @@ -4939,12 +3057,10 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s } // use misc field to store team/class info: - s->misc = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); + s->misc = ps->stats[ STAT_TEAM ] | ( ps->stats[ STAT_CLASS ] << 8 ); - //TA: have to get the surfNormal thru somehow... + // have to get the surfNormal through 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; @@ -4966,7 +3082,8 @@ qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips ) { int maxAmmo, maxClips; - BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); + maxAmmo = BG_Weapon( weapon )->maxAmmo; + maxClips = BG_Weapon( weapon )->maxClips; if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) ) maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); @@ -4976,63 +3093,53 @@ qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips ) /* ======================== -BG_AddWeaponToInventory +BG_InventoryContainsWeapon -Give a player a weapon +Does the player hold a weapon? ======================== */ -void BG_AddWeaponToInventory( int weapon, int stats[ ] ) +qboolean BG_InventoryContainsWeapon( 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 ); + // humans always have a blaster + if( stats[ STAT_TEAM ] == TEAM_HUMANS && weapon == WP_BLASTER ) + return qtrue; - stats[ STAT_SLOTS ] |= BG_FindSlotsForWeapon( weapon ); + return ( stats[ STAT_WEAPON ] == weapon ); } /* ======================== -BG_RemoveWeaponToInventory +BG_SlotsForInventory -Take a weapon from a player +Calculate the slots used by an inventory and warn of conflicts ======================== */ -void BG_RemoveWeaponFromInventory( int weapon, int stats[ ] ) +int BG_SlotsForInventory( int stats[ ] ) { - int weaponList; + int i, slot, slots; - weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 ); + slots = BG_Weapon( stats[ STAT_WEAPON ] )->slots; + if( stats[ STAT_TEAM ] == TEAM_HUMANS ) + slots |= BG_Weapon( WP_BLASTER )->slots; - weaponList &= ~( 1 << weapon ); - - stats[ STAT_WEAPONS ] = weaponList & 0x0000FFFF; - stats[ STAT_WEAPONS2 ] = ( weaponList & 0xFFFF0000 ) >> 16; - - stats[ STAT_SLOTS ] &= ~BG_FindSlotsForWeapon( weapon ); -} - -/* -======================== -BG_InventoryContainsWeapon + for( i = UP_NONE; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_InventoryContainsUpgrade( i, stats ) ) + { + slot = BG_Upgrade( i )->slots; -Does the player hold a weapon? -======================== -*/ -qboolean BG_InventoryContainsWeapon( int weapon, int stats[ ] ) -{ - int weaponList; + // this check should never be true + if( slots & slot ) + { + Com_Printf( S_COLOR_YELLOW "WARNING: held item %d conflicts with " + "inventory slot %d\n", i, slot ); + } - weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 ); + slots |= slot; + } + } - return( weaponList & ( 1 << weapon ) ); + return slots; } /* @@ -5045,11 +3152,6 @@ 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 ); } /* @@ -5062,8 +3164,6 @@ Take an upgrade from the player void BG_RemoveUpgradeFromInventory( int item, int stats[ ] ) { stats[ STAT_ITEMS ] &= ~( 1 << item ); - - stats[ STAT_SLOTS ] &= ~BG_FindSlotsForUpgrade( item ); } /* @@ -5166,6 +3266,40 @@ qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ], /* =============== +BG_GetClientNormal + +Get the normal for the surface the client is walking on +=============== +*/ +void BG_GetClientNormal( const playerState_t *ps, vec3_t normal ) +{ + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) + { + if( ps->eFlags & EF_WALLCLIMBCEILING ) + VectorSet( normal, 0.0f, 0.0f, -1.0f ); + else + VectorCopy( ps->grapplePoint, normal ); + } + else + VectorSet( normal, 0.0f, 0.0f, 1.0f ); +} + +/* +=============== +BG_GetClientViewOrigin + +Get the position of the client's eye, based on the client's position, the surface's normal, and client's view height +=============== +*/ +void BG_GetClientViewOrigin( const playerState_t *ps, vec3_t viewOrigin ) +{ + vec3_t normal; + BG_GetClientNormal( ps, normal ); + VectorMA( ps->origin, ps->viewheight, normal, viewOrigin ); +} + +/* +=============== BG_PositionBuildableRelativeToPlayer Find a place to build a buildable @@ -5181,19 +3315,11 @@ void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps, 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 ); + BG_GetClientNormal( ps, playerNormal ); VectorCopy( ps->viewangles, angles ); VectorCopy( ps->origin, playerOrigin ); - buildDist = BG_FindBuildDistForClass( ps->stats[ STAT_PCLASS ] ); + buildDist = BG_Class( ps->stats[ STAT_CLASS ] )->buildDist; AngleVectors( angles, forward, NULL, NULL ); ProjectPointOnPlane( forward, forward, playerNormal ); @@ -5209,54 +3335,90 @@ void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps, //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 ); + // The mask is MASK_DEADSOLID on purpose to avoid collisions with other entities + (*trace)( tr, entityOrigin, mins, maxs, targetOrigin, ps->clientNum, MASK_DEADSOLID ); + VectorCopy( tr->endpos, outOrigin ); vectoangles( forward, outAngles ); } /* =============== -BG_GetValueOfEquipment +BG_GetValueOfPlayer -Returns the equipment value of some human player's gear +Returns the credit value of a player =============== */ - int BG_GetValueOfEquipment( playerState_t *ps ) { - int i, worth = 0; +int BG_GetValueOfPlayer( playerState_t *ps ) +{ + int worth = 0; - for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) - { - if( BG_InventoryContainsUpgrade( i, ps->stats ) ) - worth += BG_FindPriceForUpgrade( i ); - } + worth = BG_Class( ps->stats[ STAT_CLASS ] )->value; - for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) + // Humans have worth from their equipment as well + if( ps->stats[ STAT_TEAM ] == TEAM_HUMANS ) { - if( BG_InventoryContainsWeapon( i, ps->stats ) ) - worth += BG_FindPriceForWeapon( i ); - } + upgrade_t i; + for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_InventoryContainsUpgrade( i, ps->stats ) ) + worth += BG_Upgrade( i )->price; + } - return worth; + if( ps->stats[ STAT_WEAPON ] != WP_NONE ) + worth += BG_Weapon( ps->stats[ STAT_WEAPON ] )->price; } + + return worth; +} + /* -=============== -BG_GetValueOfHuman +================= +BG_PlayerCanChangeWeapon +================= +*/ +qboolean BG_PlayerCanChangeWeapon( playerState_t *ps ) +{ + // Do not allow Lucifer Cannon "canceling" via weapon switch + if( ps->weapon == WP_LUCIFER_CANNON && + ps->stats[ STAT_MISC ] > LCANNON_CHARGE_TIME_MIN ) + return qfalse; -Returns the kills value of some human player -=============== + return ps->weaponTime <= 0 || ps->weaponstate != WEAPON_FIRING; +} + +/* +================= +BG_PlayerPoisonCloudTime +================= */ -int BG_GetValueOfHuman( playerState_t *ps ) +int BG_PlayerPoisonCloudTime( playerState_t *ps ) { - float portion = BG_GetValueOfEquipment( ps ) / (float)HUMAN_MAXED; + int time = LEVEL1_PCLOUD_TIME; + if( BG_InventoryContainsUpgrade( UP_BATTLESUIT, ps->stats ) ) + time -= BSUIT_PCLOUD_PROTECTION; + if( BG_InventoryContainsUpgrade( UP_HELMET, ps->stats ) ) + time -= HELMET_PCLOUD_PROTECTION; + if( BG_InventoryContainsUpgrade( UP_LIGHTARMOUR, ps->stats ) ) + time -= LIGHTARMOUR_PCLOUD_PROTECTION; + + return time; +} + +/* +================= +BG_GetPlayerWeapon - if( portion < 0.01f ) - portion = 0.01f; - else if( portion > 1.0f ) - portion = 1.0f; +Returns the players current weapon or the weapon they are switching to. +Only needs to be used for human weapons. +================= +*/ +weapon_t BG_GetPlayerWeapon( playerState_t *ps ) +{ + if( ps->persistant[ PERS_NEWWEAPON ] ) + return ps->persistant[ PERS_NEWWEAPON ]; - return ceil( ALIEN_MAX_SINGLE_KILLS * portion ); + return ps->weapon; } /* @@ -5297,6 +3459,103 @@ int atoi_neg( char *token, qboolean allowNegative ) return value; } +#define MAX_NUM_PACKED_ENTITY_NUMS 10 + +/* +=============== +BG_PackEntityNumbers + +Pack entity numbers into an entityState_t +=============== +*/ +void BG_PackEntityNumbers( entityState_t *es, const int *entityNums, int count ) +{ + int i; + + if( count > MAX_NUM_PACKED_ENTITY_NUMS ) + { + count = MAX_NUM_PACKED_ENTITY_NUMS; + Com_Printf( S_COLOR_YELLOW "WARNING: A maximum of %d entity numbers can be " + "packed, but BG_PackEntityNumbers was passed %d entities", + MAX_NUM_PACKED_ENTITY_NUMS, count ); + } + + es->misc = es->time = es->time2 = es->constantLight = 0; + + for( i = 0; i < MAX_NUM_PACKED_ENTITY_NUMS; i++ ) + { + int entityNum; + + if( i < count ) + entityNum = entityNums[ i ]; + else + entityNum = ENTITYNUM_NONE; + + if( entityNum & ~GENTITYNUM_MASK ) + { + Com_Error( ERR_FATAL, "BG_PackEntityNumbers passed an entity number (%d) which " + "exceeds %d bits", entityNum, GENTITYNUM_BITS ); + } + + switch( i ) + { + case 0: es->misc |= entityNum; break; + case 1: es->time |= entityNum; break; + case 2: es->time |= entityNum << GENTITYNUM_BITS; break; + case 3: es->time |= entityNum << (GENTITYNUM_BITS * 2); break; + case 4: es->time2 |= entityNum; break; + case 5: es->time2 |= entityNum << GENTITYNUM_BITS; break; + case 6: es->time2 |= entityNum << (GENTITYNUM_BITS * 2); break; + case 7: es->constantLight |= entityNum; break; + case 8: es->constantLight |= entityNum << GENTITYNUM_BITS; break; + case 9: es->constantLight |= entityNum << (GENTITYNUM_BITS * 2); break; + default: Com_Error( ERR_FATAL, "Entity index %d not handled", i ); break; + } + } +} + +/* +=============== +BG_UnpackEntityNumbers + +Unpack entity numbers from an entityState_t +=============== +*/ +int BG_UnpackEntityNumbers( entityState_t *es, int *entityNums, int count ) +{ + int i; + + if( count > MAX_NUM_PACKED_ENTITY_NUMS ) + count = MAX_NUM_PACKED_ENTITY_NUMS; + + for( i = 0; i < count; i++ ) + { + int *entityNum = &entityNums[ i ]; + + switch( i ) + { + case 0: *entityNum = es->misc; break; + case 1: *entityNum = es->time; break; + case 2: *entityNum = (es->time >> GENTITYNUM_BITS); break; + case 3: *entityNum = (es->time >> (GENTITYNUM_BITS * 2)); break; + case 4: *entityNum = es->time2; break; + case 5: *entityNum = (es->time2 >> GENTITYNUM_BITS); break; + case 6: *entityNum = (es->time2 >> (GENTITYNUM_BITS * 2)); break; + case 7: *entityNum = es->constantLight; break; + case 8: *entityNum = (es->constantLight >> GENTITYNUM_BITS); break; + case 9: *entityNum = (es->constantLight >> (GENTITYNUM_BITS * 2)); break; + default: Com_Error( ERR_FATAL, "Entity index %d not handled", i ); break; + } + + *entityNum &= GENTITYNUM_MASK; + + if( *entityNum == ENTITYNUM_NONE ) + break; + } + + return i; +} + /* =============== BG_ParseCSVEquipmentList @@ -5330,10 +3589,10 @@ void BG_ParseCSVEquipmentList( const char *string, weapon_t *weapons, int weapon q++; if( weaponsSize ) - weapons[ i ] = BG_FindWeaponNumForName( q ); + weapons[ i ] = BG_WeaponByName( q )->number; if( upgradesSize ) - upgrades[ j ] = BG_FindUpgradeNumForName( q ); + upgrades[ j ] = BG_UpgradeByName( q )->number; if( weaponsSize && weapons[ i ] == WP_NONE && upgradesSize && upgrades[ j ] == UP_NONE ) @@ -5367,7 +3626,7 @@ void BG_ParseCSVEquipmentList( const char *string, weapon_t *weapons, int weapon BG_ParseCSVClassList =============== */ -void BG_ParseCSVClassList( const char *string, pClass_t *classes, int classesSize ) +void BG_ParseCSVClassList( const char *string, class_t *classes, int classesSize ) { char buffer[ MAX_STRING_CHARS ]; int i = 0; @@ -5378,7 +3637,7 @@ void BG_ParseCSVClassList( const char *string, pClass_t *classes, int classesSiz p = q = buffer; - while( *p != '\0' ) + while( *p != '\0' && i < classesSize - 1 ) { //skip to first , or EOS while( *p != ',' && *p != '\0' ) @@ -5393,7 +3652,7 @@ void BG_ParseCSVClassList( const char *string, pClass_t *classes, int classesSiz while( *q == ' ' ) q++; - classes[ i ] = BG_FindClassNumForName( q ); + classes[ i ] = BG_ClassByName( q )->number; if( classes[ i ] == PCL_NONE ) Com_Printf( S_COLOR_YELLOW "WARNING: unknown class %s\n", q ); @@ -5428,7 +3687,7 @@ void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int p = q = buffer; - while( *p != '\0' ) + while( *p != '\0' && i < buildablesSize - 1 ) { //skip to first , or EOS while( *p != ',' && *p != '\0' ) @@ -5443,7 +3702,7 @@ void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int while( *q == ' ' ) q++; - buildables[ i ] = BG_FindBuildNumForName( q ); + buildables[ i ] = BG_BuildableByName( q )->number; if( buildables[ i ] == BA_NONE ) Com_Printf( S_COLOR_YELLOW "WARNING: unknown buildable %s\n", q ); @@ -5462,38 +3721,10 @@ void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int 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 ]; + class_t classes[ PCL_NUM_CLASSES ]; weapon_t weapons[ WP_NUM_WEAPONS ]; upgrade_t upgrades[ UP_NUM_UPGRADES ]; } gameElements_t; @@ -5572,7 +3803,7 @@ qboolean BG_UpgradeIsAllowed( upgrade_t upgrade ) BG_ClassIsAllowed ============ */ -qboolean BG_ClassIsAllowed( pClass_t class ) +qboolean BG_ClassIsAllowed( class_t class ) { int i; @@ -5607,81 +3838,86 @@ qboolean BG_BuildableIsAllowed( buildable_t buildable ) /* ============ -BG_ClientListTest +BG_LoadEmoticons ============ */ -qboolean BG_ClientListTest( clientList_t *list, int clientNum ) +int BG_LoadEmoticons( emoticon_t *emoticons, int num ) { - 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 ); -} + int numFiles; + char fileList[ MAX_EMOTICONS * ( MAX_EMOTICON_NAME_LEN + 9 ) ] = {""}; + int i; + char *filePtr; + int fileLen; + int count; -/* -============ -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 ) ); + numFiles = trap_FS_GetFileList( "emoticons", "x1.tga", fileList, + sizeof( fileList ) ); + + if( numFiles < 1 ) + return 0; + + filePtr = fileList; + fileLen = 0; + count = 0; + for( i = 0; i < numFiles && count < num; i++, filePtr += fileLen + 1 ) + { + fileLen = strlen( filePtr ); + if( fileLen < 9 || filePtr[ fileLen - 8 ] != '_' || + filePtr[ fileLen - 7 ] < '1' || filePtr[ fileLen - 7 ] > '9' ) + { + Com_Printf( S_COLOR_YELLOW "skipping invalidly named emoticon \"%s\"\n", + filePtr ); + continue; + } + if( fileLen - 8 > MAX_EMOTICON_NAME_LEN ) + { + Com_Printf( S_COLOR_YELLOW "emoticon file name \"%s\" too long (>%d)\n", + filePtr, MAX_EMOTICON_NAME_LEN + 8 ); + continue; + } + if( !trap_FS_FOpenFile( va( "emoticons/%s", filePtr ), NULL, FS_READ ) ) + { + Com_Printf( S_COLOR_YELLOW "could not open \"emoticons/%s\"\n", filePtr ); + continue; + } + + Q_strncpyz( emoticons[ count ].name, filePtr, fileLen - 8 + 1 ); +#ifndef GAME + emoticons[ count ].width = filePtr[ fileLen - 7 ] - '0'; +#endif + count++; + } + + Com_Printf( "Loaded %d of %d emoticons (MAX_EMOTICONS is %d)\n", + count, numFiles, MAX_EMOTICONS ); + return count; } /* ============ -BG_ClientListRemove +BG_TeamName ============ */ -void BG_ClientListRemove( clientList_t *list, int clientNum ) +char *BG_TeamName( team_t team ) { - if( clientNum < 0 || clientNum >= MAX_CLIENTS || !list ) - return; - if( clientNum < 32 ) - list->lo &= ~( 1 << clientNum ); - else - list->hi &= ~( 1 << ( clientNum - 32 ) ); + if( team == TEAM_NONE ) + return "spectator"; + if( team == TEAM_ALIENS ) + return "alien"; + if( team == TEAM_HUMANS ) + return "human"; + return "<team>"; } -/* -============ -BG_ClientListString -============ -*/ -char *BG_ClientListString( clientList_t *list ) +int cmdcmp( const void *a, const void *b ) { - static char s[ 17 ]; - - s[ 0 ] = '\0'; - if( !list ) - return s; - Com_sprintf( s, sizeof( s ), "%08x%08x", list->hi, list->lo ); - return s; + return Q_stricmp( (const char *)a, ((dummyCmd_t *)b)->name ); } -/* -============ -BG_ClientListParse -============ -*/ -void BG_ClientListParse( clientList_t *list, const char *s ) +char *G_CopyString( const char *str ) { - 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 ); + size_t size = strlen( str ) + 1; + char *cp = BG_Alloc( size ); + memcpy( cp, str, size ); + return cp; } - - |