summaryrefslogtreecommitdiff
path: root/src/game/bg_misc.c
diff options
context:
space:
mode:
authorMikko Tiusanen <ams@daug.net>2014-05-04 01:18:52 +0300
committerMikko Tiusanen <ams@daug.net>2014-05-04 01:18:52 +0300
commit01beb9919b95479d8be040bec74abc5cc67a5e43 (patch)
tree65f0b79e793848491832756a4c3a32b23668fab3 /src/game/bg_misc.c
parent191d731da136b7ee959a17e63111c9146219a768 (diff)
Initial import.
Diffstat (limited to 'src/game/bg_misc.c')
-rw-r--r--src/game/bg_misc.c5447
1 files changed, 5447 insertions, 0 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
new file mode 100644
index 0000000..eee366b
--- /dev/null
+++ b/src/game/bg_misc.c
@@ -0,0 +1,5447 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2000-2009 Darklegion Development
+
+This file is part of Tremulous.
+
+Tremulous is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Tremulous is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Tremulous; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+/*
+===========================================================================
+TREMULOUS EDGE MOD SRC FILE
+===========================================================================
+*/
+
+// bg_misc.c -- both games misc functions, all completely stateless
+#include "../qcommon/q_shared.h"
+#include "bg_public.h"
+
+int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
+void trap_FS_Read( void *buffer, int len, fileHandle_t f );
+void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
+void trap_FS_FCloseFile( fileHandle_t f );
+void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t
+int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
+
+static const buildableAttributes_t bg_buildableList[ ] =
+{
+//ALIEN BUILDINGS
+ {
+ BA_A_SPAWN, //int buildNum;
+ "eggpod", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ ASPAWN_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ ASPAWN_HEALTH, //int health;
+ ASPAWN_REGEN, //int regenRate;
+ ASPAWN_SPLASHDAMAGE, //int splashDamage;
+ ASPAWN_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ ASPAWN_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ ASPAWN_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ ASPAWN_VALUE, //int value;
+ },
+ {
+ BA_A_OVERMIND, //int buildNum;
+ "overmind", //char *buildName;
+ "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;
+ 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;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ OVERMIND_ATTACK_REPEAT,//int nextthink;
+ OVERMIND_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ OVERMIND_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qtrue, //qboolean uniqueTest;
+ OVERMIND_VALUE, //int value;
+ },
+ {
+ BA_A_BARRICADE, //int buildNum;
+ "barricade", //char *buildName;
+ "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;
+ 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;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),//weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ BARRICADE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;//
+ qtrue, //qboolean creepTest;
+ BARRICADE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BARRICADE_VALUE, //int value;
+ },
+ {
+ BA_A_ACIDTUBE, //int buildNum;
+ "acid_tube", //char *buildName;
+ "Acid Tube", //char *humanName;
+ "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
+ ACIDTUBE_HEALTH, //int health;
+ ACIDTUBE_REGEN, //int regenRate;
+ ACIDTUBE_SPLASHDAMAGE, //int splashDamage;
+ ACIDTUBE_SPLASHRADIUS, //int splashRadius;
+ 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;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ ACIDTUBE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ ACIDTUBE_VALUE, //int value;
+ },
+ {
+ BA_A_TRAPPER, //int buildNum;
+ "trapper", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ TRAPPER_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ TRAPPER_HEALTH, //int health;
+ TRAPPER_REGEN, //int regenRate;
+ TRAPPER_SPLASHDAMAGE, //int splashDamage;
+ TRAPPER_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ TRAPPER_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ TRAPPER_RANGE, //int turretRange;
+ TRAPPER_REPEAT, //int turretFireSpeed;
+ WP_LOCKBLOB_LAUNCHER, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ TRAPPER_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TRAPPER_VALUE, //int value;
+ },
+ {
+ BA_A_BOOSTER, //int buildNum;
+ "booster", //char *buildName;
+ "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;
+ 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;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ BOOSTER_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ BOOSTER_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BOOSTER_VALUE, //int value;
+ },
+ {
+ BA_A_HIVE, //int buildNum;
+ "hive", //char *buildName;
+ "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;
+ 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;
+ TEAM_ALIENS, //int team;
+ ( 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 uniqueTest;
+ HIVE_VALUE, //int value;
+ },
+ {
+ BA_A_PANZER_SMALL, //int buildNum;
+ "panzer_small", //char *buildName;
+ "[ye]Panzer Small", //char *humanName;
+ "LIGHT ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n",
+ "team_alien_panzer_small", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ PANZER_SMALL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ PANZER_SMALL_HEALTH, //int health;
+ PANZER_SMALL_REGEN, //int regenRate;
+ PANZER_SMALL_SPLASHDAMAGE, //int splashDamage;
+ PANZER_SMALL_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ PANZER_SMALL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ PANZER_SMALL_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ PANZER_SMALL_VALUE, //int value;
+ },
+ {
+ BA_A_PANZER_MEDIUM, //int buildNum;
+ "panzer_medium", //char *buildName;
+ "[ye]Panzer Medium", //char *humanName;
+ "AVERAGE ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n",
+ "team_alien_panzer_medium", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ PANZER_MEDIUM_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ PANZER_MEDIUM_HEALTH, //int health;
+ PANZER_MEDIUM_REGEN, //int regenRate;
+ PANZER_MEDIUM_SPLASHDAMAGE, //int splashDamage;
+ PANZER_MEDIUM_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ PANZER_MEDIUM_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ PANZER_MEDIUM_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ PANZER_MEDIUM_VALUE, //int value;
+ },
+ {
+ BA_A_PANZER_LARGE, //int buildNum;
+ "panzer_large", //char *buildName;
+ "[ye]Panzer Large", //char *humanName;
+ "HEAVY ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n",
+ "team_alien_panzer_large", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ PANZER_LARGE_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ PANZER_LARGE_HEALTH, //int health;
+ PANZER_LARGE_REGEN, //int regenRate;
+ PANZER_LARGE_SPLASHDAMAGE, //int splashDamage;
+ PANZER_LARGE_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ PANZER_LARGE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ PANZER_LARGE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ PANZER_LARGE_VALUE, //int value;
+ },
+ {
+ BA_A_TENDON_SMALL, //int buildNum;
+ "tendon_small", //char *buildName;
+ "[ye]Tendon Small", //char *humanName;
+ "LIGHT ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense or bridges.\n",
+ "team_alien_tendon_small", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ TENDON_SMALL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ TENDON_SMALL_HEALTH, //int health;
+ TENDON_SMALL_REGEN, //int regenRate;
+ TENDON_SMALL_SPLASHDAMAGE, //int splashDamage;
+ TENDON_SMALL_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ TENDON_SMALL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ TENDON_SMALL_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TENDON_SMALL_VALUE, //int value;
+ },
+ {
+ BA_A_TENDON_MEDIUM, //int buildNum;
+ "tendon_medium", //char *buildName;
+ "[ye]Tendon Medium", //char *humanName;
+ "AVERAGE ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense or bridges.\n"
+ "50HP",
+ "team_alien_tendon_medium",//char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ TENDON_MEDIUM_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ TENDON_MEDIUM_HEALTH, //int health;
+ TENDON_MEDIUM_REGEN, //int regenRate;
+ TENDON_MEDIUM_SPLASHDAMAGE, //int splashDamage;
+ TENDON_MEDIUM_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ TENDON_MEDIUM_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ TENDON_MEDIUM_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TENDON_MEDIUM_VALUE, //int value;
+ },
+ {
+ BA_A_TENDON_LARGE, //int buildNum;
+ "tendon_large", //char *buildName;
+ "[ye]Tendon Large", //char *humanName;
+ "HEAVY ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense or big bridges.\n"
+ "100HP",
+ "team_alien_tendon_large",//char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ TENDON_LARGE_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ TENDON_LARGE_HEALTH, //int health;
+ TENDON_LARGE_REGEN, //int regenRate;
+ TENDON_LARGE_SPLASHDAMAGE, //int splashDamage;
+ TENDON_LARGE_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ TENDON_LARGE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ TENDON_LARGE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TENDON_LARGE_VALUE, //int value;
+ },
+ {
+ BA_A_NET, //int buildNum;
+ "net", //char *buildName;
+ "[ye]Net", //char *humanName;
+ "LIGHT ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "Can be used for camouflage.\n"
+ "80HP",
+ "team_alien_net",//char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ NET_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ NET_HEALTH, //int health;
+ NET_REGEN, //int regenRate;
+ NET_SPLASHDAMAGE, //int splashDamage;
+ NET_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ NET_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ NET_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ NET_VALUE, //int value;
+ },
+ {
+ BA_A_NET_SPIKE, //int buildNum;
+ "net_spike", //char *buildName;
+ "[ye]Net Spike", //char *humanName;
+ "LIGHT ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "Can be used for camouflage.\n"
+ "50HP",
+ "team_alien_net_spike",//char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ NET_SPIKE_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ NET_SPIKE_HEALTH, //int health;
+ NET_SPIKE_REGEN, //int regenRate;
+ NET_SPIKE_SPLASHDAMAGE, //int splashDamage;
+ NET_SPIKE_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ NET_SPIKE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ NET_SPIKE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ NET_SPIKE_VALUE, //int value;
+ },
+ {
+ BA_A_INFESTATION_SLIME, //int buildNum;
+ "infestation_slime", //char *buildName;
+ "[ye]Infestation Slime", //char *humanName;
+ "LIGHT ORGANIC INFESTATION\n"
+ "[yei]Used for passive and active base defense.\n"
+ "Has the ability to slow down human players.\n"
+ "Nearby Humans get *sucked* in and take damage.\n"
+ "250HP",
+ "team_alien_infestation_slime",//char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ INFESTATION_SLIME_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ INFESTATION_SLIME_HEALTH, //int health;
+ INFESTATION_SLIME_REGEN, //int regenRate;
+ INFESTATION_SLIME_SPLASHDAMAGE, //int splashDamage;
+ INFESTATION_SLIME_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 200, //int nextthink;
+ INFESTATION_SLIME_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ INFESTATION_SLIME_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ INFESTATION_SLIME_VALUE, //int value;
+ },
+ {
+ BA_A_INFESTATION_THICKET, //int buildNum;
+ "infestation_thicket", //char *buildName;
+ "[ye]Infestation Thicket", //char *humanName;
+ "AVERAGE ORGANIC INFESTATION\n"
+ "[yei]Used for passive base defense.\n"
+ "Has the ability to slow down human players.\n"
+ "It's dense undergrowth can be used for camouflage.\n",
+ "team_alien_infestation_thicket", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ INFESTATION_THICKET_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ INFESTATION_THICKET_HEALTH, //int health;
+ INFESTATION_THICKET_REGEN, //int regenRate;
+ INFESTATION_THICKET_SPLASHDAMAGE, //int splashDamage;
+ INFESTATION_THICKET_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),//weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ INFESTATION_THICKET_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ INFESTATION_THICKET_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ INFESTATION_THICKET_VALUE, //int value;
+ },
+ {
+ BA_A_INFESTATION_BLISTER, //int buildNum;
+ "infestation_blister", //char *buildName;
+ "[ye]Infestation Blister", //char *humanName;
+ "HEAVY ORGANIC INFESTATION\n"
+ "[yei]Used for passive base defense.\n"
+ "Has the ability to slow down human players.\n"
+ "Creates a creep of massive scale.\n",
+ "team_alien_infestation_blister", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ INFESTATION_BLISTER_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ INFESTATION_BLISTER_HEALTH, //int health;
+ INFESTATION_BLISTER_REGEN, //int regenRate;
+ INFESTATION_BLISTER_SPLASHDAMAGE, //int splashDamage;
+ INFESTATION_BLISTER_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ INFESTATION_BLISTER_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ INFESTATION_BLISTER_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ INFESTATION_BLISTER_VALUE, //int value;
+ },
+ {
+ BA_A_REFLECTOR, //int buildNum;
+ "reflector", //char *buildName;
+ "[ye]Reflector", //char *humanName;
+ "INTELLIGENT ORGANIC STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This structure is filled with mercury.\n"
+ "It reflects Pulse Rifle & Lucifer shots.\n"
+ "Its vulnerable to mechanical projectiles.\n",
+ "team_alien_reflector", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ REFLECTOR_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ REFLECTOR_HEALTH, //int health;
+ REFLECTOR_REGEN, //int regenRate;
+ REFLECTOR_SPLASHDAMAGE, //int splashDamage;
+ REFLECTOR_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ REFLECTOR_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ REFLECTOR_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ REFLECTOR_VALUE, //int value;
+ },
+ {
+ BA_A_MUSCLE, //int buildNum;
+ "muscle", //char *buildName;
+ "[ye]Muscle", //char *humanName;
+ "INTELLIGENT ORGANIC STRUCTURE\n"
+ "[yei]Used to push alien players up.\n",
+ "team_alien_muscle", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ MUSCLE_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ MUSCLE_HEALTH, //int health;
+ MUSCLE_REGEN, //int regenRate;
+ MUSCLE_SPLASHDAMAGE, //int splashDamage;
+ MUSCLE_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 500, //int nextthink;
+ MUSCLE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ MUSCLE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ MUSCLE_VALUE, //int value;
+ },
+ {
+ BA_A_SPITEFUL_ABCESS, //int buildNum;
+ "spiteful_abcess", //char *buildName;
+ "[ye]Spiteful Abcess", //char *humanName;
+ "INTELLIGENT ORGANIC STRUCTURE\n"
+ "[yei]Used for active base defense.\n"
+ "The glowing top contains gas.\n",
+ "team_alien_spiteful_abcess", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ SPITEFUL_ABCESS_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SPITEFUL_ABCESS_HEALTH, //int health;
+ SPITEFUL_ABCESS_REGEN, //int regenRate;
+ SPITEFUL_ABCESS_SPLASHDAMAGE, //int splashDamage;
+ SPITEFUL_ABCESS_SPLASHRADIUS, //int splashRadius;
+ MOD_SPITEFUL_ABCESS, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 200, //int nextthink;
+ SPITEFUL_ABCESS_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ SPITEFUL_ABCESS_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ SPITEFUL_ABCESS_VALUE, //int value;
+ },
+ {
+ BA_A_COCOON, //int buildNum;
+ "cocoon", //char *buildName;
+ "[ye]Cocoon", //char *humanName;
+ "INTELLIGENT ORGANIC STRUCTURE\n"
+ "[yei]This heals your team faster\n"
+ "+faster adv.goon barb regen.\n"
+ "Can only be built once\n",
+ "team_alien_cocoon", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ COCOON_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ COCOON_HEALTH, //int health;
+ COCOON_REGEN, //int regenRate;
+ COCOON_SPLASHDAMAGE, //int splashDamage;
+ COCOON_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ COCOON_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ COCOON_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qtrue, //qboolean uniqueTest;
+ COCOON_VALUE, //int value;
+ },
+ {
+ BA_A_ORGANIC_BULB, //int buildNum;
+ "organic_bulb", //char *buildName;
+ "[ye]Organic Bulb", //char *humanName;
+ "INTELLIGENT ORGANIC STRUCTURE\n"
+ "[yei]Used to light spots.\n",
+ "team_alien_organic_bulb", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ ORGANIC_BULB_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ ORGANIC_BULB_HEALTH, //int health;
+ ORGANIC_BULB_REGEN, //int regenRate;
+ ORGANIC_BULB_SPLASHDAMAGE, //int splashDamage;
+ ORGANIC_BULB_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ ORGANIC_BULB_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ ORGANIC_BULB_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ ORGANIC_BULB_VALUE, //int value;
+ },
+ {
+ BA_A_POD, //int buildNum;
+ "pod", //char *buildName;
+ "[ye]Pod", //char *humanName;
+ "HEAVY ORGANIC STRUCTURE\n"
+ "[yei]This contains on top of the Pod Stump.\n"
+ "It is used to shield the top of bases.\n",
+ "team_alien_pod", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ POD_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ POD_HEALTH, //int health;
+ POD_REGEN, //int regenRate;
+ POD_SPLASHDAMAGE, //int splashDamage;
+ POD_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ POD_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ POD_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ POD_VALUE, //int value;
+ },
+ {
+ BA_A_POD_STUMP, //int buildNum;
+ "pod_stump", //char *buildName;
+ "[ye]Pod Stump", //char *humanName;
+ "HEAVY ORGANIC STRUCTURE\n"
+ "[yei]This is the stump for Pod.\n",
+ "team_alien_pod_stump", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ POD_STUMP_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ POD_STUMP_HEALTH, //int health;
+ POD_STUMP_REGEN, //int regenRate;
+ POD_STUMP_SPLASHDAMAGE, //int splashDamage;
+ POD_STUMP_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ POD_STUMP_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 1.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ POD_STUMP_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ POD_STUMP_VALUE, //int value;
+ },
+ {
+ BA_A_CREEPCOLONY, //int buildNum;
+ "creepcolony", //char *buildName;
+ "[ye]Creep colony", //char *humanName;
+ "[yei]Gives your team extra buildpoints.",
+ "team_alien_creepcolony" , //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ CREEPCOLONY_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ CREEPCOLONY_HEALTH, //int health;
+ CREEPCOLONY_REGEN, //int regenRate;
+ CREEPCOLONY_SPLASHDAMAGE, //int splashDamage;
+ CREEPCOLONY_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ TEAM_ALIENS, //int team;
+ ( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ CREEPCOLONY_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ CREEPCOLONY_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ CREEPCOLONY_VALUE, //int value;
+ },
+
+//HUMAN BUILDINGS
+ {
+ BA_H_SPAWN, //int buildNum;
+ "telenode", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ HSPAWN_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ HSPAWN_HEALTH, //int health;
+ 0, //int regenRate;
+ HSPAWN_SPLASHDAMAGE, //int splashDamage;
+ HSPAWN_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ HSPAWN_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qfalse, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ HSPAWN_VALUE, //int value;
+ },
+ {
+ BA_H_MGTURRET, //int buildNum;
+ "mgturret", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ MGTURRET_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ MGTURRET_HEALTH, //int health;
+ 0, //int regenRate;
+ MGTURRET_SPLASHDAMAGE, //int splashDamage;
+ MGTURRET_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 50, //int nextthink;
+ MGTURRET_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ MGTURRET_RANGE, //int turretRange;
+ MGTURRET_REPEAT, //int turretFireSpeed;
+ WP_MGTURRET, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ MGTURRET_VALUE, //int value;
+ },
+ {
+ BA_H_MGTURRET2, //int buildNum;
+ "mgturret2", //char *buildName;
+ "[ye]Flame 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_mgturret2", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ MGTURRET2_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ MGTURRET2_HEALTH, //int health;
+ 0, //int regenRate;
+ MGTURRET2_SPLASHDAMAGE, //int splashDamage;
+ MGTURRET2_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 50, //int nextthink;
+ MGTURRET2_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ MGTURRET2_RANGE, //int turretRange;
+ MGTURRET2_REPEAT, //int turretFireSpeed;
+ WP_MGTURRET2, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ MGTURRET_VALUE, //int value;
+ },
+ {
+ BA_H_TESLAGEN, //int buildNum;
+ "tesla", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ TESLAGEN_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ TESLAGEN_HEALTH, //int health;
+ 0, //int regenRate;
+ TESLAGEN_SPLASHDAMAGE, //int splashDamage;
+ TESLAGEN_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 150, //int nextthink;
+ TESLAGEN_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ TESLAGEN_RANGE, //int turretRange;
+ TESLAGEN_REPEAT, //int turretFireSpeed;
+ WP_TESLAGEN, //weapon_t turretProjType;
+ 0.95f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TESLAGEN_VALUE, //int value;
+ },
+ {
+ BA_H_ARMOURY, //int buildNum;
+ "arm", //char *buildName;
+ "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.0f, //float minNormal;
+ qtrue, //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 buildNum;
+ "dcc", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ DC_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ DC_HEALTH, //int health;
+ 0, //int regenRate;
+ DC_SPLASHDAMAGE, //int splashDamage;
+ DC_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ DC_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ DC_VALUE, //int value;
+ },
+ {
+ BA_H_MEDISTAT, //int buildNum;
+ "medistat", //char *buildName;
+ "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;
+ 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;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //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.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qtrue, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ MEDISTAT_VALUE, //int value;
+ },
+ {
+ BA_H_REACTOR, //int buildNum;
+ "reactor", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ REACTOR_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ REACTOR_HEALTH, //int health;
+ 0, //int regenRate;
+ REACTOR_SPLASHDAMAGE, //int splashDamage;
+ REACTOR_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ REACTOR_ATTACK_DCC_REPEAT, //int nextthink;
+ REACTOR_BT, //int buildTime;
+ qtrue, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qtrue, //qboolean uniqueTest;
+ REACTOR_VALUE, //int value;
+ },
+ {
+ BA_H_REPEATER, //int buildNum;
+ "repeater", //char *buildName;
+ "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;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ REPEATER_BP, //int buildPoints;
+ ( 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;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ REPEATER_BT, //int buildTime;
+ qtrue, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ REPEATER_VALUE, //int value;
+ },
+ {
+ BA_H_CONTAINER_SMALL, //int buildNum;
+ "container_small", //char *buildName;
+ "[ye]Container Small", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_container_small", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ CONTAINER_SMALL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ CONTAINER_SMALL_HEALTH, //int health;
+ 0, //int regenRate;
+ CONTAINER_SMALL_SPLASHDAMAGE, //int splashDamage;
+ CONTAINER_SMALL_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ CONTAINER_SMALL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ CONTAINER_SMALL_VALUE, //int value;
+ },
+ {
+ BA_H_CONTAINER_MEDIUM, //int buildNum;
+ "container_medium", //char *buildName;
+ "[ye]Container Medium", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_container_medium", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ CONTAINER_MEDIUM_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ CONTAINER_MEDIUM_HEALTH, //int health;
+ 0, //int regenRate;
+ CONTAINER_MEDIUM_SPLASHDAMAGE, //int splashDamage;
+ CONTAINER_MEDIUM_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ CONTAINER_MEDIUM_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ CONTAINER_MEDIUM_VALUE, //int value;
+ },
+ {
+ BA_H_CONTAINER_LARGE, //int buildNum;
+ "container_large", //char *buildName;
+ "[ye]Container Large", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_container_large", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ CONTAINER_LARGE_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ CONTAINER_LARGE_HEALTH, //int health;
+ 0, //int regenRate;
+ CONTAINER_LARGE_SPLASHDAMAGE, //int splashDamage;
+ CONTAINER_LARGE_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ CONTAINER_LARGE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ CONTAINER_LARGE_VALUE, //int value;
+ },
+ {
+ BA_H_PLATE_SMALL, //int buildNum;
+ "plate_small", //char *buildName;
+ "[ye]Plate Small", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense or bridges.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_plate_small", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ PLATE_SMALL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ PLATE_SMALL_HEALTH, //int health;
+ 0, //int regenRate;
+ PLATE_SMALL_SPLASHDAMAGE, //int splashDamage;
+ PLATE_SMALL_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ PLATE_SMALL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ PLATE_SMALL_VALUE, //int value;
+ },
+ {
+ BA_H_PLATE_LARGE, //int buildNum;
+ "plate_large", //char *buildName;
+ "[ye]Plate Large", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense or bridges.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_plate_large", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ PLATE_LARGE_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ PLATE_LARGE_HEALTH, //int health;
+ 0, //int regenRate;
+ PLATE_LARGE_SPLASHDAMAGE, //int splashDamage;
+ PLATE_LARGE_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ PLATE_LARGE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ PLATE_LARGE_VALUE, //int value;
+ },
+ {
+ BA_H_FENCE, //int buildNum;
+ "fence", //char *buildName;
+ "[ye]Fence", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_fence", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ FENCE_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ FENCE_HEALTH, //int health;
+ 0, //int regenRate;
+ FENCE_SPLASHDAMAGE, //int splashDamage;
+ FENCE_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ FENCE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ FENCE_VALUE, //int value;
+ },
+ {
+ BA_H_FENCE_ROD, //int buildNum;
+ "fence_rod", //char *buildName;
+ "[ye]Fence Rod", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_fence_rod", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ FENCE_ROD_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ FENCE_HEALTH, //int health;
+ 0, //int regenRate;
+ FENCE_ROD_SPLASHDAMAGE, //int splashDamage;
+ FENCE_ROD_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ FENCE_ROD_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ FENCE_ROD_VALUE, //int value;
+ },
+ {
+ BA_H_BARRIER_LINE, //int buildNum;
+ "barrier_line", //char *buildName;
+ "[ye]Barrier Line", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_barrier_line", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ BARRIER_LINE_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ BARRIER_LINE_HEALTH, //int health;
+ 0, //int regenRate;
+ BARRIER_LINE_SPLASHDAMAGE, //int splashDamage;
+ BARRIER_LINE_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ BARRIER_LINE_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BARRIER_LINE_VALUE, //int value;
+ },
+ {
+ BA_H_BARRIER_CORNER, //int buildNum;
+ "barrier_corner", //char *buildName;
+ "[ye]Barrier Corner", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_barrier_corner", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ BARRIER_CORNER_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ BARRIER_CORNER_HEALTH, //int health;
+ 0, //int regenRate;
+ BARRIER_CORNER_SPLASHDAMAGE, //int splashDamage;
+ BARRIER_CORNER_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ BARRIER_CORNER_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BARRIER_CORNER_VALUE, //int value;
+ },
+ {
+ BA_H_BARRIER_POINT, //int buildNum;
+ "barrier_point", //char *buildName;
+ "[ye]Barrier Point", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used for passive base defense.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_barrier_point", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ BARRIER_POINT_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ BARRIER_POINT_HEALTH, //int health;
+ 0, //int regenRate;
+ BARRIER_POINT_SPLASHDAMAGE, //int splashDamage;
+ BARRIER_POINT_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ BARRIER_POINT_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BARRIER_POINT_VALUE, //int value;
+ },
+ {
+ BA_H_SHIELD, //int buildNum;
+ "shield", //char *buildName;
+ "[ye]Shield", //char *humanName;
+ "INTELLIGENT STRUCTURE\n"
+ "[yei]Energy-Shield / Floodgate."
+ "Can only be used by humans.",
+ "team_human_shield", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ SHIELD_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ SHIELD_HEALTH, //int health;
+ 0, //int regenRate;
+ SHIELD_SPLASHDAMAGE, //int splashDamage;
+ SHIELD_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ SHIELD_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ SHIELD_VALUE, //int value;
+ },
+ {
+ BA_H_LADDER, //int buildNum;
+ "ladder", //char *buildName;
+ "[ye]Ammo Supply", //char *humanName;
+ "INTELLIGENT STRUCTURE\n"
+ "[yei]A tiny ammo box for non-energy weapons.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_ladder", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0, //float bounce;
+ LADDER_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ LADDER_HEALTH, //int health;
+ 0, //int regenRate;
+ LADDER_SPLASHDAMAGE, //int splashDamage;
+ LADDER_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ LADDER_BT, //int buildTime;
+ qtrue, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ LADDER_VALUE, //int value;
+ },
+ {
+ BA_H_TEFLON_FOIL, //int buildNum;
+ "teflon_foil", //char *buildName;
+ "[ye]Teflon Foil", //char *humanName;
+ "SEMI-SOLID STRUCTURE\n"
+ "[yei]Can be used for camouflage.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_teflon_foil", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ TEFLON_FOIL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ TEFLON_FOIL_HEALTH, //int health;
+ 0, //int regenRate;
+ TEFLON_FOIL_SPLASHDAMAGE, //int splashDamage;
+ TEFLON_FOIL_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ TEFLON_FOIL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ TEFLON_FOIL_VALUE, //int value;
+ },
+ {
+ BA_H_BARREL, //int buildNum;
+ "barrel", //char *buildName;
+ "[ye]Barrel", //char *humanName;
+ "SOLID STRUCTURE\n"
+ "[yei]Used to build bases.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_barrel", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ BARREL_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ BARREL_HEALTH, //int health;
+ 0, //int regenRate;
+ BARREL_SPLASHDAMAGE, //int splashDamage;
+ BARREL_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ BARREL_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ BARREL_VALUE, //int value;
+ },
+ {
+ BA_H_LIGHT, //int buildNum;
+ "light", //char *buildName;
+ "[ye]ForceField", //char *humanName;
+ "INTELLIGENT SOLID STRUCTURE\n"
+ "[yei]Creates a forcefield wich.\n"
+ "pushes alien boddies back.\n",
+ "team_human_light", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ LIGHT_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ LIGHT_HEALTH, //int health;
+ 0, //int regenRate;
+ LIGHT_SPLASHDAMAGE, //int splashDamage;
+ LIGHT_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 400, //int nextthink;
+ LIGHT_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ LIGHT_VALUE, //int value;
+ },
+ {
+ BA_H_COVER, //int buildNum;
+ "cover", //char *buildName;
+ "[ye]Cover", //char *humanName;
+ "HEAVY SOLID STRUCTURE\n"
+ "[yei]This contains on top of the Cover Stump.\n"
+ "It is used to shield the top of bases.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_cover", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ COVER_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ COVER_HEALTH, //int health;
+ 0, //int regenRate;
+ COVER_SPLASHDAMAGE, //int splashDamage;
+ COVER_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ COVER_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ COVER_VALUE, //int value;
+ },
+ {
+ BA_H_COVER_STUMP, //int buildNum;
+ "cover_stump", //char *buildName;
+ "[ye]Cover Stump", //char *humanName;
+ "HEAVY SOLID STRUCTURE\n"
+ "[yei]This is the stump for the Cover.\n"
+ "This building doesn't need a powered area!\n",
+ "team_human_cover_stump", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ COVER_STUMP_BP, //int buildPoints;
+ ( 1 << S3 ), //int stages
+ COVER_STUMP_HEALTH, //int health;
+ 0, //int regenRate;
+ COVER_STUMP_SPLASHDAMAGE, //int splashDamage;
+ COVER_STUMP_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 0, //int nextthink;
+ COVER_STUMP_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ COVER_STUMP_VALUE, //int value;
+ },
+ {
+ BA_H_REFINERY, //int buildNum;
+ "refinery", //char *buildName;
+ "[ye]Refinery", //char *humanName;
+ "SUPPLY STRUCTURE\n"
+ "[yei]Gives your team 75 buildpoints, ",
+ "team_human_refinery", //char *entityName;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ REFINERY_BP, //int buildPoints;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ REFINERY_HEALTH, //int health;
+ 0, //int regenRate;
+ REFINERY_SPLASHDAMAGE, //int splashDamage;
+ REFINERY_SPLASHRADIUS, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ TEAM_HUMANS, //int team;
+ ( 1 << WP_HBUILD ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 1000, //int nextthink;
+ REFINERY_BT, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_NONE, //weapon_t turretProjType;
+ 0.0f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ 0, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse, //qboolean transparentTest;
+ qfalse, //qboolean uniqueTest;
+ REFINERY_VALUE, //int value;
+ },
+ };
+
+int bg_numBuildables = sizeof( bg_buildableList ) / sizeof( bg_buildableList[ 0 ] );
+static const buildableAttributes_t nullBuildable = { 0 };
+/*
+==============
+BG_BuildableByName
+==============
+*/
+const buildableAttributes_t *BG_BuildableByName( const char *name )
+{
+ int i;
+
+ for( i = 0; i < bg_numBuildables; i++ )
+ {
+ if( !Q_stricmp( bg_buildableList[ i ].name, name ) )
+ return &bg_buildableList[ i ];
+ }
+ return &nullBuildable;
+}
+
+/*
+==============
+BG_BuildableByEntityName
+==============
+*/
+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 ];
+ }
+ return &nullBuildable;
+}
+
+/*
+==============
+BG_Buildable
+==============
+*/
+const buildableAttributes_t *BG_Buildable( buildable_t buildable )
+{
+ return ( buildable > BA_NONE && buildable < BA_NUM_BUILDABLES ) ?
+ &bg_buildableList[ buildable - 1 ] : &nullBuildable;
+}
+
+/*
+==============
+BG_BuildableAllowedInStage
+==============
+*/
+qboolean BG_BuildableAllowedInStage( buildable_t buildable,
+ stage_t stage )
+{
+ int stages = BG_Buildable( buildable )->stages;
+
+ if( stages & ( 1 << stage ) )
+ return qtrue;
+ else
+ return qfalse;
+}
+
+static buildableConfig_t bg_buildableConfigList[ BA_NUM_BUILDABLES ];
+
+/*
+==============
+BG_BuildableConfig
+==============
+*/
+buildableConfig_t *BG_BuildableConfig( buildable_t buildable )
+{
+ return &bg_buildableConfigList[ buildable ];
+}
+
+/*
+==============
+BG_BuildableBoundingBox
+==============
+*/
+void BG_BuildableBoundingBox( buildable_t buildable,
+ vec3_t mins, vec3_t maxs )
+{
+ buildableConfig_t *buildableConfig = BG_BuildableConfig( buildable );
+
+ if( mins != NULL )
+ VectorCopy( buildableConfig->mins, mins );
+ if( maxs != NULL )
+ VectorCopy( buildableConfig->maxs, maxs );
+}
+
+/*
+======================
+BG_ParseBuildableFile
+
+Parses a configuration file describing a buildable
+======================
+*/
+static qboolean BG_ParseBuildableFile( const char *filename, buildableConfig_t *bc )
+{
+ char *text_p;
+ int i;
+ int len;
+ char *token;
+ 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 )
+ {
+ trap_FS_FCloseFile( f );
+ Com_Printf( S_COLOR_RED "ERROR: Buildable file %s is %s\n", filename,
+ len == 0 ? "empty" : "too long" );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read optional parameters
+ while( 1 )
+ {
+ token = COM_Parse( &text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "" ) )
+ break;
+
+ if( !Q_stricmp( token, "model" ) )
+ {
+ int index = 0;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ index = atoi( token );
+
+ if( index < 0 )
+ index = 0;
+ else if( index > 3 )
+ index = 3;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( bc->models[ index ], token, sizeof( bc->models[ 0 ] ) );
+
+ defined |= MODEL;
+ continue;
+ }
+ else if( !Q_stricmp( token, "modelScale" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ scale = atof( token );
+
+ if( scale < 0.0f )
+ scale = 0.0f;
+
+ bc->modelScale = scale;
+
+ defined |= MODELSCALE;
+ continue;
+ }
+ else if( !Q_stricmp( token, "mins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ bc->mins[ i ] = atof( token );
+ }
+
+ defined |= MINS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "maxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ bc->maxs[ i ] = atof( token );
+ }
+
+ defined |= MAXS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "zOffset" ) )
+ {
+ float offset;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ offset = atof( token );
+
+ bc->zOffset = offset;
+
+ defined |= ZOFFSET;
+ continue;
+ }
+
+
+ Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
+ 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_InitBuildableConfigs
+===============
+*/
+void BG_InitBuildableConfigs( void )
+{
+ int i;
+ buildableConfig_t *bc;
+
+ for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ )
+ {
+ bc = BG_BuildableConfig( i );
+ Com_Memset( bc, 0, sizeof( buildableConfig_t ) );
+
+ BG_ParseBuildableFile( va( "configs/buildables/%s.cfg",
+ BG_Buildable( i )->name ), bc );
+ }
+}
+
+//CLASSES
+static const classAttributes_t bg_classList[ ] =
+{
+ {
+ PCL_NONE, //int classnum;
+ "spectator", //char *className;
+ "Observer mode",
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ 0, //int health;
+ 0.0f, //float fallDamage;
+ 0.0f, //float regenRate;
+ 0, //int abilities;
+ WP_NONE, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.000f, //float bob;
+ 1.0f, //float bobCycle;
+ 0, //int steptime;
+ 800, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 270.0f, //float jumpMagnitude;
+ 1.0f, //float knockbackScale;
+ { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ 0, //int cost;
+ 0, //int value;
+ },
+ {
+ PCL_ALIEN_BUILDER0, //int classnum;
+ "builder", //char *className;
+ "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.0f, //float fallDamage;
+ ABUILDER_REGEN, //float regenRate;
+ SCA_TAKESFALLDAMAGE|SCA_FOVWARPS|SCA_ALIENSENSE,//int abilities;
+ WP_ABUILD, //weapon_t startWeapon
+ 95.0f, //float buildDist;
+ 110, //int fov;
+ 0.001f, //float bob;
+ 2.0f, //float bobCycle;
+ 150, //int steptime;
+ ABUILDER_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 195.0f, //float jumpMagnitude;
+ 1.0f, //float knockbackScale;
+ { PCL_ALIEN_BUILDER0_UPG, PCL_ALIEN_LEVEL0, PCL_NONE }, //int children[ 3 ];
+ ABUILDER_COST, //int cost;
+ ABUILDER_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_BUILDER0_UPG, //int classnum;
+ "builderupg", //char *classname;
+ "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, //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;
+ 100, //int steptime;
+ ABUILDER_UPG_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 270.0f, //float jumpMagnitude;
+ 1.0f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL0, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ ABUILDER_UPG_COST, //int cost;
+ ABUILDER_UPG_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL0, //int classnum;
+ "level0", //char *classname;
+ "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, //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;
+ 25, //int steptime;
+ LEVEL0_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 400.0f, //float stopSpeed;
+ 250.0f, //float jumpMagnitude;
+ 2.0f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL0_UPG, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL0_COST, //int cost;
+ LEVEL0_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL0_UPG, //int classnum;
+ "level0upg", //char *classname;
+ "In addition to the basic Dretch abilities, the Advanced "
+ "Dretch has the ability to pounce and spread infections. "
+ "Advanced Dretch can also damage defensive structures.",
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL0_UPG_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ LEVEL0_UPG_REGEN, //float regenRate;
+ SCA_WALLCLIMBER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ WP_ALEVEL0_UPG, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 140, //int fov;
+ 0.0f, //float bob;
+ 2.5f, //float bobCycle;
+ 25, //int steptime;
+ LEVEL0_UPG_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 400.0f, //float stopSpeed;
+ 250.0f, //float jumpMagnitude;
+ 2.0f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL1, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL0_UPG_COST, //int cost;
+ LEVEL0_UPG_VALUE //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL1, //int classnum;
+ "level1", //char *classname;
+ "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."
+ "It has an Acid Bomb in his Butt wich can be used as a grenade.",
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL1_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ 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;
+ 60, //int steptime;
+ LEVEL1_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 300.0f, //float stopSpeed;
+ 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_LEVEL1_UPG, //int classnum;
+ "level1upg", //char *classname;
+ "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."
+ "It becomes invisible if stays still and has full health."
+ "It will become visible once Overmind is dead or it has < full health."
+ "It has an (powerful) Acid Bomb in his Butt wich can be used as a grenade.",
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL1_UPG_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ 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;
+ 60, //int steptime;
+ LEVEL1_UPG_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 300.0f, //float stopSpeed;
+ 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;
+ "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, //float regenRate;
+ SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE|SCA_WALLCLIMBER, //int abilities;
+ WP_ALEVEL2, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.001f, //float bob;
+ 1.5f, //float bobCycle;
+ 80, //int steptime;
+ LEVEL2_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 3.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 380.0f, //float jumpMagnitude;
+ 0.8f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL5, PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL2_UPG }, //int children[ 3 ];
+ LEVEL2_COST, //int cost;
+ LEVEL2_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL2_UPG, //int classnum;
+ "level2upg", //char *classname;
+ "The Advanced Marauder has all the abilities of the basic Marauder "
+ "with the addition of an area effect electric shock attack. "
+ "It also has 3 barbs which may be used to attack humans "
+ "from a distance.",
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL2_UPG_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ LEVEL2_UPG_REGEN, //float regenRate;
+ SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE|SCA_WALLCLIMBER, //int abilities;
+ WP_ALEVEL2_UPG, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.001f, //float bob;
+ 1.5f, //float bobCycle;
+ 80, //int steptime;
+ LEVEL2_UPG_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 3.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 380.0f, //float jumpMagnitude;
+ 0.7f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL5, PCL_ALIEN_LEVEL3, PCL_NONE }, //int children[ 3 ];
+ LEVEL2_UPG_COST, //int cost;
+ LEVEL2_UPG_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL5, //int classnum;
+ "level5", //char *classname;
+ "The Hummel can fly by pressing run / walk button"
+ "or bind a button with /bind BUTTON +speed /"
+ "set a key in Options/Controls/HummelFly",
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL5_UPG_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ LEVEL5_UPG_REGEN, //float regenRate;
+ SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE|SCA_WALLCLIMBER, //int abilities;
+ WP_ALEVEL5, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.001f, //float bob;
+ 1.5f, //float bobCycle;
+ 80, //int steptime;
+ LEVEL5_UPG_SPEED, //float speed;
+ 9.0f, //float acceleration;
+ 5.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 90.0f, //float stopSpeed;
+ 250.0f, //float jumpMagnitude;
+ 0.7f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL3_UPG, PCL_NONE }, //int children[ 3 ];
+ LEVEL5_UPG_COST, //int cost;
+ LEVEL5_UPG_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL3, //int classnum;
+ "level3", //char *classname;
+ "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, //float regenRate;
+ SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ WP_ALEVEL3, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.0005f, //float bob;
+ 1.3f, //float bobCycle;
+ 90, //int steptime;
+ LEVEL3_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 200.0f, //float stopSpeed;
+ 270.0f, //float jumpMagnitude;
+ 0.3f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL4, PCL_ALIEN_LEVEL3_UPG, PCL_NONE }, //int children[ 3 ];
+ LEVEL3_COST, //int cost;
+ LEVEL3_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL3_UPG, //int classnum;
+ "level3upg", //char *classname;
+ "In addition to the basic Dragoon abilities, the Advanced "
+ "Dragoon has 3 barbs which may be used to attack humans "
+ "from a distance and it has a higher jump high.",
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ LEVEL3_UPG_HEALTH, //int health;
+ 0.0f, //float fallDamage;
+ LEVEL3_UPG_REGEN, //float regenRate;
+ SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ WP_ALEVEL3_UPG, //weapon_t startWeapon
+ 0.0f, //float buildDist;
+ 90, //int fov;
+ 0.0005f, //float bob;
+ 1.3f, //float bobCycle;
+ 90, //int steptime;
+ LEVEL3_UPG_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 200.0f, //float stopSpeed;
+ 270.0f, //float jumpMagnitude;
+ 0.2f, //float knockbackScale;
+ { PCL_ALIEN_LEVEL4, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL3_UPG_COST, //int cost;
+ LEVEL3_UPG_VALUE, //int value;
+ },
+ {
+ PCL_ALIEN_LEVEL4, //int classnum;
+ "level4", //char *classname;
+ "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, //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;
+ 100, //int steptime;
+ LEVEL4_SPEED, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 170.0f, //float jumpMagnitude;
+ 0.1f, //float knockbackScale;
+ { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL4_COST, //int cost;
+ LEVEL4_VALUE, //int value;
+ },
+ {
+ PCL_HUMAN, //int classnum;
+ "human_base", //char *classname;
+ "",
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ 100, //int health;
+ 1.0f, //float fallDamage;
+ 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;
+ 100, //int steptime;
+ 1.0f, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 220.0f, //float jumpMagnitude;
+ 1.0f, //float knockbackScale;
+ { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ 0, //int cost;
+ ALIEN_CREDITS_PER_KILL, //int value;
+ },
+ {
+ PCL_HUMAN_BSUIT, //int classnum;
+ "human_bsuit", //char *classname;
+ "",
+ ( 1 << S3 ), //int stages
+ 100, //int health;
+ 1.0f, //float fallDamage;
+ 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;
+ 100, //int steptime;
+ 1.0f, //float speed;
+ 10.0f, //float acceleration;
+ 1.0f, //float airAcceleration;
+ 6.0f, //float friction;
+ 100.0f, //float stopSpeed;
+ 220.0f, //float jumpMagnitude;
+ 1.0f, //float knockbackScale;
+ { PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ 0, //int cost;
+ ALIEN_CREDITS_PER_KILL, //int value;
+ }
+};
+
+int bg_numClasses = sizeof( bg_classList ) / sizeof( bg_classList[ 0 ] );
+static const classAttributes_t nullClass = { 0 };
+
+/*
+==============
+BG_ClassByName
+==============
+*/
+const classAttributes_t *BG_ClassByName( const char *name )
+{
+ int i;
+
+ for( i = 0; i < bg_numClasses; i++ )
+ {
+ if( !Q_stricmp( bg_classList[ i ].name, name ) )
+ return &bg_classList[ i ];
+ }
+ return &nullClass;
+}
+
+/*
+==============
+BG_Class
+==============
+*/
+const classAttributes_t *BG_Class( class_t class )
+{
+ return ( class >= PCL_NONE && class < PCL_NUM_CLASSES ) ?
+ &bg_classList[ class ] : &nullClass;
+}
+
+/*
+==============
+BG_ClassAllowedInStage
+==============
+*/
+qboolean BG_ClassAllowedInStage( class_t class,
+ stage_t stage )
+{
+ int stages = BG_Class( class )->stages;
+
+ return stages & ( 1 << stage );
+}
+
+static classConfig_t bg_classConfigList[ PCL_NUM_CLASSES ];
+/*
+==============
+BG_ClassConfig
+==============
+*/
+classConfig_t *BG_ClassConfig( class_t class )
+{
+ return &bg_classConfigList[ class ];
+}
+
+/*
+==============
+BG_ClassBoundingBox
+==============
+*/
+void BG_ClassBoundingBox( class_t class,
+ vec3_t mins, vec3_t maxs,
+ vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs )
+{
+ classConfig_t *classConfig = BG_ClassConfig( class );
+
+ if( mins != NULL )
+ VectorCopy( classConfig->mins, mins );
+
+ if( maxs != NULL )
+ VectorCopy( classConfig->maxs, maxs );
+
+ if( cmaxs != NULL )
+ VectorCopy( classConfig->crouchMaxs, cmaxs );
+
+ if( dmins != NULL )
+ VectorCopy( classConfig->deadMins, dmins );
+
+ if( dmaxs != NULL )
+ VectorCopy( classConfig->deadMaxs, dmaxs );
+}
+
+/*
+==============
+BG_ClassHasAbility
+==============
+*/
+qboolean BG_ClassHasAbility( class_t class, int ability )
+{
+ int abilities = BG_Class( class )->abilities;
+ return abilities & ability;
+}
+
+/*
+==============
+BG_ClassCanEvolveFromTo
+==============
+*/
+int BG_ClassCanEvolveFromTo( class_t fclass,
+ class_t tclass,
+ int credits, int stage,
+ int cost )
+{
+ int i, j, best, value;
+
+ if( credits < cost || fclass == PCL_NONE || tclass == PCL_NONE ||
+ fclass == tclass )
+ return -1;
+
+ for( i = 0; i < bg_numClasses; i++ )
+
+ {
+ if( bg_classList[ i ].number != fclass )
+ continue;
+
+ 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;
+
+ 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 );
+
+ 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_AlienCanEvolve
+==============
+*/
+qboolean BG_AlienCanEvolve( class_t class, int credits, int stage )
+{
+ int i, j, tclass;
+
+ for( i = 0; i < bg_numClasses; i++ )
+ {
+ if( bg_classList[ i ].number != class )
+ continue;
+
+ for( j = 0; j < 3; j++ )
+ {
+ 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;
+ }
+ return qfalse;
+ }
+ Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_AlienCanEvolve\n" );
+ return qfalse;
+}
+
+/*
+======================
+BG_ParseClassFile
+
+Parses a configuration file describing a class
+======================
+*/
+static qboolean BG_ParseClassFile( const char *filename, classConfig_t *cc )
+{
+ char *text_p;
+ int i;
+ int len;
+ char *token;
+ 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 );
+ if( len < 0 )
+ return qfalse;
+
+ if( len == 0 || len >= sizeof( text ) - 1 )
+ {
+ trap_FS_FCloseFile( f );
+ Com_Printf( S_COLOR_RED "ERROR: Class file %s is %s\n", filename,
+ len == 0 ? "empty" : "too long" );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read optional parameters
+ while( 1 )
+ {
+ token = COM_Parse( &text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "" ) )
+ break;
+
+ if( !Q_stricmp( token, "model" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cc->modelName, token, sizeof( cc->modelName ) );
+
+ defined |= MODEL;
+ continue;
+ }
+ else if( !Q_stricmp( token, "skin" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cc->skinName, token, sizeof( cc->skinName ) );
+
+ defined |= SKIN;
+ continue;
+ }
+ else if( !Q_stricmp( token, "hud" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cc->hudName, token, sizeof( cc->hudName ) );
+
+ defined |= HUD;
+ continue;
+ }
+ else if( !Q_stricmp( token, "modelScale" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ scale = atof( token );
+
+ if( scale < 0.0f )
+ scale = 0.0f;
+
+ cc->modelScale = scale;
+
+ defined |= MODELSCALE;
+ continue;
+ }
+ else if( !Q_stricmp( token, "shadowScale" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ scale = atof( token );
+
+ if( scale < 0.0f )
+ scale = 0.0f;
+
+ cc->shadowScale = scale;
+
+ defined |= SHADOWSCALE;
+ continue;
+ }
+ else if( !Q_stricmp( token, "mins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cc->mins[ i ] = atof( token );
+ }
+
+ defined |= MINS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "maxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cc->maxs[ i ] = atof( token );
+ }
+
+ defined |= MAXS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "deadMins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cc->deadMins[ i ] = atof( token );
+ }
+
+ defined |= DEADMINS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "deadMaxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cc->deadMaxs[ i ] = atof( token );
+ }
+
+ defined |= DEADMAXS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "crouchMaxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cc->crouchMaxs[ i ] = atof( token );
+ }
+
+ defined |= CROUCHMAXS;
+ continue;
+ }
+ else if( !Q_stricmp( token, "viewheight" ) )
+ {
+ token = COM_Parse( &text_p );
+ cc->viewheight = atoi( token );
+ defined |= VIEWHEIGHT;
+ continue;
+ }
+ else if( !Q_stricmp( token, "crouchViewheight" ) )
+ {
+ token = COM_Parse( &text_p );
+ cc->crouchViewheight = atoi( token );
+ defined |= CVIEWHEIGHT;
+ continue;
+ }
+ else if( !Q_stricmp( token, "zOffset" ) )
+ {
+ float offset;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ offset = atof( token );
+
+ cc->zOffset = offset;
+
+ defined |= ZOFFSET;
+ continue;
+ }
+ else if( !Q_stricmp( token, "name" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ 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_InitClassConfigs
+===============
+*/
+void BG_InitClassConfigs( void )
+{
+ int i;
+ classConfig_t *cc;
+
+ for( i = PCL_NONE; i < PCL_NUM_CLASSES; i++ )
+ {
+ cc = BG_ClassConfig( i );
+
+ BG_ParseClassFile( va( "configs/classes/%s.cfg",
+ BG_Class( i )->name ), cc );
+ }
+}
+
+static const weaponAttributes_t bg_weapons[ ] =
+{
+ {
+ WP_ALEVEL0, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level0", //char *weaponName;
+ "Bite", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL0_BITE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL0_BITE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL0_UPG, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level0upg", //char *weaponName;
+ "Bite Upgrade", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL0_BITE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL0_BITE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL1, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level1", //char *weaponName;
+ "Claws", //char *humanName;
+ "",
+ 1, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL1_CLAW_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ ABOMB2_REPEAT, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL1_CLAW_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL1_UPG, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level1upg", //char *weaponName;
+ "Claws Upgrade", //char *humanName;
+ "",
+ 1, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL1_CLAW_U_REPEAT, //int repeatRate1;
+ LEVEL1_PCLOUD_REPEAT, //int repeatRate2;
+ ABOMB_REPEAT, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL1_CLAW_U_K_SCALE,//float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_ALIENS //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;
+ "Claws", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL2_CLAW_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL2_CLAW_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL2_UPG, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level2upg", //char *weaponName;
+ "Zap", //char *humanName;
+ "",
+ 3, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL2_CLAW_U_REPEAT, //int repeatRate1;
+ LEVEL2_AREAZAP_REPEAT,//int repeatRate2;
+ LEVEL2_BOUNCEBALL_REPEAT,//int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL2_CLAW_U_K_SCALE,//float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL5, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level5", //char *weaponName;
+ "prickles", //char *humanName;
+ "",
+ 10, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL5_CLAW_U_REPEAT, //int repeatRate1;
+ LEVEL5_POUNCE_REPEAT, //int repeatRate2;
+ LEVEL5_PRICKLES_REPEAT, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL5_CLAW_U_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qtrue, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL3, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level3", //char *weaponName;
+ "Pounce", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL3_CLAW_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL3_CLAW_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qtrue, //qboolean canZoom;
+ 100.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL3_UPG, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level3upg", //char *weaponName;
+ "Pounce (upgrade)", //char *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;
+ qtrue, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_ALEVEL4, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "level4", //char *weaponName;
+ "Charge", //char *humanName;
+ "",
+ 3, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ LEVEL4_CLAW_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ LEVEL4_FIREBREATHREPEAT, //int repeatRate3;
+ 0, //int reloadTime;
+ LEVEL4_CLAW_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+
+ {
+ WP_BLASTER, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ 0, //int slots;
+ "blaster", //char *weaponName;
+ "[yefarms]Blaster", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ BLASTER_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ BLASTER_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_MACHINEGUN, //int weaponNum;
+ RIFLE_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "rifle", //char *weaponName;
+ "[yefarms]Rifle", //char *humanName;
+ "Basic weapon. Cased projectile weapon, with a slow clip based "
+ "reload system & a fast 2nd mode.",
+ RIFLE_CLIPSIZE, //int maxAmmo;
+ RIFLE_MAXCLIPS, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ RIFLE_REPEAT, //int repeatRate1;
+ RIFLE_REPEAT2, //int repeatRate2;
+ 0, //int repeatRate3;
+ RIFLE_RELOAD, //int reloadTime;
+ RIFLE_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_PAIN_SAW, //int weaponNum;
+ PAINSAW_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "psaw", //char *weaponName;
+ "[yefarms]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. It has a blade mode for secondary fire",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ PAINSAW_REPEAT, //int repeatRate1;
+ PAINSAW_REPEAT2, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ PAINSAW_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_SHOTGUN, //int weaponNum;
+ SHOTGUN_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "shotgun", //char *weaponName;
+ "[yefarms]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;
+ SHOTGUN_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ SHOTGUN_RELOAD, //int reloadTime;
+ SHOTGUN_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_LAS_GUN, //int weaponNum;
+ LASGUN_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "lgun", //char *weaponName;
+ "[yefarms]Las Gun", //char *humanName;
+ "Slightly more powerful than the basic rifle, rapidly fires "
+ "small packets of energy.",
+ LASGUN_AMMO, //int maxAmmo;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ LASGUN_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ LASGUN_RELOAD, //int reloadTime;
+ LASGUN_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_MASS_DRIVER, //int weaponNum;
+ MDRIVER_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "mdriver", //char *weaponName;
+ "[yefarms]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. The secondary fire mode is "
+ "triggered with a combo of [primary attack] and [activate upgrade]. "
+ "It needs a full clip and fires a target seeking ball-lightning "
+ "towarads the enemy. It is available at S3",
+ MDRIVER_CLIPSIZE, //int maxAmmo;
+ MDRIVER_MAXCLIPS, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ MDRIVER_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ MDRIVER_REPEAT2, //int repeatRate3;
+ MDRIVER_RELOAD, //int reloadTime;
+ MDRIVER_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qtrue, //qboolean canZoom;
+ 25.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_CHAINGUN, //int weaponNum;
+ CHAINGUN_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "chaingun", //char *weaponName;
+ "[yefarms]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;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ CHAINGUN_REPEAT, //int repeatRate1;
+ CHAINGUN_REPEAT2, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ CHAINGUN_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_FLAMER, //int weaponNum;
+ FLAMER_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "flamer", //char *weaponName;
+ "[yefarms]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.",
+ 150, //int maxAmmo;
+ 1, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ FLAMER_REPEAT, //int repeatRate1;
+ FLAMER_SECONDARY_REPEAT, //int repeatRate2;
+ FLAMER_REPEAT, //int repeatRate3;
+ 3000, //int reloadTime;
+ FLAMER_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_PULSE_RIFLE, //int weaponNum;
+ PRIFLE_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "prifle", //char *weaponName;
+ "[yefarms]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;
+ PRIFLE_SECONDARY_REPEAT, //int repeatRate2;
+ 0, //int repeatRate3;
+ PRIFLE_RELOAD, //int reloadTime;
+ PRIFLE_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_LUCIFER_CANNON, //int weaponNum;
+ LCANNON_PRICE, //int price;
+ ( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "lcannon", //char *weaponName;
+ "[yefarms]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;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ LCANNON_REPEAT, //int repeatRate1;
+ LCANNON_SECONDARY_REPEAT, //int repeatRate2;
+ 0, //int repeatRate3;
+ LCANNON_RELOAD, //int reloadTime;
+ LCANNON_K_SCALE, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ 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 *humanName;
+ "",
+ 1, //int maxAmmo;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ GRENADE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ GRENADE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_SMOKE, //int weaponNum;
+ SMOKE_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "smoke", //char *weaponName;
+ "Smoke", //char *weaponHumanName;
+ "",
+ 1, //int maxAmmo;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ SMOKE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ SMOKE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //WUTeam_t team;
+ },
+ {
+ WP_MINE, //int weaponNum;
+ MINE_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "mine", //char *weaponName;
+ "Mine", //char *weaponHumanName;
+ "",
+ 1, //int maxAmmo;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ MINE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ MINE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //WUTeam_t team;
+ },
+ {
+ WP_LOCKBLOB_LAUNCHER, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "lockblob", //char *weaponName;
+ "Lock Blob", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 500, //int repeatRate1;
+ 500, //int repeatRate2;
+ 500, //int repeatRate3;
+ 0, //int reloadTime;
+ LOCKBLOB_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_HIVE, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "hive", //char *weaponName;
+ "Hive", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 500, //int repeatRate1;
+ 500, //int repeatRate2;
+ 500, //int repeatRate3;
+ 0, //int reloadTime;
+ HIVE_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_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 *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ 500, //int repeatRate1;
+ 500, //int repeatRate2;
+ 500, //int repeatRate3;
+ 0, //int reloadTime;
+ TESLAGEN_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_MGTURRET, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "mgturret", //char *weaponName;
+ "Machinegun Turret", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 0, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ MGTURRET_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_MGTURRET2, //int weaponNum;
+ 0, //int price;
+ ( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "mgturret2", //char *weaponName;
+ "Machinegun Turret2", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 0, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ MGTURRET2_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qfalse, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ WP_ABUILD, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "abuild", //char *weaponName;
+ "Alien build weapon", //char *humanName;
+ "",
+ 0, //int maxAmmo;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ ABUILDER_BUILD_REPEAT,//int repeatRate1;
+ ABUILDER_CLAW_REPEAT, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ ABUILDER_CLAW_K_SCALE,//float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_ALIENS //team_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 *humanName;
+ "",
+ 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;
+ TEAM_ALIENS //team_t team;
+ },
+ {
+ WP_HBUILD, //int weaponNum;
+ HBUILD_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "ckit", //char *weaponName;
+ "[yetool]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;
+ HBUILD_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ 0.0f, //float knockbackScale;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qfalse, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ }
+};
+
+int bg_numWeapons = sizeof( bg_weapons ) / sizeof( bg_weapons[ 0 ] );
+static const weaponAttributes_t nullWeapon = { 0 };
+
+/*
+==============
+BG_WeaponByName
+==============
+*/
+const weaponAttributes_t *BG_WeaponByName( const char *name )
+{
+ int i;
+
+ for( i = 0; i < bg_numWeapons; i++ )
+ {
+ if( !Q_stricmp( bg_weapons[ i ].name, name ) )
+ {
+ return &bg_weapons[ i ];
+ }
+ }
+ return &nullWeapon;
+}
+
+/*
+==============
+BG_Weapon
+==============
+*/
+const weaponAttributes_t *BG_Weapon( weapon_t weapon )
+{
+ return ( weapon > WP_NONE && weapon < WP_NUM_WEAPONS ) ?
+ &bg_weapons[ weapon - 1 ] : &nullWeapon;
+}
+
+/*
+==============
+BG_WeaponAllowedInStage
+==============
+*/
+qboolean BG_WeaponAllowedInStage( weapon_t weapon, stage_t stage )
+{
+ int stages = BG_Weapon( weapon )->stages;
+
+ return stages & ( 1 << stage );
+}
+
+static const upgradeAttributes_t bg_upgrades[ ] =
+{
+ {
+ UP_LIGHTARMOUR, //int upgradeNum;
+ LIGHTARMOUR_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_TORSO|SLOT_ARMS|SLOT_LEGS, //int slots;
+ "larmour", //char *upgradeName;
+ "[yeshield]Light Armour", //char *humanName;
+ "Protective armour that helps to defend against light alien melee "
+ "attacks.",
+ "icons/iconu_larmour",
+ qtrue, //qboolean purchasable
+ qfalse, //qboolean usable
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_HELMET, //int upgradeNum;
+ HELMET_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_HEAD, //int slots;
+ "helmet", //char *upgradeName;
+ "[yeshield]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
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_MEDKIT, //int upgradeNum;
+ MEDKIT_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "medkit", //char *upgradeName;
+ "[yemed]Medkit", //char *humanName;
+ "Basic health kit. ",
+ "icons/iconu_atoxin",
+ qtrue, //qboolean purchasable
+ qtrue, //qboolean usable
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_BIOKIT, //int upgradeNum;
+ BIOKIT_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "biokit", //char *upgradeName;
+ "[yebiok]Biokit", //char *humanName;
+ "The Biokit is a biological enhancement system that heals "
+ "wounds, improves stamina, and provides some resistance to "
+ "alien infection.",
+ "icons/iconu_biokit",
+ qtrue, //qboolean purchasable
+ qfalse, //qboolean usable
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_CLOAK, //int upgradeNum;
+ CLOAK_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ),//int stages
+ SLOT_NONE, //int slots;
+ "cloak", //char *upgradeName;
+ "[yecloa]Cloak", //char *humanName;
+ "Invisibility cloak that can be used to sneak up on aliens "
+ "without being seen. The cloak lasts for 30 seconds once it "
+ "is activated. Back-mounted battery pack and jet pack will "
+ "stay visible.",
+ "icons/iconu_cloak",
+ qtrue, //qboolean purchasable
+ qtrue, //qboolean usable
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_BATTPACK, //int upgradeNum;
+ BATTPACK_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_BACKPACK, //int slots;
+ "battpack", //char *upgradeName;
+ "[yebat]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
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_JETPACK, //int upgradeNum;
+ JETPACK_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_BACKPACK, //int slots;
+ "jetpack", //char *upgradeName;
+ "[yejet]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
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_BATTLESUIT, //int upgradeNum;
+ BSUIT_PRICE, //int price;
+ ( 1 << S3 ), //int stages
+ SLOT_HEAD|SLOT_TORSO|SLOT_ARMS|SLOT_LEGS|SLOT_BACKPACK, //int slots;
+ "bsuit", //char *upgradeName;
+ "[yeshield]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
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_GRENADE, //int upgradeNum;
+ GRENADE_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ),//int stages
+ SLOT_NONE, //int slots;
+ "gren", //char *upgradeName;
+ "[yenade]Explosive 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
+ TEAM_HUMANS //team_t team;
+ },
+ {
+ UP_MINE, //int upgradeNum;
+ MINE_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ),//int stages
+ SLOT_NONE, //int slots;
+ "min", //char *upgradeName;
+ "[yenade]Mine", //char *upgradeHumanName;
+ "",
+ 0,
+ qtrue, //qboolean purchasable
+ qtrue, //qboolean usable
+ TEAM_HUMANS //WUTeam_t team;
+ },
+ {
+ UP_SMOKE, //int upgradeNum;
+ SMOKE_PRICE, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),//int stages
+ SLOT_NONE, //int slots;
+ "smo", //char *upgradeName;
+ "[yenade]Smoke Grenade", //char *upgradeHumanName;
+ "",
+ 0,
+ qtrue, //qboolean purchasable
+ qtrue, //qboolean usable
+ TEAM_HUMANS //WUTeam_t team;
+ },
+ {
+ UP_AMMO, //int upgradeNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "ammo", //char *upgradeName;
+ "[yeammo]Ammunition", //char *humanName;
+ "Ammunition for the currently held weapon.",
+ 0,
+ qtrue, //qboolean purchasable
+ qfalse, //qboolean usable
+ TEAM_HUMANS //team_t team;
+ }
+};
+
+int bg_numUpgrades = sizeof( bg_upgrades ) / sizeof( bg_upgrades[ 0 ] );
+static const upgradeAttributes_t nullUpgrade = { 0 };
+
+/*
+==============
+BG_UpgradeByName
+==============
+*/
+const upgradeAttributes_t *BG_UpgradeByName( const char *name )
+{
+ int i;
+
+ for( i = 0; i < bg_numUpgrades; i++ )
+ {
+ if( !Q_stricmp( bg_upgrades[ i ].name, name ) )
+ {
+ return &bg_upgrades[ i ];
+ }
+ }
+ return &nullUpgrade;
+}
+
+/*
+==============
+BG_Upgrade
+==============
+*/
+const upgradeAttributes_t *BG_Upgrade( upgrade_t upgrade )
+{
+ return ( upgrade > UP_NONE && upgrade < UP_NUM_UPGRADES ) ?
+ &bg_upgrades[ upgrade - 1 ] : &nullUpgrade;
+}
+
+/*
+==============
+BG_UpgradeAllowedInStage
+==============
+*/
+qboolean BG_UpgradeAllowedInStage( upgrade_t upgrade, stage_t stage )
+{
+ int stages = BG_Upgrade( upgrade )->stages;
+
+ return stages & ( 1 << stage );
+}
+
+/*
+================
+BG_EvaluateTrajectory
+================
+*/
+void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result )
+{
+ float deltaTime;
+ float phase;
+
+ switch( tr->trType )
+ {
+ case TR_STATIONARY:
+ case TR_INTERPOLATE:
+ VectorCopy( tr->trBase, result );
+ break;
+
+ case TR_LINEAR:
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
+ break;
+
+ case TR_SINE:
+ deltaTime = ( atTime - tr->trTime ) / (float)tr->trDuration;
+ phase = sin( deltaTime * M_PI * 2 );
+ VectorMA( tr->trBase, phase, tr->trDelta, result );
+ break;
+
+ case TR_LINEAR_STOP:
+ if( atTime > tr->trTime + tr->trDuration )
+ atTime = tr->trTime + tr->trDuration;
+
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ if( deltaTime < 0 )
+ deltaTime = 0;
+
+ VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
+ break;
+
+ case TR_GRAVITY:
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
+ result[ 2 ] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity...
+ break;
+
+ case TR_BUOYANCY:
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
+ result[ 2 ] += 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity...
+ break;
+
+ default:
+ Com_Error( ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime );
+ break;
+ }
+}
+
+/*
+================
+BG_EvaluateTrajectoryDelta
+For determining velocity at a given time
+================
+*/
+void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result )
+{
+ float deltaTime;
+ float phase;
+
+ switch( tr->trType )
+ {
+ case TR_STATIONARY:
+ case TR_INTERPOLATE:
+ VectorClear( result );
+ break;
+
+ case TR_LINEAR:
+ VectorCopy( tr->trDelta, result );
+ break;
+
+ case TR_SINE:
+ deltaTime = ( atTime - tr->trTime ) / (float)tr->trDuration;
+ phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos
+ phase *= 0.5;
+ VectorScale( tr->trDelta, phase, result );
+ break;
+
+ case TR_LINEAR_STOP:
+ if( atTime > tr->trTime + tr->trDuration )
+ {
+ VectorClear( result );
+ return;
+ }
+ VectorCopy( tr->trDelta, result );
+ break;
+
+ case TR_GRAVITY:
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ VectorCopy( tr->trDelta, result );
+ result[ 2 ] -= DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity...
+ break;
+
+ case TR_BUOYANCY:
+ deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
+ VectorCopy( tr->trDelta, result );
+ result[ 2 ] += DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity...
+ break;
+
+ default:
+ Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime );
+ break;
+ }
+}
+
+char *eventnames[ ] =
+{
+ "EV_NONE",
+ "EV_FOOTSTEP",
+ "EV_FOOTSTEP_METAL",
+ "EV_FOOTSTEP_SQUELCH",
+ "EV_FOOTSPLASH",
+ "EV_FOOTWADE",
+ "EV_SWIM",
+ "EV_STEP_4",
+ "EV_STEP_8",
+ "EV_STEP_12",
+ "EV_STEP_16",
+ "EV_STEPDN_4",
+ "EV_STEPDN_8",
+ "EV_STEPDN_12",
+ "EV_STEPDN_16",
+ "EV_FALL_SHORT",
+ "EV_FALL_MEDIUM",
+ "EV_FALL_FAR",
+ "EV_FALLING",
+ "EV_JUMP",
+ "EV_AIRPOUNCE",
+ "EV_WATER_TOUCH", // foot touches
+ "EV_WATER_LEAVE", // foot leaves
+ "EV_WATER_UNDER", // head touches
+ "EV_WATER_CLEAR", // head leaves
+ "EV_NOAMMO",
+ "EV_CHANGE_WEAPON",
+ "EV_FIRE_WEAPON",
+ "EV_FIRE_WEAPON2",
+ "EV_FIRE_WEAPON3",
+ "EV_PLAYER_RESPAWN", // for fovwarp effects
+ "EV_PLAYER_TELEPORT_IN",
+ "EV_PLAYER_TELEPORT_OUT",
+ "EV_GRENADE_BOUNCE", // eventParm will be the soundindex
+ "EV_MINE_BOUNCE", // eventParm will be the soundindex
+ "EV_GENERAL_SOUND",
+ "EV_GLOBAL_SOUND", // no attenuation
+ "EV_BULLET_HIT_FLESH",
+ "EV_BULLET_HIT_WALL",
+ "EV_SHOTGUN",
+ "EV_MASS_DRIVER",
+ "EV_MISSILE_HIT",
+ "EV_MISSILE_MISS",
+ "EV_MISSILE_MISS_METAL",
+ "EV_TESLATRAIL",
+ "EV_SLIMETRAIL",
+ "EV_BULLET", // otherEntity is the shooter
+ "EV_LEV1_GRAB",
+ "EV_LEV4_TRAMPLE_PREPARE",
+ "EV_LEV4_TRAMPLE_START",
+ "EV_PAIN",
+ "EV_DEATH1",
+ "EV_DEATH2",
+ "EV_DEATH3",
+ "EV_OBITUARY",
+ "EV_GIB_PLAYER", // gib a previously living player
+ "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",
+ "EV_ALIEN_SLIME",
+ "EV_FORCE_FIELD",
+ "EV_MEDKIT_USED",
+ "EV_ALIEN_EVOLVE",
+ "EV_ALIEN_EVOLVE_FAILED",
+ "EV_DEBUG_LINE",
+ "EV_STOPLOOPINGSOUND",
+ "EV_TAUNT",
+ "EV_HUMMEL",
+ "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_MGTURRET_SPINUP", // trigger a sound
+ "EV_RPTUSE_SOUND", // trigger a sound
+ "EV_LEV2_ZAP",
+ "EV_ACIDBOMB_BOUNCE"
+};
+
+/*
+===============
+BG_EventName
+===============
+*/
+const char *BG_EventName( int num )
+{
+ if( num < 0 || num >= sizeof( eventnames ) / sizeof( char * ) )
+ return "UNKNOWN";
+
+ return eventnames[ num ];
+}
+
+/*
+===============
+BG_AddPredictableEventToPlayerstate
+
+Handles the sequence numbers
+===============
+*/
+
+void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
+
+void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps )
+{
+#ifdef _DEBUG
+ {
+ char buf[ 256 ];
+ trap_Cvar_VariableStringBuffer( "showevents", buf, sizeof( buf ) );
+
+ if( atof( buf ) != 0 )
+ {
+#ifdef GAME
+ Com_Printf( " game event svt %5d -> %5d: num = %20s parm %d\n",
+ 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,
+ BG_EventName( newEvent ), eventParm );
+#endif
+ }
+ }
+#endif
+ ps->events[ ps->eventSequence & ( MAX_PS_EVENTS - 1 ) ] = newEvent;
+ ps->eventParms[ ps->eventSequence & ( MAX_PS_EVENTS - 1 ) ] = eventParm;
+ ps->eventSequence++;
+}
+
+
+/*
+========================
+BG_PlayerStateToEntityState
+
+This is done after each set of usercmd_t on the server,
+and after local prediction on the client
+========================
+*/
+void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap )
+{
+ int i;
+
+ if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR || ps->pm_type == PM_FREEZE )
+ s->eType = ET_INVISIBLE;
+ else if( ps->persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT )
+ s->eType = ET_INVISIBLE;
+ else
+ s->eType = ET_PLAYER;
+
+ s->number = ps->clientNum;
+
+ s->pos.trType = TR_INTERPOLATE;
+ VectorCopy( ps->origin, s->pos.trBase );
+
+ if( snap )
+ SnapVector( s->pos.trBase );
+
+ //set the trDelta for flag direction
+ VectorCopy( ps->velocity, s->pos.trDelta );
+
+ s->apos.trType = TR_INTERPOLATE;
+ VectorCopy( ps->viewangles, s->apos.trBase );
+
+ if( snap )
+ SnapVector( s->apos.trBase );
+
+ 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;
+ if( ps->stats[STAT_HEALTH] <= 0 )
+ s->eFlags |= EF_DEAD;
+ else
+ s->eFlags &= ~EF_DEAD;
+
+ if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED )
+ s->eFlags |= EF_BLOBLOCKED;
+ else
+ s->eFlags &= ~EF_BLOBLOCKED;
+
+ if( ps->externalEvent )
+ {
+ s->event = ps->externalEvent;
+ s->eventParm = ps->externalEventParm;
+ }
+ else if( ps->entityEventSequence < ps->eventSequence )
+ {
+ int seq;
+
+ if( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS )
+ ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
+
+ seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 );
+ s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
+ s->eventParm = ps->eventParms[ seq ];
+ ps->entityEventSequence++;
+ }
+
+ s->weapon = ps->weapon;
+ s->groundEntityNum = ps->groundEntityNum;
+
+ //store items held and active items in modelindex and modelindex2
+ s->modelindex = 0;
+ s->modelindex2 = 0;
+ for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
+ {
+ if( BG_InventoryContainsUpgrade( i, ps->stats ) )
+ {
+ s->modelindex |= 1 << i;
+
+ if( BG_UpgradeIsActive( i, ps->stats ) )
+ s->modelindex2 |= 1 << i;
+ }
+ }
+
+ // use misc field to store team/class info:
+ s->misc = ps->stats[ STAT_TEAM ] | ( ps->stats[ STAT_CLASS ] << 8 );
+
+ // have to get the surfNormal through somehow...
+ VectorCopy( ps->grapplePoint, s->angles2 );
+
+ s->loopSound = ps->loopSound;
+ s->generic1 = ps->generic1;
+
+ if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES )
+ s->generic1 = WPM_PRIMARY;
+
+ s->otherEntityNum = ps->otherEntityNum;
+}
+
+/*
+========================
+BG_PlayerStateToEntityStateExtraPolate
+This is done after each set of usercmd_t on the server,
+and after local prediction on the client
+========================
+*/
+void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap )
+{
+ int i;
+
+ if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR || ps->pm_type == PM_FREEZE )
+ s->eType = ET_INVISIBLE;
+ else if( ps->persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT )
+ s->eType = ET_INVISIBLE;
+ else
+ s->eType = ET_PLAYER;
+
+ s->number = ps->clientNum;
+
+ s->pos.trType = TR_LINEAR_STOP;
+ VectorCopy( ps->origin, s->pos.trBase );
+
+ if( snap )
+ SnapVector( s->pos.trBase );
+
+ // set the trDelta for flag direction and linear prediction
+ VectorCopy( ps->velocity, s->pos.trDelta );
+ // set the time for linear prediction
+ s->pos.trTime = time;
+ // set maximum extra polation time
+ s->pos.trDuration = 50; // 1000 / sv_fps (default = 20)
+
+ s->apos.trType = TR_INTERPOLATE;
+ VectorCopy( ps->viewangles, s->apos.trBase );
+ if( snap )
+ SnapVector( s->apos.trBase );
+
+ s->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;
+
+ if( ps->stats[STAT_HEALTH] <= 0 )
+ s->eFlags |= EF_DEAD;
+ else
+ s->eFlags &= ~EF_DEAD;
+
+ if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED )
+ s->eFlags |= EF_BLOBLOCKED;
+ else
+ s->eFlags &= ~EF_BLOBLOCKED;
+
+ if( ps->externalEvent )
+ {
+ s->event = ps->externalEvent;
+ s->eventParm = ps->externalEventParm;
+ }
+ else if( ps->entityEventSequence < ps->eventSequence )
+ {
+ int seq;
+
+ if( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS )
+ ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
+
+ seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 );
+ s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
+ s->eventParm = ps->eventParms[ seq ];
+ ps->entityEventSequence++;
+ }
+
+ s->weapon = ps->weapon;
+ s->groundEntityNum = ps->groundEntityNum;
+
+ //store items held and active items in modelindex and modelindex2
+ s->modelindex = 0;
+ s->modelindex2 = 0;
+
+ for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
+ {
+ if( BG_InventoryContainsUpgrade( i, ps->stats ) )
+ {
+ s->modelindex |= 1 << i;
+
+ if( BG_UpgradeIsActive( i, ps->stats ) )
+ s->modelindex2 |= 1 << i;
+ }
+ }
+
+ // use misc field to store team/class info:
+ s->misc = ps->stats[ STAT_TEAM ] | ( ps->stats[ STAT_CLASS ] << 8 );
+
+ // have to get the surfNormal through somehow...
+ VectorCopy( ps->grapplePoint, s->angles2 );
+
+ s->loopSound = ps->loopSound;
+ s->generic1 = ps->generic1;
+
+ if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES )
+ s->generic1 = WPM_PRIMARY;
+
+ s->otherEntityNum = ps->otherEntityNum;
+}
+
+/*
+========================
+BG_WeaponIsFull
+Check if a weapon has full ammo
+========================
+*/
+qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips )
+{
+ int maxAmmo, maxClips;
+
+ maxAmmo = BG_Weapon( weapon )->maxAmmo;
+ maxClips = BG_Weapon( weapon )->maxClips;
+
+ if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) )
+ maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER );
+
+
+ return ( maxAmmo == ammo ) && ( maxClips == clips );
+}
+
+/*
+========================
+BG_InventoryContainsWeapon
+Does the player hold a weapon?
+========================
+*/
+qboolean BG_InventoryContainsWeapon( int weapon, int stats[ ] )
+{
+ // humans always have a blaster
+ if( stats[ STAT_TEAM ] == TEAM_HUMANS && weapon == WP_BLASTER )
+ return qtrue;
+
+ return ( stats[ STAT_WEAPON ] == weapon );
+}
+
+/*
+========================
+BG_SlotsForInventory
+Calculate the slots used by an inventory and warn of conflicts
+========================
+*/
+int BG_SlotsForInventory( int stats[ ] )
+{
+ int i, slot, slots;
+
+ slots = BG_Weapon( stats[ STAT_WEAPON ] )->slots;
+ if( stats[ STAT_TEAM ] == TEAM_HUMANS )
+ slots |= BG_Weapon( WP_BLASTER )->slots;
+
+ for( i = UP_NONE; i < UP_NUM_UPGRADES; i++ )
+ {
+ if( BG_InventoryContainsUpgrade( i, stats ) )
+ {
+ slot = BG_Upgrade( i )->slots;
+
+ // 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 );
+ }
+
+ slots |= slot;
+ }
+ }
+ return slots;
+}
+
+/*
+========================
+BG_AddUpgradeToInventory
+Give the player an upgrade
+========================
+*/
+void BG_AddUpgradeToInventory( int item, int stats[ ] )
+{
+ stats[ STAT_ITEMS ] |= ( 1 << item );
+}
+
+/*
+========================
+BG_RemoveUpgradeFromInventory
+Take an upgrade from the player
+========================
+*/
+void BG_RemoveUpgradeFromInventory( int item, int stats[ ] )
+{
+ stats[ STAT_ITEMS ] &= ~( 1 << item );
+}
+
+/*
+========================
+BG_InventoryContainsUpgrade
+Does the player hold an upgrade?
+========================
+*/
+qboolean BG_InventoryContainsUpgrade( int item, int stats[ ] )
+{
+ return( stats[ STAT_ITEMS ] & ( 1 << item ) );
+}
+
+/*
+========================
+BG_ActivateUpgrade
+Activates an upgrade
+========================
+*/
+void BG_ActivateUpgrade( int item, int stats[ ] )
+{
+ stats[ STAT_ACTIVEITEMS ] |= ( 1 << item );
+}
+
+/*
+========================
+BG_DeactivateUpgrade
+Deactivates an upgrade
+========================
+*/
+void BG_DeactivateUpgrade( int item, int stats[ ] )
+{
+ stats[ STAT_ACTIVEITEMS ] &= ~( 1 << item );
+}
+
+/*
+========================
+BG_UpgradeIsActive
+Is this upgrade active?
+========================
+*/
+qboolean BG_UpgradeIsActive( int item, int stats[ ] )
+{
+ return( stats[ STAT_ACTIVEITEMS ] & ( 1 << item ) );
+}
+
+/*
+===============
+BG_RotateAxis
+Shared axis rotation function
+===============
+*/
+qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
+ vec3_t outAxis[ 3 ], qboolean inverse, qboolean ceiling )
+{
+ vec3_t refNormal = { 0.0f, 0.0f, 1.0f };
+ vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f };
+ vec3_t localNormal, xNormal;
+ float rotAngle;
+
+ //the grapplePoint being a surfNormal rotation Normal hack... see above :)
+ if( ceiling )
+ {
+ VectorCopy( ceilingNormal, localNormal );
+ VectorCopy( surfNormal, xNormal );
+ }
+ else
+ {
+ //cross the reference normal and the surface normal to get the rotation axis
+ VectorCopy( surfNormal, localNormal );
+ CrossProduct( localNormal, refNormal, xNormal );
+ VectorNormalize( xNormal );
+ }
+
+ //can't rotate with no rotation vector
+ if( VectorLength( xNormal ) != 0.0f )
+ {
+ rotAngle = RAD2DEG( acos( DotProduct( localNormal, refNormal ) ) );
+
+ if( inverse )
+ rotAngle = -rotAngle;
+
+ AngleNormalize180( rotAngle );
+
+ //hmmm could get away with only one rotation and some clever stuff later... but i'm lazy
+ RotatePointAroundVector( outAxis[ 0 ], xNormal, inAxis[ 0 ], -rotAngle );
+ RotatePointAroundVector( outAxis[ 1 ], xNormal, inAxis[ 1 ], -rotAngle );
+ RotatePointAroundVector( outAxis[ 2 ], xNormal, inAxis[ 2 ], -rotAngle );
+ }
+ else
+ return qfalse;
+ return qtrue;
+}
+
+/*
+===============
+BG_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
+===============
+*/
+void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
+ const vec3_t mins, const vec3_t maxs,
+ void (*trace)( trace_t *, const vec3_t, const vec3_t,
+ const vec3_t, const vec3_t, int, int ),
+ vec3_t outOrigin, vec3_t outAngles, trace_t *tr )
+{
+ vec3_t forward, entityOrigin, targetOrigin;
+ vec3_t angles, playerOrigin, playerNormal;
+ float buildDist;
+
+ BG_GetClientNormal( ps, playerNormal );
+
+ VectorCopy( ps->viewangles, angles );
+ VectorCopy( ps->origin, playerOrigin );
+ buildDist = BG_Class( ps->stats[ STAT_CLASS ] )->buildDist;
+
+ AngleVectors( angles, forward, NULL, NULL );
+ ProjectPointOnPlane( forward, forward, playerNormal );
+ VectorNormalize( forward );
+
+ VectorMA( playerOrigin, buildDist, forward, entityOrigin );
+
+ VectorCopy( entityOrigin, targetOrigin );
+
+ //so buildings can be placed facing slopes
+ VectorMA( entityOrigin, 32, playerNormal, entityOrigin );
+
+ //so buildings drop to floor
+ VectorMA( targetOrigin, -128, playerNormal, targetOrigin );
+
+ // The mask is MASK_DEADSOLID on purpose to avoid collisions with other entities
+ (*trace)( tr, entityOrigin, mins, maxs, targetOrigin, ps->clientNum, MASK_PLAYERSOLID );
+ VectorCopy( tr->endpos, entityOrigin );
+ VectorMA( entityOrigin, 0.1f, playerNormal, outOrigin );
+ vectoangles( forward, outAngles );
+}
+
+/*
+===============
+BG_GetValueOfPlayer
+Returns the credit value of a player
+===============
+*/
+int BG_GetValueOfPlayer( playerState_t *ps )
+{
+ int i, worth = 0;
+
+ worth = BG_Class( ps->stats[ STAT_CLASS ] )->value;
+
+ // Humans have worth from their equipment as well
+ if( ps->stats[ STAT_TEAM ] == TEAM_HUMANS )
+ {
+ for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
+ {
+ if( BG_InventoryContainsUpgrade( i, ps->stats ) )
+ worth += BG_Upgrade( i )->price;
+ }
+
+ for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
+ {
+ if( BG_InventoryContainsWeapon( i, ps->stats ) )
+ worth += BG_Weapon( i )->price;
+ }
+ }
+ return worth;
+}
+
+/*
+=================
+BG_PlayerCanChangeWeapon
+=================
+*/
+qboolean BG_PlayerCanChangeWeapon( playerState_t *ps )
+{
+ // Do not allow Lucifer Cannon "canceling" via weapon switch
+ if( (ps->weapon == WP_LUCIFER_CANNON || ps->weapon == WP_FLAMER) &&
+ ps->stats[ STAT_MISC ] > LCANNON_CHARGE_TIME_MIN )
+ return qfalse;
+
+ return ps->weaponTime <= 0 || ps->weaponstate != WEAPON_FIRING;
+}
+
+/*
+=================
+BG_PlayerPoisonCloudTime
+=================
+*/
+int BG_PlayerPoisonCloudTime( playerState_t *ps )
+{
+ 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
+
+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 ps->weapon;
+}
+
+/*
+===============
+atof_neg
+atof with an allowance for negative values
+===============
+*/
+float atof_neg( char *token, qboolean allowNegative )
+{
+ float value;
+
+ value = atof( token );
+
+ if( !allowNegative && value < 0.0f )
+ value = 1.0f;
+
+ return value;
+}
+
+/*
+===============
+atoi_neg
+atoi with an allowance for negative values
+===============
+*/
+int atoi_neg( char *token, qboolean allowNegative )
+{
+ int value;
+
+ value = atoi( token );
+
+ if( !allowNegative && value < 0 )
+ value = 1;
+
+ return value;
+}
+
+#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
+===============
+*/
+void BG_ParseCSVEquipmentList( const char *string, weapon_t *weapons, int weaponsSize,
+ upgrade_t *upgrades, int upgradesSize )
+{
+ char buffer[ MAX_STRING_CHARS ];
+ int i = 0, j = 0;
+ char *p, *q;
+ qboolean EOS = qfalse;
+
+ Q_strncpyz( buffer, string, MAX_STRING_CHARS );
+
+ p = q = buffer;
+
+ while( *p != '\0' )
+ {
+ //skip to first , or EOS
+ while( *p != ',' && *p != '\0' )
+ p++;
+
+ if( *p == '\0' )
+ EOS = qtrue;
+
+ *p = '\0';
+
+ //strip leading whitespace
+ while( *q == ' ' )
+ q++;
+
+ if( weaponsSize )
+ weapons[ i ] = BG_WeaponByName( q )->number;
+
+ if( upgradesSize )
+ upgrades[ j ] = BG_UpgradeByName( q )->number;
+
+ if( weaponsSize && weapons[ i ] == WP_NONE &&
+ upgradesSize && upgrades[ j ] == UP_NONE )
+ Com_Printf( S_COLOR_YELLOW "WARNING: unknown equipment %s\n", q );
+ else if( weaponsSize && weapons[ i ] != WP_NONE )
+ i++;
+ else if( upgradesSize && upgrades[ j ] != UP_NONE )
+ j++;
+
+ if( !EOS )
+ {
+ p++;
+ q = p;
+ }
+ else
+ break;
+
+ if( i == ( weaponsSize - 1 ) || j == ( upgradesSize - 1 ) )
+ break;
+ }
+
+ if( weaponsSize )
+ weapons[ i ] = WP_NONE;
+
+ if( upgradesSize )
+ upgrades[ j ] = UP_NONE;
+}
+
+/*
+===============
+BG_ParseCSVClassList
+===============
+*/
+void BG_ParseCSVClassList( const char *string, class_t *classes, int classesSize )
+{
+ char buffer[ MAX_STRING_CHARS ];
+ int i = 0;
+ char *p, *q;
+ qboolean EOS = qfalse;
+
+ Q_strncpyz( buffer, string, MAX_STRING_CHARS );
+
+ p = q = buffer;
+
+ while( *p != '\0' && i < classesSize - 1 )
+ {
+ //skip to first , or EOS
+ while( *p != ',' && *p != '\0' )
+ p++;
+
+ if( *p == '\0' )
+ EOS = qtrue;
+
+ *p = '\0';
+
+ //strip leading whitespace
+ while( *q == ' ' )
+ q++;
+
+ classes[ i ] = BG_ClassByName( q )->number;
+
+ if( classes[ i ] == PCL_NONE )
+ Com_Printf( S_COLOR_YELLOW "WARNING: unknown class %s\n", q );
+ else
+ i++;
+
+ if( !EOS )
+ {
+ p++;
+ q = p;
+ }
+ else
+ break;
+ }
+
+ classes[ i ] = PCL_NONE;
+}
+
+/*
+===============
+BG_ParseCSVBuildableList
+===============
+*/
+void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int buildablesSize )
+{
+ char buffer[ MAX_STRING_CHARS ];
+ int i = 0;
+ char *p, *q;
+ qboolean EOS = qfalse;
+
+ Q_strncpyz( buffer, string, MAX_STRING_CHARS );
+
+ p = q = buffer;
+
+ while( *p != '\0' && i < buildablesSize - 1 )
+ {
+ //skip to first , or EOS
+ while( *p != ',' && *p != '\0' )
+ p++;
+
+ if( *p == '\0' )
+ EOS = qtrue;
+
+ *p = '\0';
+
+ //strip leading whitespace
+ while( *q == ' ' )
+ q++;
+
+ buildables[ i ] = BG_BuildableByName( q )->number;
+
+ if( buildables[ i ] == BA_NONE )
+ Com_Printf( S_COLOR_YELLOW "WARNING: unknown buildable %s\n", q );
+ else
+ i++;
+
+ if( !EOS )
+ {
+ p++;
+ q = p;
+ }
+ else
+ break;
+ }
+
+ buildables[ i ] = BA_NONE;
+}
+
+typedef struct gameElements_s
+{
+ buildable_t buildables[ BA_NUM_BUILDABLES ];
+ class_t classes[ PCL_NUM_CLASSES ];
+ weapon_t weapons[ WP_NUM_WEAPONS ];
+ upgrade_t upgrades[ UP_NUM_UPGRADES ];
+} gameElements_t;
+
+static gameElements_t bg_disabledGameElements;
+
+/*
+============
+BG_InitAllowedGameElements
+============
+*/
+void BG_InitAllowedGameElements( void )
+{
+ char cvar[ MAX_CVAR_VALUE_STRING ];
+
+ trap_Cvar_VariableStringBuffer( "g_disabledEquipment",
+ cvar, MAX_CVAR_VALUE_STRING );
+
+ BG_ParseCSVEquipmentList( cvar,
+ bg_disabledGameElements.weapons, WP_NUM_WEAPONS,
+ bg_disabledGameElements.upgrades, UP_NUM_UPGRADES );
+
+ trap_Cvar_VariableStringBuffer( "g_disabledClasses",
+ cvar, MAX_CVAR_VALUE_STRING );
+
+ BG_ParseCSVClassList( cvar,
+ bg_disabledGameElements.classes, PCL_NUM_CLASSES );
+
+ trap_Cvar_VariableStringBuffer( "g_disabledBuildables",
+ cvar, MAX_CVAR_VALUE_STRING );
+
+ BG_ParseCSVBuildableList( cvar,
+ bg_disabledGameElements.buildables, BA_NUM_BUILDABLES );
+}
+
+/*
+============
+BG_WeaponIsAllowed
+============
+*/
+qboolean BG_WeaponIsAllowed( weapon_t weapon )
+{
+ int i;
+
+ for( i = 0; i < WP_NUM_WEAPONS &&
+ bg_disabledGameElements.weapons[ i ] != WP_NONE; i++ )
+ {
+ if( bg_disabledGameElements.weapons[ i ] == weapon )
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+============
+BG_UpgradeIsAllowed
+============
+*/
+qboolean BG_UpgradeIsAllowed( upgrade_t upgrade )
+{
+ int i;
+
+ for( i = 0; i < UP_NUM_UPGRADES &&
+ bg_disabledGameElements.upgrades[ i ] != UP_NONE; i++ )
+ {
+ if( bg_disabledGameElements.upgrades[ i ] == upgrade )
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+============
+BG_ClassIsAllowed
+============
+*/
+qboolean BG_ClassIsAllowed( class_t class )
+{
+ int i;
+
+ for( i = 0; i < PCL_NUM_CLASSES &&
+ bg_disabledGameElements.classes[ i ] != PCL_NONE; i++ )
+ {
+ if( bg_disabledGameElements.classes[ i ] == class )
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+============
+BG_BuildableIsAllowed
+============
+*/
+qboolean BG_BuildableIsAllowed( buildable_t buildable )
+{
+ int i;
+
+ for( i = 0; i < BA_NUM_BUILDABLES &&
+ bg_disabledGameElements.buildables[ i ] != BA_NONE; i++ )
+ {
+ if( bg_disabledGameElements.buildables[ i ] == buildable )
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+============
+BG_PrimaryWeapon
+============
+*/
+weapon_t BG_PrimaryWeapon( int stats[ ] )
+{
+ int i;
+
+ for( i = WP_NONE; i < WP_NUM_WEAPONS; i++ )
+ {
+ if( BG_Weapon( i )->slots != SLOT_WEAPON )
+ continue;
+ if( BG_InventoryContainsWeapon( i, stats ) )
+ return i;
+ }
+
+ if( BG_InventoryContainsWeapon( WP_BLASTER, stats ) )
+ return WP_BLASTER;
+
+ return WP_NONE;
+}
+
+/*
+============
+BG_LoadEmoticons
+============
+*/
+int BG_LoadEmoticons( emoticon_t *emoticons, int num )
+{
+ int numFiles;
+ char fileList[ MAX_EMOTICONS * ( MAX_EMOTICON_NAME_LEN + 9 ) ] = {""};
+ int i;
+ char *filePtr;
+ int fileLen;
+ int count;
+
+ 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_TeamName
+============
+*/
+char *BG_TeamName( team_t team )
+{
+ if( team == TEAM_NONE )
+ return "spectator";
+ if( team == TEAM_ALIENS )
+ return "alien";
+ if( team == TEAM_HUMANS )
+ return "human";
+ return "<team>";
+}
+
+int cmdcmp( const void *a, const void *b )
+{
+ return Q_stricmp( (const char *)a, ((dummyCmd_t *)b)->name );
+}