diff options
author | Mikko Tiusanen <ams@daug.net> | 2014-05-04 01:18:52 +0300 |
---|---|---|
committer | Mikko Tiusanen <ams@daug.net> | 2014-05-04 01:18:52 +0300 |
commit | 01beb9919b95479d8be040bec74abc5cc67a5e43 (patch) | |
tree | 65f0b79e793848491832756a4c3a32b23668fab3 /src/game/bg_misc.c | |
parent | 191d731da136b7ee959a17e63111c9146219a768 (diff) |
Initial import.
Diffstat (limited to 'src/game/bg_misc.c')
-rw-r--r-- | src/game/bg_misc.c | 5447 |
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 ); +} |