2011-06-01 12:20:56 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
# include "g_local.h"
# include "g_groups.h"
//extern qboolean BG_BorgTransporting( playerState_t *ps );
extern void BG_LoadItemNames ( void ) ;
extern qboolean BG_ParseRankNames ( char * fileName , rankNames_t rankNames [ ] ) ;
qboolean G_LoadMapConfigurations ( void ) ;
//RPG-X: RedTechie
//int shaketimer; //Global shake timer varible //TiM: NOT NECESSARY
int RPGEntityCount ; //Global entity count varible
//int lastTimedMessage; //The last timed message that was displayed //TiM: Not necessary here
level_locals_t level ;
extern char races [ 256 ] ; //this is evil!
extern qboolean levelExiting ;
group_list_t group_list [ MAX_GROUP_MEMBERS ] ;
int group_count ;
int numKilled ;
typedef struct {
vmCvar_t * vmCvar ;
char * cvarName ;
char * defaultString ;
int cvarFlags ;
int modificationCount ; // for tracking changes
qboolean trackChange ; // track this variable, and announce if changed
} cvarTable_t ;
gentity_t g_entities [ MAX_GENTITIES ] ;
gclient_t g_clients [ MAX_CLIENTS ] ;
rankNames_t g_rankNames [ MAX_RANKS ] ;
g_classData_t g_classData [ MAX_CLASSES ] ;
vmCvar_t g_pModAssimilation ;
vmCvar_t g_pModDisintegration ;
vmCvar_t g_pModActionHero ;
vmCvar_t g_pModSpecialties ;
vmCvar_t g_pModElimination ;
vmCvar_t g_gametype ;
vmCvar_t g_dmflags ;
vmCvar_t g_fraglimit ;
vmCvar_t g_timelimit ;
vmCvar_t g_timelimitWinningTeam ;
vmCvar_t g_capturelimit ;
vmCvar_t g_friendlyFire ;
vmCvar_t g_password ;
vmCvar_t g_needpass ;
vmCvar_t g_maxclients ;
vmCvar_t g_maxGameClients ;
vmCvar_t g_dedicated ;
vmCvar_t g_speed ;
vmCvar_t g_gravity ;
vmCvar_t g_cheats ;
vmCvar_t g_knockback ;
vmCvar_t g_dmgmult ;
vmCvar_t g_forcerespawn ;
vmCvar_t g_inactivity ;
vmCvar_t g_debugMove ;
vmCvar_t g_debugDamage ;
vmCvar_t g_debugAlloc ;
vmCvar_t g_weaponRespawn ;
vmCvar_t g_adaptRespawn ;
vmCvar_t g_motd ;
vmCvar_t g_synchronousClients ;
vmCvar_t g_warmup ;
vmCvar_t g_doWarmup ;
vmCvar_t g_restarted ;
vmCvar_t g_log ;
vmCvar_t g_logSync ;
vmCvar_t g_podiumDist ;
vmCvar_t g_podiumDrop ;
vmCvar_t g_allowVote ;
vmCvar_t g_teamAutoJoin ;
vmCvar_t g_teamForceBalance ;
vmCvar_t g_banIPs ;
vmCvar_t g_filterBan ;
vmCvar_t g_banIDs ; //TiM - Security ban system
vmCvar_t g_debugForward ;
vmCvar_t g_debugRight ;
vmCvar_t g_debugUp ;
vmCvar_t g_language ;
vmCvar_t g_holoIntro ;
//vmCvar_t g_ghostRespawn;
vmCvar_t g_intermissionTime ;
vmCvar_t g_team_group_red ;
vmCvar_t g_team_group_blue ;
vmCvar_t g_random_skin_limit ;
vmCvar_t g_classChangeDebounceTime ;
//vmCvar_t ui_playerclass;
//RPG-X: - RedTechie More CVAR INFO
vmCvar_t rpg_allowvote ;
vmCvar_t rpg_chatsallowed ;
vmCvar_t rpg_allowsuicide ;
vmCvar_t rpg_selfdamage ;
vmCvar_t rpg_rpg ;
vmCvar_t rpg_kickspammers ; //!< Specifies whether player that spam get kicked automatically.
vmCvar_t rpg_kicksuiciders ; //!< Specifies whether player that sucide get kicked automatically.
vmCvar_t rpg_allowspmaps ; //!< Specifies whether singleplayer maps can be loaded
vmCvar_t rpg_rangetricorder ; //!< Maximum range the Tricorder can scan.
vmCvar_t rpg_rangehypo ; //!< Maximum range of the Hypospray.
vmCvar_t rpg_norpgclasses ;
vmCvar_t rpg_forceclasscolor ; //!< Specifies whether class colors specified in the *.class file are enforced.
vmCvar_t rpg_nosecurity ;
vmCvar_t rpg_nomarine ;
vmCvar_t rpg_nomedical ;
vmCvar_t rpg_noscience ;
vmCvar_t rpg_nocommand ;
vmCvar_t rpg_noengineer ;
vmCvar_t rpg_noalien ;
vmCvar_t rpg_nomaker ;
vmCvar_t rpg_non00b ;
vmCvar_t rpg_nocloak ; //!< Can be used to disable the admin cloaking device.
vmCvar_t rpg_noflight ; //!< Can be used to disable the admin flight mode.
vmCvar_t rpg_phaserdmg ; //!< Specifies whether the phaser damges players.
vmCvar_t rpg_rifledmg ; //!< Specifies whether the phaser rifle damages players.
vmCvar_t rpg_stasisdmg ; //!< Specifies whether the disruptor damages rifles.
vmCvar_t rpg_imoddmg ;
vmCvar_t rpg_noweapons ; //!< Can be used to disable all weapons.
//vmCvar_t rpg_marinepass;
//vmCvar_t rpg_securitypass;
//vmCvar_t rpg_adminpass;
//vmCvar_t rpg_medicalpass;
//vmCvar_t rpg_sciencepass;
//vmCvar_t rpg_commandpass;
//vmCvar_t rpg_engineerpass;
//vmCvar_t rpg_alienpass;
//vmCvar_t rpg_n00bpass;
//vmCvar_t rpg_alienflags;
//vmCvar_t rpg_marineflags;
//vmCvar_t rpg_securityflags;
//vmCvar_t rpg_adminflags;
//vmCvar_t rpg_medicalflags;
//vmCvar_t rpg_scienceflags;
//vmCvar_t rpg_commandflags;
//vmCvar_t rpg_engineerflags;
vmCvar_t rpg_welcomemessage ; //!< Welcome message displayed when a player joins the server.
//vmCvar_t rpg_timedmessage;
vmCvar_t rpg_timedmessagetime ; //!< Delay between timed mesagges
vmCvar_t rpg_message1 ; //!< Timed message
vmCvar_t rpg_message2 ; //!< Timed message
vmCvar_t rpg_message3 ; //!< Timed message
vmCvar_t rpg_message4 ; //!< Timed message
vmCvar_t rpg_message5 ; //!< Timed message
vmCvar_t rpg_message6 ; //!< Timed message
vmCvar_t rpg_message7 ; //!< Timed message
vmCvar_t rpg_message8 ; //!< Timed message
vmCvar_t rpg_message9 ; //!< Timed message
vmCvar_t rpg_message10 ; //!< Timed message
vmCvar_t rpg_forcekillradius ; //!< Specifies whether the forcekillradius command is avaible.
vmCvar_t rpg_forcekillradiuswaittime ; //!< forcekillradius delay
vmCvar_t rpg_noclipspectating ; //!< Specifies whether spectators uses clipping.
vmCvar_t rpg_chatarearange ; //!< Maximumrange for area chat.
vmCvar_t rpg_forcefielddamage ; //!< Damage a player takes when touching an admin force field
vmCvar_t rpg_invisibletripmines ; //!< Specifies whether invisible tripmines are enabled.
vmCvar_t rpg_medicsrevive ; //!< Are medics allowed to revive other players
vmCvar_t rpg_effectsgun ; //!< Can be used to enable/disable the effects gun
vmCvar_t rpg_phaserdisintegrates ; //!< If enabled phasers disintegrate players instead ob incapacitating them.
//vmCvar_t rpg_enabledranks;
//vmCvar_t rpg_servershakeallclients;//RPG-X: RedTechie - Server only shake cmd used to shake clients view when set
//vmCvar_t rpg_servershakeallclientsintensity;//RPG-X: RedTechie - Server only shake cmd used to shake clients view intensity
//! Kick player for n00bing after this ammount of kills
vmCvar_t rpg_kickAfterXkills ; //RPG-X | Phenix | 06/04/2005
vmCvar_t rpg_rankSet ; //!< Rankset to use
vmCvar_t rpg_passMessage ; //RPG-X | TiM | 2/2/2006
//! If enabled the previous name of a player is displayed if the reconnects with a different one.
vmCvar_t rpg_renamedPlayers ; //RPG-X | TiM | For players that disconnect, reconnect with dif names to try and be sneaky...
//! If enabled only one player can have a name at the same time.
vmCvar_t rpg_uniqueNames ; //RPG-X | TiM | When active, only one player can have the same name on a server
//RPG-X | TiM | Cvars to make the rank system more controllable
vmCvar_t rpg_startingRank ; //!< The rank players will start as, regardless
vmCvar_t rpg_maxRank ; //!< Absolute rank players can set themselves to
vmCvar_t rpg_changeRanks ; //!< If players are allowed to change ranks themselves
//TiM - height paramters
vmCvar_t rpg_maxHeight ;
vmCvar_t rpg_minHeight ;
vmCvar_t rpg_maxWeight ;
vmCvar_t rpg_minWeight ;
//! Classet to use
vmCvar_t rpg_classSet ; //TiM: current server class configuration
vmCvar_t rpg_mapGiveFlags ;
vmCvar_t rpg_scannablePanels ; //!< Scan consoles and doors be scanned with the Tricorder
// Drop stuff
//! Enables weapon dropping
vmCvar_t rpg_allowWeaponDrop ; //RPG-X | Marcin | 03/12/2008
//! Do weapons stay in inventory when a player drops them
vmCvar_t rpg_weaponsStay ; //RPG-X | Marcin | 04/12/2008
//! Does a player drop his weapons when he dies
vmCvar_t rpg_dropOnDeath ; //RPG-X | Marcin | 30/12/2008
//vmCvar_t rpg_flushDroppedOnDisconnect; //RPG-X | GSIO01 | 08/05/2009
// Weapon speeds
//! Speed for compression riffle projectiles
vmCvar_t rpg_rifleSpeed ; //RPG-X | Marcin | 04/12/2008
//! Speed for disruptor projectiles
vmCvar_t rpg_disruptorSpeed ; //RPG-X | Marcin | 04/12/2008
//! Speed for photon burst projectiles
vmCvar_t rpg_photonSpeed ; //RPG-X | Marcin | 05/12/2008
//! Speed for altfire photon burst projectiles
vmCvar_t rpg_altPhotonSpeed ; //RPG-X | Marcin | 06/12/2008
// Weapon delays
//! Fire delay for Compression Rifle
vmCvar_t rpg_rifleDelay ; //RPG-X | Marcin | 06/12/2008
//! Fire delay for Disruptor
vmCvar_t rpg_disruptorDelay ; //RPG-X | Marcin | 06/12/2008
//! Fire delay for photon burst primary fire
vmCvar_t rpg_photonDelay ; //RPG-X | Marcin | 06/12/2008
//! Fire delay for photon burst secondary fire
vmCvar_t rpg_altPhotonDelay ; //RPG-X | Marcin | 06/12/2008
//! Fire delay for TR116
vmCvar_t rpg_TR116Delay ; //RPG-X | Marcin | 30/12/2008
//! Fire delay for Tricorder alt fire
vmCvar_t rpg_altTricorderDelay ; //RPG-X | GSIO01 | 14/05/2009
// Motd
//! Specifies the message of the day file
vmCvar_t rpg_motdFile ; //RPG-X | Marcin | 23/12/2008
// Privacy
//! If enabled admins can the private chat messages
vmCvar_t rpg_respectPrivacy ; //RPG-X | Marcin | 24/12/2008
// Weaps
vmCvar_t rpg_maxTricorders ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxPADDs ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxCups ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxPhasers ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxRifles ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxTR116s ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxAdminguns ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxPhotonbursts ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxDisruptors ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxMedkits ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxHyposprays ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxRegenerators ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxToolkits ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_maxHyperSpanners ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minTricorders ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minPADDs ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minCups ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minPhasers ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minRifles ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minTR116s ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minAdminguns ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minPhotonbursts ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minDisruptors ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minMedkits ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minHyposprays ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minRegenerators ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minToolkits ; //RPG-X | Marcin | 30/12/2008
vmCvar_t rpg_minHyperSpanners ; //RPG-X | Marcin | 30/12/2008
// respawn delay
//! Delay for respawn function
vmCvar_t rpg_fraggerSpawnDelay ; //RPG-X | Marcin | 03/01/2009
// borg adaption
//! If enabled borg get immune to weapons after some time
vmCvar_t rpg_borgAdapt ; //RPG-X | GSIO01 | 08/05/2009
//! Borg shield plays sound if hit?
vmCvar_t rpg_adaptUseSound ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptPhaserHits ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptPhotonHits ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptCrifleHits ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptDisruptorHits ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptTR116Hits ; //RPG-X | GSIO01 | 08/05/2009
//! Number of hits before borg adapt to this weapon
vmCvar_t rpg_adaptGrenadeLauncherHits ; //RPG-X | GSIO01 | 08/05/2009
//! Are player allowed to remodulate their weapons
vmCvar_t rpg_allowRemodulation ; //RPG-X | GSIO01 | 10/05/2009
//! Can borg move through admin force fields
vmCvar_t rpg_borgMoveThroughFields ; //RPG-X | GSIO01 | 19/05/2009
//! Delay for modulation
vmCvar_t rpg_RemodulationDelay ;
// hypo melee
//! Can the hypospray be used as weapons
vmCvar_t rpg_hypoMelee ;
// repairing breakables
//! Can be used to modify repairspeed
vmCvar_t rpg_repairModifier ; //RPG-X | GSIO01 | 09/05/2009
// force field colors
//! Current force field color
vmCvar_t rpg_forceFieldColor ; //RPG-X | GSIO01 | 09/05/2009
// modulation thingies //RPG-X | GSIO01 | 12/05/2009
vmCvar_t rpg_forceFieldFreq ;
// calc lif travel duration by dec distance
//! Calculathe the travel durration of the turbolift by the difference between the deck numbers?
vmCvar_t rpg_calcLiftTravelDuration ;
//! Can be used to modify the lift speed
vmCvar_t rpg_liftDurationModifier ;
// admin vote override
//! Admins can override votes
vmCvar_t rpg_adminVoteOverride ;
// server change
//! Enables/disables target_serverchange
vmCvar_t rpg_serverchange ;
vmCvar_t rpg_server1 ;
vmCvar_t rpg_server2 ;
vmCvar_t rpg_server3 ;
vmCvar_t rpg_server4 ;
vmCvar_t rpg_server5 ;
vmCvar_t rpg_server6 ;
// SP level change
//! Allow target_levelchange to change the current level?
vmCvar_t rpg_allowSPLevelChange ;
# ifdef XTRA
vmCvar_t sql_dbName ; //!< Name of the SQL Database
vmCvar_t sql_use ; //!< Use SQL? 1 = mysql, 2 = sqlite
vmCvar_t sql_server ; //!< SQL server to connect to (only mysql)
vmCvar_t sql_user ; //!< SQL user for sql_server (only mysql)
vmCvar_t sql_password ; //!< SQL password for sql_server (only mysql)
vmCvar_t sql_port ; //!< SQL port to use to connect to sql_server (only mysql)
vmCvar_t sql_hash ; //!< Specifies whether passwords should be hashed and what hash to use (only mysql)
# endif
// developer tools
vmCvar_t dev_showTriggers ;
# ifdef G_LUA
// Print Lua debugging information into the game console?
vmCvar_t g_debugLua ;
vmCvar_t lua_modules ;
vmCvar_t lua_allowedModules ;
# endif
// XPERIMENTAL
//vmCvar_t rpg_useLanguages;
static cvarTable_t gameCvarTable [ ] = {
// don't override the cheat state set by the system
{ & g_cheats , " sv_cheats " , " " , 0 , 0 , qfalse } ,
// noset vars
{ NULL , " gamename " , GAMEVERSION , CVAR_SERVERINFO | CVAR_ROM , 0 , qfalse } ,
{ NULL , " gamedate " , __DATE__ , CVAR_ROM , 0 , qfalse } ,
{ & g_restarted , " g_restarted " , " 0 " , CVAR_ROM , 0 , qfalse } ,
{ NULL , " sv_mapname " , " " , CVAR_SERVERINFO | CVAR_ROM , 0 , qfalse } ,
// latched vars
{ & g_gametype , " g_gametype " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH | CVAR_INIT | CVAR_ROM , 0 , qfalse } ,
{ & g_pModAssimilation , " g_pModAssimilation " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & g_pModDisintegration , " g_pModDisintegration " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & g_pModActionHero , " g_pModActionHero " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & g_pModSpecialties , " g_pModSpecialties " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & g_pModElimination , " g_pModElimination " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & g_maxclients , " sv_maxclients " , " 8 " , CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_maxGameClients , " g_maxGameClients " , " 0 " , CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
// change anytime vars
{ & g_dmflags , " dmflags " , " 0 " , CVAR_SERVERINFO | CVAR_ARCHIVE , 0 , qtrue } ,
{ & g_fraglimit , " fraglimit " , " 20 " , CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART , 0 , qtrue } ,
{ & g_timelimit , " timelimit " , " 0 " , CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART , 0 , qtrue } ,
{ & g_timelimitWinningTeam , " timelimitWinningTeam " , " " , CVAR_NORESTART , 0 , qtrue } ,
{ & g_capturelimit , " capturelimit " , " 8 " , CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART , 0 , qtrue } ,
{ & g_synchronousClients , " g_synchronousClients " , " 0 " , CVAR_SYSTEMINFO , 0 , qfalse } ,
{ & g_friendlyFire , " g_friendlyFire " , " 0 " , CVAR_SERVERINFO | CVAR_ARCHIVE , 0 , qtrue } ,
{ & g_teamAutoJoin , " g_teamAutoJoin " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_teamForceBalance , " g_teamForceBalance " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_intermissionTime , " g_intermissionTime " , " 20 " , CVAR_ARCHIVE , 0 , qtrue } ,
{ & g_warmup , " g_warmup " , " 20 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_doWarmup , " g_doWarmup " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_log , " g_log " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_logSync , " g_logSync " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_password , " g_password " , " " , CVAR_USERINFO , 0 , qfalse } ,
{ & g_banIPs , " g_banIPs " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_filterBan , " g_filterBan " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_banIDs , " g_banIDs " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_needpass , " g_needpass " , " 0 " , CVAR_SERVERINFO | CVAR_ROM , 0 , qfalse } ,
{ & g_dedicated , " dedicated " , " 0 " , 0 , 0 , qfalse } ,
{ & g_speed , " g_speed " , " 250 " , CVAR_SERVERINFO | CVAR_ARCHIVE , 0 , qtrue } , // Quake 3 default was 320.
{ & g_gravity , " g_gravity " , " 800 " , CVAR_SERVERINFO | CVAR_ARCHIVE , 0 , qtrue } ,
{ & g_knockback , " g_knockback " , " 500 " , 0 , 0 , qtrue } ,
{ & g_dmgmult , " g_dmgmult " , " 1 " , 0 , 0 , qtrue } ,
{ & g_weaponRespawn , " g_weaponrespawn " , " 5 " , 0 , 0 , qtrue } , // Quake 3 default (with 1 ammo weapons) was 5.
{ & g_adaptRespawn , " g_adaptrespawn " , " 1 " , 0 , 0 , qtrue } , // Make weapons respawn faster with a lot of players.
{ & g_forcerespawn , " g_forcerespawn " , " 0 " , 0 , 0 , qtrue } , // Quake 3 default was 20. This is more "user friendly".
{ & g_inactivity , " g_inactivity " , " 0 " , 0 , 0 , qtrue } ,
{ & g_debugMove , " g_debugMove " , " 0 " , 0 , 0 , qfalse } ,
{ & g_debugDamage , " g_debugDamage " , " 0 " , 0 , 0 , qfalse } ,
{ & g_debugAlloc , " g_debugAlloc " , " 0 " , 0 , 0 , qfalse } ,
{ & g_motd , " g_motd " , " " , 0 , 0 , qfalse } ,
{ & g_podiumDist , " g_podiumDist " , " 80 " , 0 , 0 , qfalse } ,
{ & g_podiumDrop , " g_podiumDrop " , " 70 " , 0 , 0 , qfalse } ,
{ & g_allowVote , " g_allowVote " , " 1 " , CVAR_SERVERINFO , 0 , qfalse } ,
#if 0
{ & g_debugForward , " g_debugForward " , " 0 " , 0 , 0 , qfalse } ,
{ & g_debugRight , " g_debugRight " , " 0 " , 0 , 0 , qfalse } ,
{ & g_debugUp , " g_debugUp " , " 0 " , 0 , 0 , qfalse } ,
# endif
{ & g_language , " g_language " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_holoIntro , " g_holoIntro " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
// { &g_ghostRespawn, "g_ghostRespawn", "5", CVAR_ARCHIVE, 0, qfalse}, // How long the player is ghosted, in seconds.
{ & g_team_group_red , " g_team_group_red " , " " , CVAR_LATCH , 0 , qfalse } , // Used to have CVAR_ARCHIVE
{ & g_team_group_blue , " g_team_group_blue " , " " , CVAR_LATCH , 0 , qfalse } , // Used to have CVAR_ARCHIVE
{ & g_random_skin_limit , " g_random_skin_limit " , " 4 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & g_classChangeDebounceTime , " g_classChangeDebounceTime " , " 180 " , CVAR_ARCHIVE , 0 , qfalse } ,
// { &ui_playerclass, "ui_playerclass", "NOCLASS", CVAR_ARCHIVE, 0, qfalse },
//RPG-X: RedTechie - RPG-X CVARS....duh....just for the slow ones
{ & rpg_allowvote , " rpg_allowVote " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_chatsallowed , " rpg_chatsAllowed " , " 10 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_allowsuicide , " rpg_allowSuicide " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_selfdamage , " rpg_selfDamage " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_rpg , " rpg_rpg " , " 1 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_kickspammers , " rpg_kickSpammers " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_kicksuiciders , " rpg_kickSuiciders " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_allowspmaps , " rpg_allowSPMaps " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_rangetricorder , " rpg_rangeTricorder " , " 128 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_rangehypo , " rpg_rangeHypo " , " 32 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_norpgclasses , " rpg_noRPGClasses " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_forceclasscolor , " rpg_forceClassColor " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nosecurity , " rpg_noSecurity " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nomarine , " rpg_noMarine " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nomedical , " rpg_noMedical " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_noscience , " rpg_noScience " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nocommand , " rpg_noCommand " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_noengineer , " rpg_noEngineer " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_noalien , " rpg_noAlien " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_non00b , " rpg_non00b " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nomaker , " rpg_noMaker " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_nocloak , " rpg_noCloak " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_noflight , " rpg_noFlight " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_phaserdmg , " rpg_phaserDmg " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_rifledmg , " rpg_rifleDmg " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_stasisdmg , " rpg_stasisDmg " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_imoddmg , " rpg_imodDmg " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_noweapons , " rpg_noWeapons " , " 0 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
/*{ &rpg_marinepass, "rpg_marinepass", "marine", CVAR_ARCHIVE, 0, qfalse },
{ & rpg_securitypass , " rpg_securityPass " , " security " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adminpass , " rpg_adminPass " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_medicalpass , " rpg_medicalPass " , " medical " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_sciencepass , " rpg_sciencePass " , " science " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_commandpass , " rpg_commandPass " , " command " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_engineerpass , " rpg_engineerPass " , " engineer " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_alienpass , " rpg_alienpass " , " alien " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_n00bpass , " rpg_n00bpass " , " n00b " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_alienflags , " rpg_alienFlags " , " 1026 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //16
//{ &rpg_marineflags, "rpg_marineflags", "8184", CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse },
{ & rpg_marineflags , " rpg_marineFlags " , " 12398 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //111
{ & rpg_securityflags , " rpg_securityFlags " , " 110 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //15
{ & rpg_adminflags , " rpg_adminFlags " , " 65534 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //24361
{ & rpg_medicalflags , " rpg_medicalFlags " , " 14382 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //231
{ & rpg_scienceflags , " rpg_scienceFlags " , " 46 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //7
{ & rpg_commandflags , " rpg_commandFlags " , " 62 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //6
{ & rpg_engineerflags , " rpg_engineerFlags " , " 49198 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } , //775*/
{ & rpg_welcomemessage , " rpg_welcomeMessage " , " Welcome to the RPG-X Mod " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
// { &rpg_timedmessage, "rpg_timedmessage", "Server is in: Character Development Mode", CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse },
{ & rpg_timedmessagetime , " rpg_timedMessageTime " , " 5 " , CVAR_ARCHIVE , 0 , qfalse } , //TiM : LATCH Not necessary here.
{ & rpg_message1 , " rpg_message1 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message2 , " rpg_message2 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message3 , " rpg_message3 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message4 , " rpg_message4 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message5 , " rpg_message5 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message6 , " rpg_message6 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message7 , " rpg_message7 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message8 , " rpg_message8 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message9 , " rpg_message9 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_message10 , " rpg_message10 " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_forcekillradius , " rpg_forceKillRadius " , " 0 " , CVAR_ARCHIVE | CVAR_NORESTART , 0 , qtrue } ,
{ & rpg_forcekillradiuswaittime , " rpg_forceKillRadiusWaitTime " , " 45000 " , CVAR_LATCH | CVAR_ARCHIVE , 0 , qfalse } ,
//{ &rpg_noclipspectating, "rpg_noclipSpectating", "1", CVAR_ARCHIVE, 0, qtrue}, //Not latched (ie doesnt need server restart)
{ & rpg_chatarearange , " rpg_chatAreaRange " , " 200 " , CVAR_ARCHIVE | CVAR_NORESTART , 0 , qtrue } , //Not latched (ie doesnt need server restart)
{ & rpg_forcefielddamage , " rpg_forcefieldDamage " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_invisibletripmines , " rpg_invisibleTripmines " , " 1 " , CVAR_ARCHIVE | CVAR_SERVERINFO , 0 , qfalse } ,
{ & rpg_medicsrevive , " rpg_medicsRevive " , " 1 " , CVAR_ARCHIVE | CVAR_LATCH , 0 , qfalse } ,
{ & rpg_effectsgun , " rpg_effectsGun " , " 1 " , CVAR_ARCHIVE | CVAR_SERVERINFO , 0 , qfalse } ,
{ & rpg_phaserdisintegrates , " rpg_phaserDisintegrates " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
//{ &rpg_servershakeallclients, "rpg_serverShakeAllClients", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse}, //RPG-X: RedTechie - SHould not be used directly this is to shake allll clients views if set on
//{ &rpg_servershakeallclientsintensity, "rpg_serverShakeAllClientsIntensity", "2", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse}, //RPG-X: RedTechie - SHould not be used directly this is to shake allll clients views itensity
//{ &rpg_enabledranks, "rpg_enabledRanks", "65535", CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse},//RPG-X: RedTechie - This use to be CVAR_ROM jason i have no idea why you set it to read only but im setting it back to normal to fix ranks
{ & rpg_kickAfterXkills , " rpg_kickAfterNumkills " , " 2 " , CVAR_ARCHIVE , 0 , qfalse } , //RPG-X | Phenix | 06/04/2005
{ & rpg_rankSet , " rpg_rankSet " , RANKSET_DEFAULT , CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & rpg_passMessage , " rpg_passMessage " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_renamedPlayers , " rpg_renamedPlayers " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_uniqueNames , " rpg_uniqueNames " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_startingRank , " rpg_startingRank " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_maxRank , " rpg_maxRank " , " " , CVAR_ARCHIVE | CVAR_SERVERINFO , 0 , qfalse } ,
{ & rpg_changeRanks , " rpg_changeRanks " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_classSet , " rpg_classSet " , " rpgx_default " , CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_LATCH , 0 , qfalse } ,
{ & rpg_maxHeight , " rpg_maxHeight " , " 1.15 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_minHeight , " rpg_minHeight " , " 0.90 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_maxWeight , " rpg_maxWeight " , " 1.10 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_minWeight , " rpg_minWeight " , " 0.90 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_mapGiveFlags , " rpg_mapGiveFlags " , " 0 " , CVAR_ARCHIVE | CVAR_LATCH , 0 , qfalse } ,
//TiM - maybe we can fix it later, but for now, disable it
{ & rpg_scannablePanels , " rpg_scannablePanels " , " 1 " , CVAR_ARCHIVE | CVAR_LATCH | CVAR_SERVERINFO , 0 , qfalse } ,
//{ &rpg_scannableForceField, "rpg_scannableForceField", "1", CVAR_ARCHIVE, 0, qfalse }, //RPG-X | GSIO01 | 13/05/2009
{ & rpg_allowWeaponDrop , " rpg_allowWeaponDrop " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } , // RPG-X | Marcin | 03/12/2008
{ & rpg_weaponsStay , " rpg_weaponsStay " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } , // RPG-X | Marcin | 04/12/2008
{ & rpg_rifleSpeed , " rpg_rifleSpeed " , " 2700 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 04/12/2008
{ & rpg_disruptorSpeed , " rpg_disruptorSpeed " , " 3000 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 04/12/2008
{ & rpg_photonSpeed , " rpg_photonSpeed " , " 1300 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 05/12/2008
{ & rpg_altPhotonSpeed , " rpg_altPhotonSpeed " , " 650 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 06/12/2008
{ & rpg_rifleDelay , " rpg_rifleDelay " , " 250 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 06/12/2008
{ & rpg_disruptorDelay , " rpg_disruptorDelay " , " 700 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 06/12/2008
{ & rpg_photonDelay , " rpg_photonDelay " , " 1200 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 06/12/2008
{ & rpg_altPhotonDelay , " rpg_altPhotonDelay " , " 1600 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 06/12/2008
{ & rpg_TR116Delay , " rpg_TR116Delay " , " 500 " , 0 , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_motdFile , " rpg_motdFile " , " RPG-X_Motd.txt " , CVAR_ARCHIVE | CVAR_LATCH , 0 , qfalse } , // RPG-X | Marcin | 23/12/2008
{ & rpg_respectPrivacy , " rpg_respectPrivacy " , " 0 " , CVAR_ARCHIVE | CVAR_SERVERINFO , 0 , qfalse } , // RPG-X | Marcin | 24/12/2008
{ & rpg_maxTricorders , " rpg_maxTricorders " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxPADDs , " rpg_maxPADDs " , " 10 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxCups , " rpg_maxCups " , " 2 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxPhasers , " rpg_maxPhasers " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxRifles , " rpg_maxRifles " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxTR116s , " rpg_maxTR116s " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxAdminguns , " rpg_maxAdminguns " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxPhotonbursts , " rpg_maxPhotonbursts " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxDisruptors , " rpg_maxDisruptors " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxMedkits , " rpg_maxMedkits " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxHyposprays , " rpg_maxHyposprays " , " 2 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxRegenerators , " rpg_maxRegenerators " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxToolkits , " rpg_maxToolkits " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_maxHyperSpanners , " rpg_maxHyperSpanners " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minTricorders , " rpg_minTricorders " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minPADDs , " rpg_minPADDs " , " 5 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minCups , " rpg_minCups " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minPhasers , " rpg_minPhasers " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minRifles , " rpg_minRifles " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minTR116s , " rpg_minTR116s " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minAdminguns , " rpg_minAdminguns " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minPhotonbursts , " rpg_minPhotonbursts " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minDisruptors , " rpg_minDisruptors " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minMedkits , " rpg_minMedkits " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minHyposprays , " rpg_minHyposprays " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minRegenerators , " rpg_minRegenerators " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minToolkits , " rpg_minToolkits " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_minHyperSpanners , " rpg_minHyperSpanners " , " 1 " , CVAR_ARCHIVE , 0 , qtrue } , // RPG-X | Marcin | 30/12/2008
{ & rpg_dropOnDeath , " rpg_dropItemsOnDeath " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } , // RPG-X | Marcin | 30/12/2008
{ & rpg_fraggerSpawnDelay , " rpg_fraggerSpawnDelay " , " 100 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_borgAdapt , " rpg_borgAdapt " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
//{ &rpg_flushDroppedOnDisconnect, "rpg_flushDroppedOnDisconnect", "1", CVAR_ARCHIVE, 0, qfalse }
{ & rpg_hypoMelee , " rpg_hypoMelee " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptUseSound , " rpg_adaptUseSound " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptCrifleHits , " rpg_adaptCrifleHits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptDisruptorHits , " rpg_adaptDisruptorHits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptPhaserHits , " rpg_adaptPhaserHits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptPhotonHits , " rpg_adaptPhotonHits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptTR116Hits , " rpg_adaptTR116Hits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adaptGrenadeLauncherHits , " rpg_adaptGrenadeLauncherHits " , " 6 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_repairModifier , " rpg_repairModifier " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_forceFieldColor , " rpg_forceFieldColor " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_allowRemodulation , " rpg_allowRemodulation " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_forceFieldFreq , " rpg_forceFieldFreq " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_calcLiftTravelDuration , " rpg_calcLiftTravelDuration " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_liftDurationModifier , " rpg_liftDurationModifier " , " 0.5 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_altTricorderDelay , " rpg_altTricorderDelay " , " 1000 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_borgMoveThroughFields , " rpg_borgMoveThroughFields " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_RemodulationDelay , " rpg_RemodulationDelay " , " 5000 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_adminVoteOverride , " rpg_adminVoteOverride " , " 1 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_serverchange , " rpg_serverchange " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server1 , " rpg_server1 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server2 , " rpg_server2 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server3 , " rpg_server3 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server4 , " rpg_server4 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server5 , " rpg_server5 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_server6 , " rpg_server6 " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & rpg_allowSPLevelChange , " rpg_allowSPLevelChange " , " 1 " , CVAR_ARCHIVE | CVAR_LATCH , 0 , qfalse } ,
//XPERIMENTAL
//{ &rpg_useLanguages, "rpg_useLanguages", "1", CVAR_ARCHIVE, 0, qfalse }
{ & dev_showTriggers , " dev_showTriggers " , " 0 " , CVAR_ARCHIVE , 0 , qfalse }
# ifdef XTRA
,
{ & sql_dbName , " sql_dbName " , " rpgx " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_use , " sql_use " , " 0 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_password , " sql_password " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_port , " sql_port " , " 3306 " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_server , " sql_server " , " " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_user , " sql_user " , " rpgx " , CVAR_ARCHIVE , 0 , qfalse } ,
{ & sql_hash , " sql_hash " , " 0 " , CVAR_ARCHIVE , 0 , qfalse }
# endif
# ifdef G_LUA
,
{ & g_debugLua , " g_debugLua " , " 0 " , 0 , 0 , qfalse } ,
{ & lua_allowedModules , " lua_allowedModules " , " " , 0 , 0 , qfalse } ,
{ & lua_modules , " lua_modules " , " " , 0 , 0 , qfalse }
# endif
} ;
static int gameCvarTableSize = sizeof ( gameCvarTable ) / sizeof ( gameCvarTable [ 0 ] ) ;
void G_InitGame ( int levelTime , int randomSeed , int restart ) ;
void G_RunFrame ( int levelTime ) ;
void G_ShutdownGame ( int restart ) ;
void CheckExitRules ( void ) ;
//=============================
//** begin code
/*
= = = = = = = = = = = = = = = =
vmMain
This is the only way control passes into the module .
This MUST be the very first function compiled into the . q3vm file
= = = = = = = = = = = = = = = =
*/
//intptr_t
intptr_t vmMain ( int command , int arg0 , int arg1 , int arg2 , int arg3 , int arg4 , int arg5 , int arg6 ) {
switch ( command ) {
case GAME_INIT :
G_InitGame ( arg0 , arg1 , arg2 ) ;
return 0 ;
case GAME_SHUTDOWN :
G_ShutdownGame ( arg0 ) ;
return 0 ;
case GAME_CLIENT_CONNECT :
return ( size_t ) ClientConnect ( arg0 , arg1 , arg2 ) ;
case GAME_CLIENT_THINK :
ClientThink ( arg0 ) ;
return 0 ;
case GAME_CLIENT_USERINFO_CHANGED :
ClientUserinfoChanged ( arg0 ) ; //TiM - this means a user just tried to change it
return 0 ;
case GAME_CLIENT_DISCONNECT :
ClientDisconnect ( arg0 ) ;
return 0 ;
case GAME_CLIENT_BEGIN :
ClientBegin ( arg0 , qtrue , qfalse , qtrue ) ;
return 0 ;
case GAME_CLIENT_COMMAND :
ClientCommand ( arg0 ) ;
return 0 ;
case GAME_RUN_FRAME :
G_RunFrame ( arg0 ) ;
return 0 ;
case GAME_CONSOLE_COMMAND :
//RPG-X : TiM - plagiarised Red's logic from SFEFMOD here lol
return ConsoleCommand ( ) ;
//return ConsoleCommand();
case BOTAI_START_FRAME :
return BotAIStartFrame ( arg0 ) ;
}
return - 1 ;
}
void QDECL G_PrintfClientAll ( const char * fmt , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , fmt ) ;
vsprintf ( text , fmt , argptr ) ;
va_end ( argptr ) ;
trap_SendServerCommand ( - 1 , va ( " print \" %s \n \" " , text ) ) ;
}
void QDECL G_PrintfClient ( gentity_t * ent , const char * fmt , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , fmt ) ;
vsprintf ( text , fmt , argptr ) ;
va_end ( argptr ) ;
# ifdef G_LUA
LuaHook_G_ClientPrint ( text , ent ) ;
# endif
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , text ) ) ;
}
void QDECL G_Printf ( const char * fmt , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , fmt ) ;
vsprintf ( text , fmt , argptr ) ;
va_end ( argptr ) ;
# ifdef G_LUA
// Lua API callbacks
LuaHook_G_Print ( text ) ;
# endif
trap_Printf ( text ) ;
}
void QDECL G_Error ( const char * fmt , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , fmt ) ;
vsprintf ( text , fmt , argptr ) ;
va_end ( argptr ) ;
# ifdef G_LUA
G_LuaShutdown ( ) ;
# endif
trap_Error ( text ) ;
}
stringID_table_t WeaponTable [ ] = {
2011-06-09 11:31:41 +00:00
{ ENUM2STRING ( WP_TRICORDER ) } ,
{ ENUM2STRING ( WP_PADD ) } ,
{ ENUM2STRING ( WP_COFFEE ) } ,
2011-06-01 12:20:56 +00:00
2011-06-09 11:31:41 +00:00
{ ENUM2STRING ( WP_PHASER ) } ,
{ ENUM2STRING ( WP_COMPRESSION_RIFLE ) } ,
{ ENUM2STRING ( WP_TR116 ) } ,
2011-06-01 12:20:56 +00:00
2011-06-09 11:31:41 +00:00
{ ENUM2STRING ( WP_GRENADE_LAUNCHER ) } ,
{ ENUM2STRING ( WP_QUANTUM_BURST ) } ,
{ ENUM2STRING ( WP_DISRUPTOR ) } ,
2011-06-01 12:20:56 +00:00
2011-06-09 11:31:41 +00:00
{ ENUM2STRING ( WP_MEDKIT ) } ,
{ ENUM2STRING ( WP_VOYAGER_HYPO ) } ,
{ ENUM2STRING ( WP_DERMAL_REGEN ) } ,
2011-06-01 12:20:56 +00:00
2011-06-09 11:31:41 +00:00
{ ENUM2STRING ( WP_TOOLKIT ) } ,
{ ENUM2STRING ( WP_HYPERSPANNER ) } ,
{ NULL , - 1 }
2011-06-01 12:20:56 +00:00
} ;
/**************************
G_LoadClassData
TiM : Loads a " .class " file
and parses the class data
for utilization on the server
and transfer to clients
* * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef Q3_VM
static qboolean G_LoadClassData ( char * fileName )
{
char buffer [ 32000 ] ;
char * textPtr , * token ;
int fileLen ;
fileHandle_t f ;
qboolean classValid = qfalse ;
int classIndex = 0 ;
int weapon ;
int i ;
//Init the storage place
memset ( & g_classData , 0 , sizeof ( g_classData ) ) ;
fileLen = trap_FS_FOpenFile ( fileName , & f , FS_READ ) ;
if ( ! f ) {
G_Printf ( S_COLOR_RED " ERROR: File %s not found. \n " , fileName ) ;
return qfalse ;
}
if ( fileLen > = sizeof ( buffer ) ) {
G_Printf ( S_COLOR_RED " ERROR: File %s was way too big. \n " , fileName ) ;
trap_FS_FCloseFile ( f ) ;
return qfalse ;
}
trap_FS_Read ( buffer , fileLen , f ) ;
buffer [ fileLen ] = 0 ;
trap_FS_FCloseFile ( f ) ;
COM_BeginParseSession ( ) ;
textPtr = buffer ;
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] ) {
G_Printf ( S_COLOR_RED " ERROR: No data was found when going to parse the file! \n " ) ;
return qfalse ;
}
if ( Q_stricmpn ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: File did not start with a '{' symbol! \n " ) ;
return qfalse ;
}
while ( 1 )
{
if ( classIndex > = MAX_CLASSES )
break ;
if ( ! Q_stricmpn ( token , " { " , 1 ) )
{
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] ) {
break ;
}
if ( ! Q_stricmpn ( token , " consoleName " , 11 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class console name in class index: %i. \n " , classIndex ) ;
SkipBracedSection ( & textPtr ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . consoleName , token , sizeof ( g_classData [ classIndex ] . consoleName ) ) ;
classValid = qtrue ;
//G_Printf( S_COLOR_RED "%s\n", g_classData[classIndex].consoleName );
continue ;
}
if ( ! Q_stricmpn ( token , " formalName " , 11 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class formal name in class index: %i. \n " , classIndex ) ;
SkipBracedSection ( & textPtr ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . formalName , token , sizeof ( g_classData [ classIndex ] . formalName ) ) ;
classValid = qtrue ;
//G_Printf( S_COLOR_RED "%s\n", g_classData[classIndex].consoleName );
continue ;
}
if ( ! Q_stricmpn ( token , " message " , 7 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class message in class index: %i. \n " , classIndex ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . message , token , sizeof ( g_classData [ classIndex ] . message ) ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " modelSkin " , 9 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class skin color in class index: %i. \n " , classIndex ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . modelSkin , token , sizeof ( g_classData [ classIndex ] . modelSkin ) ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " weapons " , 7 ) )
{
token = COM_Parse ( & textPtr ) ;
if ( Q_stricmpn ( token , " { " , 1 ) )
{
G_Printf ( S_COLOR_RED " No opening bracket found for weapons field in class: %i. \n " , classIndex ) ;
SkipRestOfLine ( & textPtr ) ;
continue ;
}
//sub loop
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
break ;
if ( ! Q_stricmpn ( token , " | " , 1 ) )
continue ;
if ( ! Q_stricmpn ( token , " } " , 1 ) )
break ;
if ( ! Q_stricmpn ( token , " WP_ " , 3 ) )
{
weapon = GetIDForString ( WeaponTable , token ) ;
if ( weapon > = 0 )
{
g_classData [ classIndex ] . weaponsFlags | = ( 1 < < weapon ) ;
continue ;
}
}
}
continue ;
}
if ( ! Q_stricmpn ( token , " admin " , 5 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isAdmin ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class admin check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " marine " , 6 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isMarine ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class marine check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " medical " , 7 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isMedical ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class medic check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " isBorg " , 6 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isBorg ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class borg check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " n00b " , 4 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isn00b ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class n00b check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
//skip the client-side specific entries since they interfere with the parsing
if ( ! Q_stricmpn ( token , " radarColor " , 10 )
| | ! Q_stricmpn ( token , " iconColor " , 9 )
| | ! Q_stricmpn ( token , " hasRanks " , 8 )
| | ! Q_stricmpn ( token , " noShow " , 6 )
)
{
SkipRestOfLine ( & textPtr ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " } " , 1 ) )
{
break ;
}
}
if ( classValid )
{
classIndex + + ;
classValid = qfalse ;
}
}
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
{
break ;
}
}
//build ourselves custom CVARs for each class
for ( i = 0 ; g_classData [ i ] . consoleName [ 0 ] & & i < MAX_CLASSES ; i + + )
{
trap_Cvar_Register ( NULL , va ( " rpg_%sPass " , g_classData [ i ] . consoleName ) , g_classData [ i ] . consoleName , CVAR_ARCHIVE ) ;
trap_Cvar_Register ( NULL , va ( " rpg_%sFlags " , g_classData [ i ] . consoleName ) , va ( " %i " , g_classData [ i ] . weaponsFlags ) , CVAR_ARCHIVE ) ;
}
if ( classIndex > 0 )
{
return qtrue ;
}
else
{
G_Printf ( S_COLOR_RED " ERROR: No valid classes were found. \n " ) ;
return qfalse ;
}
}
# else
static qboolean G_LoadClassData ( char * fileName )
{
char * buffer ;
char * textPtr , * token ;
int fileLen ;
fileHandle_t f ;
qboolean classValid = qfalse ;
int classIndex = 0 ;
int weapon ;
int i ;
//Init the storage place
memset ( & g_classData , 0 , sizeof ( g_classData ) ) ;
fileLen = trap_FS_FOpenFile ( fileName , & f , FS_READ ) ;
if ( ! f ) {
G_Printf ( S_COLOR_RED " ERROR: File %s not found. \n " , fileName ) ;
return qfalse ;
}
if ( fileLen > = 32000 ) {
G_Printf ( S_COLOR_RED " ERROR: File %s was way too big. \n " , fileName ) ;
trap_FS_FCloseFile ( f ) ;
return qfalse ;
}
buffer = ( char * ) malloc ( 32000 * sizeof ( char ) ) ;
if ( ! buffer ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , 32000 * sizeof ( char ) ) ;
trap_FS_FCloseFile ( f ) ;
return qfalse ;
}
trap_FS_Read ( buffer , fileLen , f ) ;
buffer [ fileLen ] = 0 ;
trap_FS_FCloseFile ( f ) ;
COM_BeginParseSession ( ) ;
textPtr = buffer ;
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] ) {
G_Printf ( S_COLOR_RED " ERROR: No data was found when going to parse the file! \n " ) ;
free ( buffer ) ;
return qfalse ;
}
if ( Q_stricmpn ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: File did not start with a '{' symbol! \n " ) ;
free ( buffer ) ;
return qfalse ;
}
while ( 1 )
{
if ( classIndex > = MAX_CLASSES )
break ;
if ( ! Q_stricmpn ( token , " { " , 1 ) )
{
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] ) {
break ;
}
if ( ! Q_stricmpn ( token , " consoleName " , 11 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class console name in class index: %i. \n " , classIndex ) ;
SkipBracedSection ( & textPtr ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . consoleName , token , sizeof ( g_classData [ classIndex ] . consoleName ) ) ;
classValid = qtrue ;
//G_Printf( S_COLOR_RED "%s\n", g_classData[classIndex].consoleName );
continue ;
}
if ( ! Q_stricmpn ( token , " formalName " , 11 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class formal name in class index: %i. \n " , classIndex ) ;
SkipBracedSection ( & textPtr ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . formalName , token , sizeof ( g_classData [ classIndex ] . formalName ) ) ;
classValid = qtrue ;
//G_Printf( S_COLOR_RED "%s\n", g_classData[classIndex].consoleName );
continue ;
}
if ( ! Q_stricmpn ( token , " message " , 7 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class message in class index: %i. \n " , classIndex ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . message , token , sizeof ( g_classData [ classIndex ] . message ) ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " modelSkin " , 9 ) )
{
if ( COM_ParseString ( & textPtr , & token ) )
{
G_Printf ( S_COLOR_RED " ERROR: Invalid class skin color in class index: %i. \n " , classIndex ) ;
continue ;
}
Q_strncpyz ( g_classData [ classIndex ] . modelSkin , token , sizeof ( g_classData [ classIndex ] . modelSkin ) ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " weapons " , 7 ) )
{
token = COM_Parse ( & textPtr ) ;
if ( Q_stricmpn ( token , " { " , 1 ) )
{
G_Printf ( S_COLOR_RED " No opening bracket found for weapons field in class: %i. \n " , classIndex ) ;
SkipRestOfLine ( & textPtr ) ;
continue ;
}
//sub loop
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
break ;
if ( ! Q_stricmpn ( token , " | " , 1 ) )
continue ;
if ( ! Q_stricmpn ( token , " } " , 1 ) )
break ;
if ( ! Q_stricmpn ( token , " WP_ " , 3 ) )
{
weapon = GetIDForString ( WeaponTable , token ) ;
if ( weapon > = 0 )
{
g_classData [ classIndex ] . weaponsFlags | = ( 1 < < weapon ) ;
continue ;
}
}
}
continue ;
}
if ( ! Q_stricmpn ( token , " admin " , 5 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isAdmin ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class admin check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " marine " , 6 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isMarine ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class marine check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " medical " , 7 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isMedical ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class medic check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " isBorg " , 6 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isBorg ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class borg check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
if ( ! Q_stricmpn ( token , " n00b " , 4 ) )
{
if ( COM_ParseInt ( & textPtr , & g_classData [ classIndex ] . isn00b ) )
{
G_Printf ( S_COLOR_RED " ERROR: Class n00b check for class %i was invalid. \n " , classIndex ) ;
continue ;
}
continue ;
}
//skip the client-side specific entries since they interfere with the parsing
if ( ! Q_stricmpn ( token , " radarColor " , 10 )
| | ! Q_stricmpn ( token , " iconColor " , 9 )
| | ! Q_stricmpn ( token , " hasRanks " , 8 )
| | ! Q_stricmpn ( token , " noShow " , 6 )
)
{
SkipRestOfLine ( & textPtr ) ;
continue ;
}
if ( ! Q_stricmpn ( token , " } " , 1 ) )
{
break ;
}
}
if ( classValid )
{
classIndex + + ;
classValid = qfalse ;
}
}
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
{
break ;
}
}
free ( buffer ) ;
//build ourselves custom CVARs for each class
for ( i = 0 ; g_classData [ i ] . consoleName [ 0 ] & & i < MAX_CLASSES ; i + + )
{
trap_Cvar_Register ( NULL , va ( " rpg_%sPass " , g_classData [ i ] . consoleName ) , g_classData [ i ] . consoleName , CVAR_ARCHIVE ) ;
trap_Cvar_Register ( NULL , va ( " rpg_%sFlags " , g_classData [ i ] . consoleName ) , va ( " %i " , g_classData [ i ] . weaponsFlags ) , CVAR_ARCHIVE ) ;
}
if ( classIndex > 0 )
{
return qtrue ;
}
else
{
G_Printf ( S_COLOR_RED " ERROR: No valid classes were found. \n " ) ;
return qfalse ;
}
}
# endif
void BG_LanguageFilename ( char * baseName , char * baseExtension , char * finalName ) ;
void SP_target_location ( gentity_t * ent ) ;
holoData_t holoData ;
# ifdef Q3_VM
void G_LoadHolodeckFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
char mapRoute [ MAX_QPATH ] ;
char info [ MAX_INFO_STRING ] ;
fileHandle_t f ;
char buffer [ 20000 ] ;
int file_len ;
char * txtPtr , * token ;
int numProgs = 0 ;
int i ;
//get the map name out of the server data
trap_GetServerinfo ( info , sizeof ( info ) ) ;
//setup the file route
Com_sprintf ( mapRoute , sizeof ( mapRoute ) , " maps/%s " , Info_ValueForKey ( info , " mapname " ) ) ;
BG_LanguageFilename ( mapRoute , " holodeck " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmpn ( token , " HolodeckData " , 12 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_stricmpn ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: HolodeckData had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_stricmpn ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmpn ( token , " Program " , 7 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_stricmpn ( token , " [ " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: Program had no opening brace ( [ )! \n " ) ;
continue ;
}
// expected format:
// <string> - target notnull
// <string> - name
// <string> - desc1
// <string> - desc2
// <string> - image
// <string> - iTrigger
// <string> - dTrigger
while ( Q_stricmpn ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( numProgs > = 5 ) return ;
// targetname of info_notnull
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . target [ numProgs ] , token , sizeof ( holoData . target [ numProgs ] ) ) ;
// parse name
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . name [ numProgs ] , token , sizeof ( holoData . name [ numProgs ] ) ) ;
// parse desc1
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . desc1 [ numProgs ] , token , sizeof ( holoData . desc1 [ numProgs ] ) ) ;
// parse desc2
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . desc2 [ numProgs ] , token , sizeof ( holoData . desc2 [ numProgs ] ) ) ;
// parse image
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . image [ numProgs ] , token , sizeof ( holoData . image [ numProgs ] ) ) ;
// parse iTrigger
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . iTrigger [ numProgs + 1 ] , token , sizeof ( holoData . iTrigger [ numProgs + 1 ] ) ) ;
// parse dTrigger
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . dTrigger [ numProgs + 1 ] , token , sizeof ( holoData . dTrigger [ numProgs + 1 ] ) ) ;
holoData . active = - 1 ;
numProgs + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
for ( i = 0 ; i < MAX_GENTITIES ; i + + )
if ( ! strcmp ( " target_holodeck " , & g_entities [ i ] - > classname ) ) {
strcpy ( holoData . iTrigger [ 0 ] , & g_entities [ i ] - > target ) ;
strcpy ( holoData . dTrigger [ 0 ] , & g_entities [ i ] - > redsound ) ;
break ;
}
holoData . numProgs = numProgs ;
}
# else
void G_LoadHolodeckFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
char mapRoute [ MAX_QPATH ] ;
char * info ;
fileHandle_t f ;
char * buffer ;
int file_len ;
char * txtPtr , * token ;
int numProgs = 0 ;
//int i;
info = ( char * ) malloc ( MAX_INFO_STRING * sizeof ( char ) ) ;
if ( ! info ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i byte. \n " , MAX_INFO_STRING * sizeof ( char ) ) ;
return ;
}
//get the map name out of the server data
trap_GetServerinfo ( info , MAX_INFO_STRING * sizeof ( char ) ) ;
//setup the file route
Com_sprintf ( mapRoute , sizeof ( mapRoute ) , " maps/%s " , Info_ValueForKey ( info , " mapname " ) ) ;
BG_LanguageFilename ( mapRoute , " holodeck " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
free ( info ) ;
if ( ! file_len ) return ;
buffer = ( char * ) malloc ( 32000 * sizeof ( char ) ) ;
if ( ! buffer ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , 32000 * sizeof ( char ) ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
free ( buffer ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
memset ( & holoData , 0 , sizeof ( holoData ) ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmpn ( token , " HolodeckData " , 12 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_stricmpn ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: HolodeckData had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_stricmpn ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmpn ( token , " Program " , 7 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_stricmpn ( token , " [ " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: Program had no opening brace ( [ )! \n " ) ;
continue ;
}
// expected format:
// <string> - target notnull
// <string> - name
// <string> - desc1
// <string> - desc2
// <string> - image
while ( Q_stricmpn ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( numProgs > = 5 ) {
free ( buffer ) ;
return ;
}
// targetname of info_notnull
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . target [ numProgs ] , token , sizeof ( holoData . target [ numProgs ] ) ) ;
// parse name
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . name [ numProgs ] , token , sizeof ( holoData . name [ numProgs ] ) ) ;
// parse desc1
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . desc1 [ numProgs ] , token , sizeof ( holoData . desc1 [ numProgs ] ) ) ;
// parse desc2
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . desc2 [ numProgs ] , token , sizeof ( holoData . desc2 [ numProgs ] ) ) ;
// parse image
token = COM_Parse ( & txtPtr ) ;
Q_strncpyz ( holoData . image [ numProgs ] , token , sizeof ( holoData . image [ numProgs ] ) ) ;
holoData . active = - 1 ;
numProgs + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
holoData . numProgs = numProgs ;
free ( buffer ) ;
}
# endif
srvChangeData_t srvChangeData ;
# ifdef Q3_VM
static void G_LoadServerChangeFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
//char mapRoute[MAX_QPATH];
char infoString [ MAX_INFO_STRING ] ;
fileHandle_t f ;
char buffer [ 20000 ] ;
int file_len ;
char * txtPtr , * token ;
char * temp ;
int cnt = 0 ;
int i = 0 ;
BG_LanguageFilename ( " serverchange " , " cfg " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
memset ( infoString , 0 , sizeof ( infoString ) ) ;
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " ServerChangeConfig " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: ServerChangeConfig had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " Server " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " [ " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: Server had no opening brace ( [ )! \n " ) ;
continue ;
}
token = COM_Parse ( & txtPtr ) ;
while ( Q_strncmp ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( cnt > 12 ) break ;
temp = G_NewString ( token ) ;
/*if(!infoString[0])
Com_sprintf ( infoString , sizeof ( infoString ) , " i%i \\ %s \\ " , cnt , temp ) ;
else {
if ( cnt % 2 = = 0 )
Com_sprintf ( infoString , sizeof ( infoString ) , " %si%i \\ %s \\ " , infoString , i , temp ) ;
else
Com_sprintf ( infoString , sizeof ( infoString ) , " %sd%i \\ %s \\ " , infoString , i , temp ) ;
} */
if ( cnt % 2 = = 0 )
Q_strncpyz ( srvChangeData . ip [ i ] , token , sizeof ( srvChangeData . ip [ i ] ) ) ;
else
Q_strncpyz ( srvChangeData . name [ i ] , token , sizeof ( srvChangeData . name [ i ] ) ) ;
cnt + + ;
if ( cnt % 2 = = 0 )
i + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
//trap_SetConfigstring(CS_SERVERCHANGE, infoString);
}
# else
static void G_LoadServerChangeFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
//char mapRoute[MAX_QPATH];
fileHandle_t f ;
char * buffer ;
int file_len ;
char * txtPtr , * token ;
char * temp ;
int cnt = 0 ;
int i = 0 ;
BG_LanguageFilename ( " serverchange " , " cfg " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
buffer = ( char * ) malloc ( 32000 * sizeof ( char ) ) ;
if ( ! buffer ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , 32000 * sizeof ( char ) ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
free ( buffer ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
memset ( & srvChangeData , 0 , sizeof ( srvChangeData ) ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " ServerChangeConfig " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: ServerChangeConfig had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " Server " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " [ " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: Server had no opening brace ( [ )! \n " ) ;
continue ;
}
token = COM_Parse ( & txtPtr ) ;
while ( Q_strncmp ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( cnt > 12 ) break ;
temp = G_NewString ( token ) ;
/*if(!infoString[0])
Com_sprintf ( infoString , sizeof ( infoString ) , " i%i \\ %s \\ " , cnt , temp ) ;
else {
if ( cnt % 2 = = 0 )
Com_sprintf ( infoString , sizeof ( infoString ) , " %si%i \\ %s \\ " , infoString , i , temp ) ;
else
Com_sprintf ( infoString , sizeof ( infoString ) , " %sd%i \\ %s \\ " , infoString , i , temp ) ;
} */
if ( cnt % 2 = = 0 )
Q_strncpyz ( srvChangeData . ip [ i ] , token , sizeof ( srvChangeData . ip [ i ] ) ) ;
else
Q_strncpyz ( srvChangeData . name [ i ] , token , sizeof ( srvChangeData . name [ i ] ) ) ;
cnt + + ;
if ( cnt % 2 = = 0 )
i + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
free ( buffer ) ;
//trap_SetConfigstring(CS_SERVERCHANGE, infoString);
}
# endif
mapChangeData_t mapChangeData ;
# ifdef Q3_VM
static void G_LoadMapChangeFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
//char mapRoute[MAX_QPATH];
char infoString [ MAX_INFO_STRING ] ;
fileHandle_t f ;
char buffer [ 20000 ] ;
int file_len ;
char * txtPtr , * token ;
char * temp ;
int cnt = 0 ;
int i = 0 ;
BG_LanguageFilename ( " mapchange " , " cfg " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
memset ( infoString , 0 , sizeof ( infoString ) ) ;
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " MapChangeConfig " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: MapChangeConfig had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " Map " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " [ " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: Server had no opening brace ( [ )! \n " ) ;
continue ;
}
token = COM_Parse ( & txtPtr ) ;
while ( Q_strncmp ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( cnt > 12 ) break ;
temp = G_NewString ( token ) ;
/*if(!infoString[0])
Com_sprintf ( infoString , sizeof ( infoString ) , " i%i \\ %s \\ " , cnt , temp ) ;
else {
if ( cnt % 2 = = 0 )
Com_sprintf ( infoString , sizeof ( infoString ) , " %si%i \\ %s \\ " , infoString , i , temp ) ;
else
Com_sprintf ( infoString , sizeof ( infoString ) , " %sd%i \\ %s \\ " , infoString , i , temp ) ;
} */
if ( cnt % 2 = = 0 )
Q_strncpyz ( mapChangeData . name [ i ] , token , sizeof ( mapChangeData . name [ i ] ) ) ;
else
Q_strncpyz ( mapChangeData . bspname [ i ] , token , sizeof ( mapChangeData . bspname [ i ] ) ) ;
cnt + + ;
if ( cnt % 2 = = 0 )
i + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
//trap_SetConfigstring(CS_SERVERCHANGE, infoString);
}
# else
static void G_LoadMapChangeFile ( void ) {
char fileRoute [ MAX_QPATH ] ;
//char mapRoute[MAX_QPATH];
fileHandle_t f ;
char * buffer ;
int file_len ;
char * txtPtr , * token ;
char * temp ;
int cnt = 0 ;
int i = 0 ;
BG_LanguageFilename ( " mapchange " , " cfg " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
buffer = ( char * ) malloc ( 32000 * sizeof ( char ) ) ;
if ( ! buffer ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , 32000 * sizeof ( char ) ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
free ( buffer ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
memset ( & srvChangeData , 0 , sizeof ( srvChangeData ) ) ;
COM_BeginParseSession ( ) ;
txtPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " MapChangeConfig " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: MapChangeConfig had no opening brace ( { )! \n " ) ;
continue ;
}
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( ! token [ 0 ] ) break ;
if ( ! Q_stricmp ( token , " Map " ) ) {
token = COM_Parse ( & txtPtr ) ;
if ( Q_strncmp ( token , " [ " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: Server had no opening brace ( [ )! \n " ) ;
continue ;
}
token = COM_Parse ( & txtPtr ) ;
while ( Q_strncmp ( token , " ] " , 1 ) ) {
if ( ! token [ 0 ] ) break ;
if ( cnt > 12 ) break ;
temp = G_NewString ( token ) ;
/*if(!infoString[0])
Com_sprintf ( infoString , sizeof ( infoString ) , " i%i \\ %s \\ " , cnt , temp ) ;
else {
if ( cnt % 2 = = 0 )
Com_sprintf ( infoString , sizeof ( infoString ) , " %si%i \\ %s \\ " , infoString , i , temp ) ;
else
Com_sprintf ( infoString , sizeof ( infoString ) , " %sd%i \\ %s \\ " , infoString , i , temp ) ;
} */
if ( cnt % 2 = = 0 )
Q_strncpyz ( mapChangeData . name [ i ] , token , sizeof ( mapChangeData . name [ i ] ) ) ;
else
Q_strncpyz ( mapChangeData . bspname [ i ] , token , sizeof ( mapChangeData . bspname [ i ] ) ) ;
cnt + + ;
if ( cnt % 2 = = 0 )
i + + ;
token = COM_Parse ( & txtPtr ) ;
}
}
}
}
}
free ( buffer ) ;
//trap_SetConfigstring(CS_SERVERCHANGE, infoString);
}
# endif
# ifdef Q3_VM
static void G_LoadLocationsFile ( void )
{
char fileRoute [ MAX_QPATH ] ;
char mapRoute [ MAX_QPATH ] ;
char serverInfo [ MAX_TOKEN_CHARS ] ;
fileHandle_t f ;
char buffer [ 20000 ] ;
int file_len ;
char * textPtr , * token ;
vec3_t origin , angles ;
gentity_t * ent ;
char * desc ;
int rest ;
//get the map name out of the server data
trap_GetServerinfo ( serverInfo , sizeof ( serverInfo ) ) ;
//setup the file route
Com_sprintf ( mapRoute , sizeof ( mapRoute ) , " maps/%s " , Info_ValueForKey ( serverInfo , " mapname " ) ) ;
BG_LanguageFilename ( mapRoute , " locations " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
G_Printf ( " Locations file %s located. Proceeding to load scan data. \n " , fileRoute ) ; //GSIO01: why did this say "Usables file ..."? lol
COM_BeginParseSession ( ) ;
textPtr = buffer ;
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
break ;
if ( ! Q_strncmp ( token , " LocationsList2 " , 19 ) ) { // new style locations list with restricted locations
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: LocationsList2 had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
//expected format is "<origin> <angle> <int> <string>"
while ( Q_strncmp ( token , " } " , 1 ) )
{
if ( ! token [ 0 ] )
break ;
//Parse origin
if ( COM_ParseVec3 ( & textPtr , origin ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
return ;
}
//Parse angles
if ( COM_ParseVec3 ( & textPtr , angles ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
return ;
}
//Pars restriction value
if ( COM_ParseInt ( & textPtr , & rest ) )
{
G_Printf ( S_COLOR_RED " Invalid restriction entry in %s! \n " , fileRoute ) ;
return ;
}
//Parse Location string
token = COM_ParseExt ( & textPtr , qfalse ) ;
if ( ! token [ 0 ] )
{
G_Printf ( S_COLOR_RED " Invalid string desc entry in %s! \n " , fileRoute ) ;
return ;
}
desc = token ;
//create a new entity
ent = G_Spawn ( ) ;
if ( ! ent )
{
G_Printf ( S_COLOR_RED " Couldn't create entity in %s! \n " , fileRoute ) ;
return ;
}
ent - > classname = " target_location " ;
//copy position data
VectorCopy ( origin , ent - > s . origin ) ;
VectorCopy ( angles , ent - > s . angles ) ;
//copy string
ent - > message = G_NewString ( desc ) ;
//copy desc into target as well
ent - > target = ent - > targetname = G_NewString ( desc ) ;
// copy restriction value
ent - > sound1to2 = rest ;
//G_Printf( S_COLOR_RED "Added string %s to entity %i.\n", ent->message, (int)(ent-g_entities) );
//initiate it as a location ent
SP_target_location ( ent ) ;
//reset the ent
ent = NULL ;
//--
token = COM_Parse ( & textPtr ) ;
}
} else if ( ! Q_strncmp ( token , " LocationsList " , 18 ) ) // old stly locations file
{
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: LocationsList had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
//expected format is "<origin> <angle> <string>"
while ( Q_strncmp ( token , " } " , 1 ) )
{
if ( ! token [ 0 ] )
break ;
//Parse origin
if ( COM_ParseVec3 ( & textPtr , origin ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
return ;
}
//Parse angles
if ( COM_ParseVec3 ( & textPtr , angles ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
return ;
}
//Parse Location string
token = COM_ParseExt ( & textPtr , qfalse ) ;
if ( ! token [ 0 ] )
{
G_Printf ( S_COLOR_RED " Invalid string desc entry in %s! \n " , fileRoute ) ;
return ;
}
desc = token ;
//create a new entity
ent = G_Spawn ( ) ;
if ( ! ent )
{
G_Printf ( S_COLOR_RED " Couldn't create entity in %s! \n " , fileRoute ) ;
return ;
}
ent - > classname = " target_location " ;
//copy position data
VectorCopy ( origin , ent - > s . origin ) ;
VectorCopy ( angles , ent - > s . angles ) ;
//copy string
ent - > message = G_NewString ( desc ) ;
//copy desc into target as well
ent - > target = ent - > targetname = G_NewString ( desc ) ;
//G_Printf( S_COLOR_RED "Added string %s to entity %i.\n", ent->message, (int)(ent-g_entities) );
//initiate it as a location ent
SP_target_location ( ent ) ;
//reset the ent
ent = NULL ;
//--
token = COM_Parse ( & textPtr ) ;
}
}
}
}
# else
static void G_LoadLocationsFile ( void )
{
char fileRoute [ MAX_QPATH ] ;
char mapRoute [ MAX_QPATH ] ;
char * serverInfo ;
fileHandle_t f ;
char * buffer ;
int file_len ;
char * textPtr , * token ;
vec3_t origin , angles ;
gentity_t * ent ;
char * desc ;
int rest ;
serverInfo = ( char * ) malloc ( MAX_INFO_STRING * sizeof ( char ) ) ;
if ( ! serverInfo ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , MAX_INFO_STRING * sizeof ( char ) ) ;
return ;
}
//get the map name out of the server data
trap_GetServerinfo ( serverInfo , MAX_INFO_STRING * sizeof ( char ) ) ;
//setup the file route
Com_sprintf ( mapRoute , sizeof ( mapRoute ) , " maps/%s " , Info_ValueForKey ( serverInfo , " mapname " ) ) ;
BG_LanguageFilename ( mapRoute , " locations " , fileRoute ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
free ( serverInfo ) ;
if ( ! file_len )
return ;
buffer = ( char * ) malloc ( 32000 * sizeof ( char ) ) ;
if ( ! buffer ) {
G_Printf ( S_COLOR_RED " ERROR: Was unable to allocate %i bytes. \n " , 32000 * sizeof ( char ) ) ;
trap_FS_FCloseFile ( f ) ;
return ;
}
trap_FS_Read ( buffer , file_len , f ) ;
if ( ! buffer [ 0 ] )
{
G_Printf ( S_COLOR_RED " ERROR: Couldn't read in file: %s! \n " , fileRoute ) ;
trap_FS_FCloseFile ( f ) ;
free ( buffer ) ;
return ;
}
buffer [ file_len ] = ' \0 ' ;
trap_FS_FCloseFile ( f ) ;
G_Printf ( " Locations file %s located. Proceeding to load scan data. \n " , fileRoute ) ; //GSIO01: why did this say "Usables file ..."? lol
COM_BeginParseSession ( ) ;
textPtr = buffer ;
while ( 1 )
{
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
break ;
if ( ! Q_strncmp ( token , " LocationsList2 " , 19 ) ) { // new style locations list with restricted locations
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: LocationsList2 had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
//expected format is "<origin> <angle> <int> <string>"
while ( Q_strncmp ( token , " } " , 1 ) )
{
if ( ! token [ 0 ] )
break ;
//Parse origin
if ( COM_ParseVec3 ( & textPtr , origin ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
//Parse angles
if ( COM_ParseVec3 ( & textPtr , angles ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
//Pars restriction value
if ( COM_ParseInt ( & textPtr , & rest ) )
{
G_Printf ( S_COLOR_RED " Invalid restriction entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
//Parse Location string
token = COM_ParseExt ( & textPtr , qfalse ) ;
if ( ! token [ 0 ] )
{
G_Printf ( S_COLOR_RED " Invalid string desc entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
desc = token ;
//create a new entity
ent = G_Spawn ( ) ;
if ( ! ent )
{
G_Printf ( S_COLOR_RED " Couldn't create entity in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
ent - > classname = " target_location " ;
//copy position data
VectorCopy ( origin , ent - > s . origin ) ;
VectorCopy ( angles , ent - > s . angles ) ;
//copy string
ent - > message = G_NewString ( desc ) ;
//copy desc into target as well
ent - > target = ent - > targetname = G_NewString ( desc ) ;
// copy restriction value
ent - > sound1to2 = rest ;
//G_Printf( S_COLOR_RED "Added string %s to entity %i.\n", ent->message, (int)(ent-g_entities) );
//initiate it as a location ent
SP_target_location ( ent ) ;
//reset the ent
ent = NULL ;
//--
token = COM_Parse ( & textPtr ) ;
}
} else if ( ! Q_strncmp ( token , " LocationsList " , 18 ) ) // old stly locations file
{
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: LocationsList had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
//expected format is "<origin> <angle> <string>"
while ( Q_strncmp ( token , " } " , 1 ) )
{
if ( ! token [ 0 ] )
break ;
//Parse origin
if ( COM_ParseVec3 ( & textPtr , origin ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
//Parse angles
if ( COM_ParseVec3 ( & textPtr , angles ) )
{
G_Printf ( S_COLOR_RED " Invalid origin entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
//Parse Location string
token = COM_ParseExt ( & textPtr , qfalse ) ;
if ( ! token [ 0 ] )
{
G_Printf ( S_COLOR_RED " Invalid string desc entry in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
desc = token ;
//create a new entity
ent = G_Spawn ( ) ;
if ( ! ent )
{
G_Printf ( S_COLOR_RED " Couldn't create entity in %s! \n " , fileRoute ) ;
free ( buffer ) ;
return ;
}
ent - > classname = " target_location " ;
//copy position data
VectorCopy ( origin , ent - > s . origin ) ;
VectorCopy ( angles , ent - > s . angles ) ;
//copy string
ent - > message = G_NewString ( desc ) ;
//copy desc into target as well
ent - > target = ent - > targetname = G_NewString ( desc ) ;
//G_Printf( S_COLOR_RED "Added string %s to entity %i.\n", ent->message, (int)(ent-g_entities) );
//initiate it as a location ent
SP_target_location ( ent ) ;
//reset the ent
ent = NULL ;
//--
token = COM_Parse ( & textPtr ) ;
}
}
}
free ( buffer ) ;
}
# endif
/*void G_initGroupsList(void)
{
char filename [ MAX_QPATH ] ;
char dirlist [ 4096 ] ;
int i ;
char * dirptr ;
char * race_list ;
int numdirs ;
int dirlen ;
memset ( group_list , 0 , sizeof ( group_list ) ) ;
group_count = 0 ;
// search through each and every skin we can find
//BOOKMARK
numdirs = trap_FS_GetFileList ( " models/players_rpgx " , " / " , dirlist , sizeof ( dirlist ) ) ;
dirptr = dirlist ;
for ( i = 0 ; i < numdirs ; i + + , dirptr + = dirlen + 1 )
{
dirlen = strlen ( dirptr ) ;
if ( dirlen & & dirptr [ dirlen - 1 ] = = ' / ' )
{
dirptr [ dirlen - 1 ] = ' \0 ' ;
}
if ( ! strcmp ( dirptr , " . " ) | | ! strcmp ( dirptr , " .. " ) )
{
continue ;
}
if ( group_count = = MAX_GROUP_MEMBERS )
{
G_Printf ( " Number of possible models larger than group array - limiting to first %d models \n " , MAX_GROUP_MEMBERS ) ;
break ;
}
// work out racename to
Com_sprintf ( filename , sizeof ( filename ) , " models/players_rpgx/%s/groups.cfg " , dirptr ) ;
race_list = BG_RegisterRace ( filename ) ;
Q_strncpyz ( group_list [ group_count ] . name , dirptr , sizeof ( group_list [ 0 ] . name ) ) ;
Q_strncpyz ( group_list [ group_count + + ] . text , race_list , sizeof ( group_list [ 0 ] . text ) ) ;
}
} */
# define MAX_GROUP_FILE_SIZE 5000
char * G_searchGroupList ( const char * name )
{
char * text_p = NULL , * slash = NULL ;
char text [ MAX_GROUP_FILE_SIZE ] ;
int i ;
char mod_name [ 200 ] ;
memset ( races , 0 , sizeof ( races ) ) ;
memset ( text , 0 , sizeof ( text ) ) ;
// check to see if there is a '/' in the name
Q_strncpyz ( mod_name , name , sizeof ( mod_name ) ) ;
slash = strstr ( mod_name , " / " ) ;
if ( slash ! = NULL )
{ //drop the slash and everything after it for the purpose of finding the model name in th group
* slash = 0 ;
}
// find the name in the group list
for ( i = 0 ; i < group_count ; i + + )
{
if ( ! Q_stricmp ( mod_name , group_list [ i ] . name ) )
{
text_p = group_list [ i ] . text ;
break ;
}
}
// did we find this group in the list?
if ( i = = group_count )
{
Com_sprintf ( races , sizeof ( races ) , " unknown " ) ;
}
else
{
Com_sprintf ( races , sizeof ( races ) , text_p ) ;
}
return races ;
}
/*
= = = = = = = = = = = = = = = =
G_FindTeams
Chain together all entities with a matching team field .
Entity teams are used for item groups and multi - entity mover groups .
All but the first will have the FL_TEAMSLAVE flag set and teammaster field set
All but the last will have the teamchain field set to the next one
= = = = = = = = = = = = = = = =
*/
void G_FindTeams ( void ) {
gentity_t * e , * e2 ;
int i , j ;
int c , c2 ;
c = 0 ;
c2 = 0 ;
for ( i = 1 , e = g_entities + i ; i < level . num_entities ; i + + , e + + ) {
if ( ! e - > inuse )
continue ;
if ( ! e - > team )
continue ;
if ( e - > flags & FL_TEAMSLAVE )
continue ;
if ( e - > classname & & Q_stricmp ( " func_door " , e - > classname ) ! = 0 )
{ //not a door
if ( Q_stricmp ( " 1 " , e - > team ) = = 0 | | Q_stricmp ( " 2 " , e - > team ) = = 0 )
{ //is trying to tell us it belongs to the TEAM_RED or TEAM_BLUE
continue ;
}
}
e - > teammaster = e ;
c + + ;
c2 + + ;
for ( j = i + 1 , e2 = e + 1 ; j < level . num_entities ; j + + , e2 + + )
{
if ( ! e2 - > inuse )
continue ;
if ( ! e2 - > team )
continue ;
if ( e2 - > flags & FL_TEAMSLAVE )
continue ;
if ( ! strcmp ( e - > team , e2 - > team ) )
{
c2 + + ;
e2 - > teamchain = e - > teamchain ;
e - > teamchain = e2 ;
e2 - > teammaster = e ;
e2 - > flags | = FL_TEAMSLAVE ;
// make sure that targets only point at the master
if ( e2 - > targetname ) {
e - > targetname = e2 - > targetname ;
e2 - > targetname = NULL ;
}
}
}
}
G_Printf ( " %i teams with %i entities \n " , c , c2 ) ;
}
/*
= = = = = = = = = = = = = = = = =
G_RegisterCvars
= = = = = = = = = = = = = = = = =
*/
void G_RegisterCvars ( void ) {
int i ;
cvarTable_t * cv ;
for ( i = 0 , cv = gameCvarTable ; i < gameCvarTableSize ; i + + , cv + + )
{
if ( rpg_rpg . integer ! = 0 )
{
trap_Cvar_Set ( " g_pModDisintegration " , " 0 " ) ;
trap_Cvar_Set ( " g_pModActionHero " , " 0 " ) ;
trap_Cvar_Set ( " g_pModSpecialties " , " 0 " ) ;
trap_Cvar_Set ( " g_pModAssimilation " , " 0 " ) ;
trap_Cvar_Set ( " g_gametype " , " 0 " ) ; //RPG-X: RedTechie - Make sure we keep gametype at 0
}
trap_Cvar_Register ( cv - > vmCvar , cv - > cvarName , cv - > defaultString , cv - > cvarFlags ) ;
if ( cv - > vmCvar )
{
cv - > modificationCount = cv - > vmCvar - > modificationCount ;
}
}
// check some things
if ( g_gametype . integer < 0 | | g_gametype . integer > = GT_MAX_GAME_TYPE ) {
G_Printf ( " g_gametype %i is out of range, defaulting to 0 \n " , g_gametype . integer ) ;
trap_Cvar_Set ( " g_gametype " , " 0 " ) ;
}
level . warmupModificationCount = g_warmup . modificationCount ;
}
/*
= = = = = = = = = = = = = = = = =
G_UpdateCvars
= = = = = = = = = = = = = = = = =
*/
void G_UpdateCvars ( void )
{
int i ;
cvarTable_t * cv ;
for ( i = 0 , cv = gameCvarTable ; i < gameCvarTableSize ; i + + , cv + + )
{
if ( cv - > vmCvar )
{
trap_Cvar_Update ( cv - > vmCvar ) ;
if ( cv - > modificationCount ! = cv - > vmCvar - > modificationCount )
{
cv - > modificationCount = cv - > vmCvar - > modificationCount ;
if ( cv - > trackChange )
{
if ( ! levelExiting )
{ //no need to do this during level changes
//RPG-X: J2J - Don't show gravity changed messages any more (for the gravity target ents)
if ( Q_stricmp ( cv - > cvarName , " g_gravity " ) ! = 0 )
{
trap_SendServerCommand ( - 1 , va ( " print \" Server: %s changed to %s \n \" " ,
cv - > cvarName , cv - > vmCvar - > string ) ) ;
}
}
}
}
}
}
}
extern int altAmmoUsage [ ] ;
extern team_t borgTeam ;
extern team_t initialBorgTeam ;
void G_InitModRules ( void )
{
numKilled = 0 ;
if ( g_pModDisintegration . integer ! = 0 )
{ //don't use up ammo in disintegration mode
altAmmoUsage [ WP_COMPRESSION_RIFLE ] = 0 ;
}
if ( g_pModSpecialties . integer ! = 0 )
{ //tripwires use more ammo
altAmmoUsage [ WP_GRENADE_LAUNCHER ] = 3 ;
}
if ( g_pModAssimilation . integer ! = 0 )
{
borgTeam = initialBorgTeam ;
}
}
extern qboolean G_CallSpawn ( gentity_t * ent ) ;
extern qboolean G_ParseField ( const char * key , const char * value , gentity_t * ent ) ;
/*
= = = = = = = = = = = =
G_LoadSpawnFile
If there is a spawn file it will parse it and spawn / change things .
Expected file Layout :
SpawnFile
{
Spawn
{
Entity
{
classname < string > //needs to be there
< key > < value > //unlimited number of keys and values
}
}
Convert
{
Entity
{
" Bmodel " " *<int> "
< key > < value >
}
Entity
{
" targetname " < string >
< key > < value >
}
Entity
{
" target " < string >
< key > < value >
}
}
Remove
{
Entity
{
" Bmodel " " *<int> "
}
Entity
{
" targetname " < string >
}
Entity
{
" target " < string >
}
}
}
= = = = = = = = = = = =
*/
void G_LoadSpawnFile ( void ) {
/* char fileRoute[MAX_QPATH];
char mapRoute [ MAX_QPATH ] ;
char serverInfo [ MAX_TOKEN_CHARS ] ;
fileHandle_t f ;
char buffer [ 29400 ] ;
int file_len ;
char * textPtr , * token ;
gentity_t * newEnt ;
char tempKey [ MAX_TOKEN_CHARS ] , tempValue [ MAX_TOKEN_CHARS ] ;
//vec3_t tempVec;
//int tempInt;
//float tempFloat;
//get the map name out of the server data
trap_GetServerinfo ( serverInfo , sizeof ( serverInfo ) ) ;
//setup the file route
Com_sprintf ( mapRoute , sizeof ( mapRoute ) , " maps/%s.%s " , Info_ValueForKey ( serverInfo , " mapname " ) , " spawn " ) ;
file_len = trap_FS_FOpenFile ( fileRoute , & f , FS_READ ) ;
if ( ! file_len )
return ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
trap_FS_Read ( buffer , file_len , f ) ;
buffer [ file_len ] = ' 0 ' ;
trap_FS_FCloseFile ( f ) ;
if ( ! buffer [ 0 ] ) {
G_Printf ( S_COLOR_RED " ERROR: Attempted to load %s, but no data was inside! \n " , fileRoute ) ;
return ;
}
G_Printf ( " Spawn file %s located. Proceeding to load scan data. \n " , fileRoute ) ;
COM_BeginParseSession ( ) ;
textPtr = buffer ;
while ( 1 ) {
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] )
break ;
while ( 1 ) {
token = COM_Parse ( & textPtr ) ;
if ( ! token [ 0 ] ) return ;
if ( ! Q_stricmpn ( token , " SpawnFile " , 9 ) ) {
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ! = 0 )
{
G_Printf ( S_COLOR_RED " ERROR: SpawnFile in %s had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
token = COM_Parse ( & textPtr ) ;
while ( Q_stricmpn ( token , " } " , 1 ) ) {
token = COM_Parse ( & textPtr ) ;
if ( ! Q_stricmpn ( token , " Spawn " , 5 ) ) {
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: Spawn block in %s had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
token = COM_Parse ( & textPtr ) ;
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & textPtr ) ;
if ( ! Q_stricmpn ( token , " Entity " , 6 ) ) {
if ( Q_strncmp ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED , " ERROR: Entity in %s had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
token = COM_Parse ( & textPtr ) ;
if ( ! Q_strncmp ( token , " classname " , 9 ) ) {
G_Printf ( S_COLOR_RED , " ERROR: First key in Entity in Spawn block in %s was not \" classname \" ! \n " , fileRoute ) ;
continue ;
}
newEnt = G_Spawn ( ) ;
if ( ! newEnt ) continue ;
newEnt - > tmpEntity = qtrue ;
token = COM_Parse ( & textPtr ) ;
newEnt - > classname = G_NewString ( token ) ;
// check if this entity is valid in Spawn block ...
if ( ! Q_strncmp ( newEnt - > classname , " func_ " , 5 ) // func entities are never valid as they need brushmodels
| | ! Q_strncmp ( newEnt - > classname , " misc_ " , 5 ) // misc entities are all invalid for now
) {
G_FreeEntity ( newEnt ) ;
G_Printf ( S_COLOR_RED " ERROR: Entities of type %s are invalid in Spawn Block! \n " , token ) ;
continue ;
}
while ( Q_strncmp ( token , " } " , 1 ) ) {
token = COM_Parse ( & textPtr ) ;
Com_sprintf ( tempKey , sizeof ( tempKey ) , " %s " , token ) ;
token = COM_Parse ( & textPtr ) ;
Com_sprintf ( tempValue , sizeof ( tempValue ) , " %s " , token ) ;
if ( ! G_ParseField ( tempKey , tempValue , newEnt ) ) {
//GSIO01: oh well not part of fields ehh?
//then let's see what entities this is and check if you are valid for it
}
}
}
}
} else if ( ! Q_strncmp ( token , " Convert " , 7 ) ) {
//all entities in here are converted as long as the wanted conversion is valid
//criterias might be:
// do both have a brushmodel?
// do both have a origin brush?
// and so on
//because we simply can't convert a info_notnull to a func_door xD
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: Convert block in %s had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
//There are 3 ways to identify an entity 100 percent accurate:
// by it's targetname (only if it is the only one with it)
// by it's target (only if it is the only one targeting it)
// by it's brushmodel (always 100% accurate but only works on brushentities)
//Entity IDs can't be used as loading the map locally or on a server
//might result in diffrent entity IDs.
} else if ( ! Q_strncmp ( token , " Remove " , 6 ) ) {
token = COM_Parse ( & textPtr ) ;
if ( Q_strncmp ( token , " { " , 1 ) ) {
G_Printf ( S_COLOR_RED " ERROR: Remove block in %s had no opening brace ( { )! \n " , fileRoute ) ;
continue ;
}
}
}
}
}
} */
}
static void Dev_ShowTriggers ( gentity_t * ent ) {
int i ;
gentity_t * tar ;
ent - > nextthink = level . time + 9500 ;
for ( i = 0 ; i < MAX_GENTITIES ; i + + ) {
if ( ( tar = & g_entities [ i ] ) = = NULL ) continue ;
if ( ! Q_stricmpn ( tar - > classname , " trigger_ " , 8 ) ) {
if ( ! Q_stricmp ( tar - > classname , " trigger_always " ) ) continue ;
if ( tar - > r . svFlags & SVF_NOCLIENT )
tar - > r . svFlags ^ = SVF_NOCLIENT ;
trap_LinkEntity ( ent ) ;
if ( ! Q_stricmpn ( tar - > classname , " trigger_push " , 13 ) )
G_AddEvent ( tar , EV_TRIGGER_SHOW , 1 ) ;
else
G_AddEvent ( tar , EV_TRIGGER_SHOW , 0 ) ;
}
}
}
/*
= = = = = = = = = = = =
G_InitGame
= = = = = = = = = = = =
*/
extern int lastKillTime [ ] ;
extern int LastFKRadius [ ] ; //(RPG-X J2J) added so array can be initialised to 0 first.
extern RPGX_SiteTOSiteData TransDat [ ] ; //(RPG-X J2J) added for tricorder transporter
extern RPGX_DragData DragDat [ ] ;
void G_InitGame ( int levelTime , int randomSeed , int restart ) {
int i ; //,j;
//vec3_t Zero = {0.0,0.0,0.0}; //RPG-X J2J //TiM - use vec3_origin instead
gentity_t * SpawnPnt ; //RPG-X J2J
char fileName [ MAX_QPATH ] ;
float messageTime ;
G_Printf ( " ------- Game Initialization ------- \n " ) ;
G_Printf ( " gamename: %s \n " , GAMEVERSION ) ;
G_Printf ( " gamedate: %s \n " , __DATE__ ) ;
init_tonextint ( qtrue ) ;
srand ( randomSeed ) ;
numKilled = 0 ;
level . numObjectives = 0 ; //no objectives by default
G_RegisterCvars ( ) ;
G_ProcessIPBans ( ) ;
G_ProcessIDBans ( ) ;
G_InitMemory ( ) ;
//G_initGroupsList();
BG_LoadItemNames ( ) ;
// set some level globals
memset ( & level , 0 , sizeof ( level ) ) ;
//Class loader
memset ( fileName , 0 , sizeof ( fileName ) ) ;
Com_sprintf ( fileName , sizeof ( fileName ) , " ext_data/classes/%s.classes " , rpg_classSet . string ) ;
if ( ! G_LoadClassData ( fileName ) )
{
G_Printf ( S_COLOR_RED " ERROR: Could not load class set %s. Reverting to default. \n " , fileName ) ;
trap_Cvar_Set ( " rpg_classSet " , CLASS_DEFAULT ) ;
if ( ! G_LoadClassData ( va ( " ext_data/classes/%s.classes " , CLASS_DEFAULT ) ) )
{
G_Error ( " Could not load default class set: %s " , CLASS_DEFAULT ) ;
}
}
//Rank Loader
memset ( fileName , 0 , sizeof ( fileName ) ) ;
Com_sprintf ( fileName , sizeof ( fileName ) , " ext_data/ranksets/%s.ranks " , rpg_rankSet . string ) ;
if ( ! BG_ParseRankNames ( fileName , g_rankNames ) )
{
G_Printf ( S_COLOR_RED " ERROR: Could not load rankset %s. Reverting to default. \n " , fileName ) ;
trap_Cvar_Set ( " rpg_rankSet " , RANKSET_DEFAULT ) ;
if ( ! BG_ParseRankNames ( va ( " ext_data/ranksets/%s.ranks " , RANKSET_DEFAULT ) , g_rankNames ) )
{
G_Error ( " Could not load default rankset: %s " , RANKSET_DEFAULT ) ;
}
}
level . time = levelTime ;
level . startTime = levelTime ;
level . restarted = restart ;
//level.message = levelTime - (int)(rpg_timedmessagetime.value * 60000) + 30000;
if ( rpg_timedmessagetime . value < 0.2 ) {
messageTime = 0.2 ;
} else {
messageTime = rpg_timedmessagetime . value ;
}
level . message = levelTime + ( messageTime * 60000 ) ;
level . snd_fry = G_SoundIndex ( " sound/player/fry.wav " ) ; // FIXME standing in lava / slime
if ( g_gametype . integer ! = GT_SINGLE_PLAYER & & g_log . string [ 0 ] ) {
if ( g_logSync . integer ) {
trap_FS_FOpenFile ( g_log . string , & level . logFile , FS_APPEND_SYNC ) ;
} else {
trap_FS_FOpenFile ( g_log . string , & level . logFile , FS_APPEND ) ;
}
if ( ! level . logFile ) {
G_Printf ( " WARNING: Couldn't open logfile: %s \n " , g_log . string ) ;
} else {
char serverinfo [ MAX_INFO_STRING ] ;
trap_GetServerinfo ( serverinfo , sizeof ( serverinfo ) ) ;
G_LogPrintf ( " ------------------------------------------------------------ \n " ) ;
G_LogPrintf ( " InitGame: %s \n " , serverinfo ) ;
}
} else {
G_Printf ( " Not logging to disk. \n " ) ;
}
# ifdef G_LUA
G_LuaInit ( ) ;
# endif
G_LogWeaponInit ( ) ;
G_InitWorldSession ( ) ;
// initialize all entities for this game
memset ( g_entities , 0 , MAX_GENTITIES * sizeof ( g_entities [ 0 ] ) ) ;
level . gentities = g_entities ;
// initialize all clients for this game
level . maxclients = g_maxclients . integer ;
memset ( g_clients , 0 , MAX_CLIENTS * sizeof ( g_clients [ 0 ] ) ) ;
level . clients = g_clients ;
// set client fields on player ents
for ( i = 0 ; i < level . maxclients ; i + + ) {
g_entities [ i ] . client = level . clients + i ;
}
// always leave room for the max number of clients,
// even if they aren't all used, so numbers inside that
// range are NEVER anything but clients
level . num_entities = MAX_CLIENTS ;
// let the server system know where the entites are
trap_LocateGameData ( level . gentities , level . num_entities , sizeof ( gentity_t ) ,
& level . clients [ 0 ] . ps , sizeof ( level . clients [ 0 ] ) ) ;
// reserve some spots for dead player bodies
InitBodyQue ( ) ;
ClearRegisteredItems ( ) ;
// parse the map usables file
G_SetupUsablesStrings ( ) ;
// parse the key/value pairs and spawn gentities
G_SpawnEntitiesFromString ( ) ;
//TiM: load a locations file, whereever possible
G_LoadLocationsFile ( ) ;
//GSIO: load server change file if avaible
G_LoadServerChangeFile ( ) ;
//GSIO: load map change file if avaible
G_LoadMapChangeFile ( ) ;
//GSIO: load holodeck file if avaible
G_LoadHolodeckFile ( ) ;
// general initialization
G_FindTeams ( ) ;
// make sure we have flags for CTF, etc
G_CheckTeamItems ( ) ;
SaveRegisteredItems ( ) ;
G_Printf ( " ----------------------------------- \n " ) ;
if ( g_gametype . integer = = GT_SINGLE_PLAYER | | trap_Cvar_VariableIntegerValue ( " com_buildScript " ) ) {
G_ModelIndex ( SP_PODIUM_MODEL ) ;
G_SoundIndex ( " sound/player/gurp1.wav " ) ;
G_SoundIndex ( " sound/player/gurp2.wav " ) ;
}
if ( g_gametype . integer > = GT_TEAM | | trap_Cvar_VariableIntegerValue ( " com_buildScript " ) )
{
G_ModelIndex ( TEAM_PODIUM_MODEL ) ;
}
if ( trap_Cvar_VariableIntegerValue ( " bot_enable " ) ) {
BotAISetup ( restart ) ;
BotAILoadMap ( restart ) ;
G_InitBots ( restart ) ;
}
G_InitModRules ( ) ;
levelExiting = qfalse ;
/*RPG-X J2J************************************************************************************/
G_Printf ( " Initializing RPG-X Globals... " ) ;
SpawnPnt = SelectRandomSpawnPoint ( ) ; //Grab a random spawn point.
//TiM : Reset teh recon system on game init.
//Leave this out for now to make this data persistant.
//Altho, make sure to init the arrays before actually using lol
//memset( &g_reconData, 0, sizeof( g_reconData ) );
//g_reconNum = 0;
//WARNING - used hard coded number to shut up compiler, 1023 is MAX_ENTITIES (which apperently cant be increased without substansial exe recoding)
//TiM : NB Ents 0 -> 128 are clients only. cyclicng thru all ents here is not needed.
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
//g_entities[i].last_tr116_fire = 0;
//RPG-X: Redtechie - Make sure score cant be chnaged unless other wise told to
if ( g_entities [ i ] . client ) {
g_entities [ i ] . client - > UpdateScore = qfalse ;
g_entities [ i ] . client - > AdminFailed = 0 ; // RPG-X | Phenix | 21/11/2004 | Init Admin Failed Integer
g_entities [ i ] . client - > LoggedAsAdmin = qfalse ;
g_entities [ i ] . client - > LoggedAsDeveloper = qfalse ;
}
}
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
lastKillTime [ i ] = level . time - 30000 ;
//FKR
LastFKRadius [ i ] = level . time - rpg_forcekillradiuswaittime . integer ;
//Transporter
memset ( & TransDat [ i ] , 0 , sizeof ( TransDat [ i ] ) ) ;
TransDat [ i ] . LastClick = level . time - 5000 ; //Make last click current time less 5 seconds.
//TransDat[i].Used = qfalse; //And set both site to site and tricorder to unused.
//TransDat[i].pUsed = qfalse;
//And Zero the vectors
//Huh... why couldn't we use the memset func
//here for most of those =0 statements?
/*VectorCopy(vec3_origin, TransDat[i].TransCoord);
VectorCopy ( vec3_origin , TransDat [ i ] . TransCoordRot ) ;
VectorCopy ( vec3_origin , TransDat [ i ] . pTransCoord ) ;
VectorCopy ( vec3_origin , TransDat [ i ] . pTransCoordRot ) ; */
//TransDat[i].beamed = qfalse;
//TransDat[i].beamer = -1;
//TransDat[i].beamTime = 0;
//Drag Data
DragDat [ i ] . AdminId = - 1 ;
//DragDat[i].distance = 0.0f;
}
//Couldn't think of anywhere else for this, so here it goes.
//TiM - WTF? You can't cache multimedia assets like that in the game module. O_o
//The server couldn't care less about playing sounds. No one would hear them >.<
//n00bsnd = trap_S_RegisterSound("sound\n00b.mp3");
//RPG-X: RedTechie - Set Shake cvars back to normal just to stop hacking
//trap_SendConsoleCommand( EXEC_APPEND, "set rpg_servershakeallclients 0\n" );
//trap_SendConsoleCommand( EXEC_APPEND, "set rpg_servershakeallclientsintensity 2\n" );
// check for remap file, load and apply if one if found
//G_LoadShaderRemaps();
//Check spawn file - not in this release yet
//G_ParseSpawnFile();
G_Printf ( " %i entities loaded. \n " , level . num_entities ) ;
G_Printf ( " COMPLETED \n " ) ;
# ifdef G_LUA
LuaHook_G_InitGame ( levelTime , randomSeed , restart ) ;
# endif
if ( dev_showTriggers . integer & & ! restart ) {
gentity_t * t ;
t = G_Spawn ( ) ;
if ( t ) {
t - > think = Dev_ShowTriggers ;
t - > nextthink = level . time + 1000 ;
}
}
/*************************************************************************************************/
G_Printf ( " ,. \n " ) ; G_Printf ( " ..:, :Xt. ,:. \n " ) ;
G_Printf ( " ,=+t: .IRX= :++=. \n " ) ; G_Printf ( " .=iVt:. :RYYI. .itt+ \n " ) ;
G_Printf ( " .:tXI=;. tRtiV; ,IYY:. \n " ) ; G_Printf ( " .+;ii=;. ,XVi+Vt. :tIi+ \n " ) ;
G_Printf ( " .;ti;;:. +RI++IY, ,+tt=. \n " ) ; G_Printf ( " ,++YY;. ,XXi+++X= ;IYI=. \n " ) ;
G_Printf ( " ;ttY+;. .,=iVRI++++YX+;. ;VYt; \n " ) ; G_Printf ( " .;ii+=, .;IXRRXVi++++iVRXVi:. ,=iii. \n " ) ;
G_Printf ( " .==;ti, .;YRRVVXYii+++++IVIVRXt, ,+=tI= \n " ) ; G_Printf ( " .iitY=, .tRRVXXVRV+++ii++YRXVIYXV; :tYti, \n " ) ;
G_Printf ( " .+iii=,,IBVVXYiiXViiiiiiitVtIXViVR= ,+t+I: \n " ) ; G_Printf ( " =+=I:.tBVXVt=;tRIiiiiiiiiXi:=YXiIX; :+=It; \n " ) ;
G_Printf ( " .;;tYt:;RVVV+=:,YRiiiiiiiiiYI,.:IXiVY..+IYi= \n " ) ; G_Printf ( " .ti=t+;tRIXi;, :XViiiiiiiiiIV: ,YViX=.:titt. \n " ) ;
G_Printf ( " iY++I;YVYY=: +BIiiiiiiiiiiX= +XiVi;i++Vi, \n " ) ; G_Printf ( " ,+YYYI:VYYY;. .YRiiiiiiiiiiiVt. ;RIYt:IIVVi: \n " ) ;
G_Printf ( " ,+tYXi;YVIX; ;RVtiiiiIXXtiiVI, iRIVt,=XVit: \n " ) ; G_Printf ( " .+iiti++XiXI. iBIiiiiYXIIXtiIV: :XXIV++;i+iI;. \n " ) ;
G_Printf ( " ;Ii=ii:VYtRi,VRtiiiVVi=;IXitX=;VBYXI=i+;iV+;. \n " ) ; G_Printf ( " ;tYtVt;;XYIRXBVttiVV+;:.:VYiXVRBVXY+;+IYVt+, \n " ) ;
G_Printf ( " =iiItii,=XVIRRIttXV+=:..,tRtVBXVRI+=i:iIit+. \n " ) ; G_Printf ( " :t==++I:.=YXYIIiYBXYIttIVRBYtVXXI+;;t+;;+Y=, \n " ) ;
G_Printf ( " +I=;+Y= .:IRItYIVXRRRBBRXXVIRY+=;.:i=;iVi;. \n " ) ; G_Printf ( " .+IYVV+: +BYXXVXXXXXXXXXVRVVi;:.:;tVYY+=: \n " ) ;
G_Printf ( " .+ttii+ .IBXY++ittIIIti++tXXi, .++=tI+;: \n " ) ; G_Printf ( " ;YYtIY;;VBI+;:,::;;;;;:,:IBt,::tItYV=. \n " ) ;
G_Printf ( " =IYYI++ti+;, ....... :Xt;i=iYYI+;. \n " ) ; G_Printf ( " .:+i++ii;;. .=i=+i=t+;;:. \n " ) ;
G_Printf ( " ,tYIVI==:,.. ..,;=+iYIVt:.. \n " ) ; G_Printf ( " ,itt+iIYYti;. ,;itYIIt:iIi=;. \n " ) ;
G_Printf ( " .:;;:+tIIVIi:.;iYYIii+=:,;;:. \n " ) ; G_Printf ( " . ,:=itIXi.tXYit=;::, . \n " ) ;
G_Printf ( " .+tti=,,iIt+;. \n " ) ; G_Printf ( " .:;;:. ,;;;:. \n " ) ;
}
extern void G_RestoreClientInitialStatus ( gentity_t * ent ) ;
extern int borgQueenClientNum ;
void G_CheckResetAssimilationClients ( void )
{
if ( g_pModAssimilation . integer ! = 0 )
{
gentity_t * ent ;
int i ;
//clear current queen
borgQueenClientNum = - 1 ;
//put the assimilated players back on their original team and class
for ( i = 0 ; i < level . maxclients ; i + + )
{
ent = & g_entities [ i ] ;
if ( ent - > client & & ent - > inuse )
{
G_RestoreClientInitialStatus ( ent ) ;
}
}
//clear borg team
borgTeam = initialBorgTeam ;
}
}
void EliminationRespawn ( gentity_t * ent , char * team ) ;
void G_CheckResetEliminationClients ( void )
{
if ( g_pModElimination . integer ! = 0 )
{ //no players respawn when in elimination
gentity_t * client ;
int i ;
for ( i = 0 ; i < level . numConnectedClients ; i + + )
{
client = & g_entities [ & level . clients [ level . sortedClients [ i ] ] - level . clients ] ;
if ( client - > team & & client - > client - > sess . sessionTeam = = TEAM_SPECTATOR )
{
EliminationRespawn ( client , client - > team ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = =
G_ShutdownGame
= = = = = = = = = = = = = = = = =
*/
void G_ShutdownGame ( int restart ) {
G_CheckResetAssimilationClients ( ) ;
G_CheckResetEliminationClients ( ) ;
G_Printf ( " ==== ShutdownGame ==== \n " ) ;
# ifdef G_LUA
LuaHook_G_Shutdown ( restart ) ;
G_LuaShutdown ( ) ;
# endif
#if 0 // kef -- Pat sez this is causing some trouble these days
G_LogWeaponOutput ( ) ;
# endif
if ( level . logFile ) {
G_LogPrintf ( " ShutdownGame: \n " ) ;
G_LogPrintf ( " ------------------------------------------------------------ \n " ) ;
trap_FS_FCloseFile ( level . logFile ) ;
}
// write all the client session data so we can get it back
G_WriteSessionData ( ) ;
if ( trap_Cvar_VariableIntegerValue ( " bot_enable " ) ) {
BotAIShutdown ( restart ) ;
}
}
//===================================================================
# ifndef GAME_HARD_LINKED
// this is only here so the functions in q_shared.c and bg_*.c can link
void QDECL Com_Error ( int errlevel , const char * error , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , error ) ;
vsprintf ( text , error , argptr ) ;
va_end ( argptr ) ;
G_Error ( " %s " , text ) ;
}
void QDECL Com_Printf ( const char * msg , . . . ) {
va_list argptr ;
char text [ 1024 ] ;
va_start ( argptr , msg ) ;
vsprintf ( text , msg , argptr ) ;
va_end ( argptr ) ;
G_Printf ( " %s " , text ) ;
}
# endif
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PLAYER COUNTING / SCORE SORTING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = =
AddTournamentPlayer
If there are less than two tournament players , put a
spectator in the game and restart
= = = = = = = = = = = = =
*/
void AddTournamentPlayer ( void ) {
int i ;
gclient_t * client ;
gclient_t * nextInLine ;
clientSession_t * sess ;
if ( level . numPlayingClients > = 2 ) {
return ;
}
// never change during intermission
if ( level . intermissiontime ) {
return ;
}
nextInLine = NULL ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
client = & level . clients [ i ] ;
if ( client - > pers . connected ! = CON_CONNECTED ) {
continue ;
}
sess = & client - > sess ;
if ( sess - > sessionTeam ! = TEAM_SPECTATOR ) {
continue ;
}
// never select the dedicated follow or scoreboard clients
if ( sess - > spectatorState = = SPECTATOR_SCOREBOARD | |
sess - > spectatorClient < 0 ) {
continue ;
}
if ( ! nextInLine | | sess - > spectatorTime < nextInLine - > sess . spectatorTime ) {
nextInLine = client ;
}
}
if ( ! nextInLine ) {
return ;
}
level . warmupTime = - 1 ;
// set them to free-for-all team
SetTeam ( & g_entities [ nextInLine - level . clients ] , " f " ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = =
RemoveTournamentLoser
Make the loser a spectator at the back of the line
= = = = = = = = = = = = = = = = = = = = = = =
*/
void RemoveTournamentLoser ( void ) {
int clientNum ;
if ( level . numPlayingClients ! = 2 ) {
return ;
}
clientNum = level . sortedClients [ 1 ] ;
if ( level . clients [ clientNum ] . pers . connected ! = CON_CONNECTED ) {
return ;
}
// make them a spectator
SetTeam ( & g_entities [ clientNum ] , " s " ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = =
AdjustTournamentScores
= = = = = = = = = = = = = = = = = = = = = = =
*/
void AdjustTournamentScores ( void ) {
int clientNum ;
clientNum = level . sortedClients [ 0 ] ;
if ( level . clients [ clientNum ] . pers . connected = = CON_CONNECTED ) {
level . clients [ clientNum ] . sess . wins + + ;
ClientUserinfoChanged ( clientNum ) ;
}
clientNum = level . sortedClients [ 1 ] ;
if ( level . clients [ clientNum ] . pers . connected = = CON_CONNECTED ) {
level . clients [ clientNum ] . sess . losses + + ;
ClientUserinfoChanged ( clientNum ) ;
}
}
/*
= = = = = = = = = = = = =
SortRanks
= = = = = = = = = = = = =
*/
int QDECL SortRanks ( const void * a , const void * b ) {
gclient_t * ca , * cb ;
ca = & level . clients [ * ( int * ) a ] ;
cb = & level . clients [ * ( int * ) b ] ;
// sort special clients last
if ( ca - > sess . spectatorState = = SPECTATOR_SCOREBOARD | | ca - > sess . spectatorClient < 0 ) {
return 1 ;
}
if ( cb - > sess . spectatorState = = SPECTATOR_SCOREBOARD | | cb - > sess . spectatorClient < 0 ) {
return - 1 ;
}
// then connecting clients
if ( ca - > pers . connected = = CON_CONNECTING ) {
return 1 ;
}
if ( cb - > pers . connected = = CON_CONNECTING ) {
return - 1 ;
}
// then spectators
if ( ca - > sess . sessionTeam = = TEAM_SPECTATOR & & cb - > sess . sessionTeam = = TEAM_SPECTATOR ) {
if ( ca - > sess . spectatorTime < cb - > sess . spectatorTime ) {
return - 1 ;
}
if ( ca - > sess . spectatorTime > cb - > sess . spectatorTime ) {
return 1 ;
}
return 0 ;
}
if ( ca - > sess . sessionTeam = = TEAM_SPECTATOR ) {
return 1 ;
}
if ( cb - > sess . sessionTeam = = TEAM_SPECTATOR ) {
return - 1 ;
}
// then sort by score & number of times killed
if ( ca - > ps . persistant [ PERS_SCORE ]
> cb - > ps . persistant [ PERS_SCORE ] ) {
return - 1 ;
}
if ( ( ca - > ps . persistant [ PERS_SCORE ] = = cb - > ps . persistant [ PERS_SCORE ] ) & &
( ca - > ps . persistant [ PERS_KILLED ] < cb - > ps . persistant [ PERS_KILLED ] ) )
{ return - 1 ; }
if ( ca - > ps . persistant [ PERS_SCORE ]
< cb - > ps . persistant [ PERS_SCORE ] ) {
return 1 ;
}
if ( ( ca - > ps . persistant [ PERS_SCORE ] = = cb - > ps . persistant [ PERS_SCORE ] ) & &
( ca - > ps . persistant [ PERS_KILLED ] > cb - > ps . persistant [ PERS_KILLED ] ) )
{ return 1 ; }
return 0 ;
}
/*
= = = = = = = = = = = =
CalculateRanks
Recalculates the score ranks of all players
This will be called on every client connect , begin , disconnect , death ,
and team change .
FIXME : for elimination , the last man standing must be ranked first
= = = = = = = = = = = =
*/
void CalculateRanks ( qboolean fromExit ) {
int i ;
int rank ;
int score ;
int newScore ;
gclient_t * cl ;
level . follow1 = - 1 ;
level . follow2 = - 1 ;
level . numConnectedClients = 0 ;
level . numNonSpectatorClients = 0 ;
level . numPlayingClients = 0 ;
level . numVotingClients = 0 ; // don't count bots
for ( i = 0 ; i < level . maxclients ; i + + ) {
if ( level . clients [ i ] . pers . connected ! = CON_DISCONNECTED ) {
level . sortedClients [ level . numConnectedClients ] = i ;
level . numConnectedClients + + ;
if ( level . clients [ i ] . sess . sessionTeam ! = TEAM_SPECTATOR ) {
level . numNonSpectatorClients + + ;
// decide if this should be auto-followed
if ( level . clients [ i ] . pers . connected = = CON_CONNECTED ) {
level . numPlayingClients + + ;
if ( ! ( g_entities [ i ] . r . svFlags & SVF_BOT ) ) {
level . numVotingClients + + ;
}
if ( level . follow1 = = - 1 ) {
level . follow1 = i ;
} else if ( level . follow2 = = - 1 ) {
level . follow2 = i ;
}
}
}
}
}
qsort ( level . sortedClients , level . numConnectedClients ,
sizeof ( level . sortedClients [ 0 ] ) , SortRanks ) ;
// set the rank value for all clients that are connected and not spectators
if ( g_gametype . integer > = GT_TEAM ) {
// in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
for ( i = 0 ; i < level . numConnectedClients ; i + + ) {
cl = & level . clients [ level . sortedClients [ i ] ] ;
if ( level . teamScores [ TEAM_RED ] = = level . teamScores [ TEAM_BLUE ] ) {
cl - > ps . persistant [ PERS_RANK ] = 2 ;
} else if ( level . teamScores [ TEAM_RED ] > level . teamScores [ TEAM_BLUE ] ) {
cl - > ps . persistant [ PERS_RANK ] = 0 ;
} else {
cl - > ps . persistant [ PERS_RANK ] = 1 ;
}
}
} else {
rank = - 1 ;
score = 0 ;
for ( i = 0 ; i < level . numPlayingClients ; i + + ) {
cl = & level . clients [ level . sortedClients [ i ] ] ;
newScore = cl - > ps . persistant [ PERS_SCORE ] ;
if ( i = = 0 | | newScore ! = score ) {
rank = i ;
// assume we aren't tied until the next client is checked
level . clients [ level . sortedClients [ i ] ] . ps . persistant [ PERS_RANK ] = rank ;
} else {
// we are tied with the previous client
level . clients [ level . sortedClients [ i - 1 ] ] . ps . persistant [ PERS_RANK ] = rank | RANK_TIED_FLAG ;
level . clients [ level . sortedClients [ i ] ] . ps . persistant [ PERS_RANK ] = rank | RANK_TIED_FLAG ;
}
score = newScore ;
if ( g_gametype . integer = = GT_SINGLE_PLAYER & & level . numPlayingClients = = 1 ) {
level . clients [ level . sortedClients [ i ] ] . ps . persistant [ PERS_RANK ] = rank | RANK_TIED_FLAG ;
}
}
}
// set the CS_SCORES1/2 configstrings, which will be visible to everyone
if ( g_gametype . integer > = GT_TEAM ) {
trap_SetConfigstring ( CS_SCORES1 , va ( " %i " , level . teamScores [ TEAM_RED ] ) ) ;
trap_SetConfigstring ( CS_SCORES2 , va ( " %i " , level . teamScores [ TEAM_BLUE ] ) ) ;
} else {
if ( level . numConnectedClients = = 0 ) {
trap_SetConfigstring ( CS_SCORES1 , va ( " %i " , SCORE_NOT_PRESENT ) ) ;
trap_SetConfigstring ( CS_SCORES2 , va ( " %i " , SCORE_NOT_PRESENT ) ) ;
} else if ( level . numConnectedClients = = 1 ) {
trap_SetConfigstring ( CS_SCORES1 , va ( " %i " , level . clients [ level . sortedClients [ 0 ] ] . ps . persistant [ PERS_SCORE ] ) ) ;
trap_SetConfigstring ( CS_SCORES2 , va ( " %i " , SCORE_NOT_PRESENT ) ) ;
} else {
trap_SetConfigstring ( CS_SCORES1 , va ( " %i " , level . clients [ level . sortedClients [ 0 ] ] . ps . persistant [ PERS_SCORE ] ) ) ;
trap_SetConfigstring ( CS_SCORES2 , va ( " %i " , level . clients [ level . sortedClients [ 1 ] ] . ps . persistant [ PERS_SCORE ] ) ) ;
}
}
// see if it is time to end the level
if ( ! fromExit )
{ //not coming this from the CheckExitRules func
CheckExitRules ( ) ;
}
// if we are at the intermission, send the new info to everyone
if ( level . intermissiontime ) {
SendScoreboardMessageToAllClients ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MAP CHANGING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = = = =
SendScoreboardMessageToAllClients
Do this at BeginIntermission time and whenever ranks are recalculated
due to enters / exits / forced team changes
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void SendScoreboardMessageToAllClients ( void ) {
int i ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
if ( level . clients [ i ] . pers . connected = = CON_CONNECTED ) {
DeathmatchScoreboardMessage ( g_entities + i ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
MoveClientToIntermission
When the intermission starts , this will be called for all players .
If a new client connects , this will be called after the spawn function .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void MoveClientToIntermission ( gentity_t * ent ) {
entityState_t * es = & ent - > s ;
playerState_t * ps = & ent - > client - > ps ;
// take out of follow mode if needed
if ( ent - > client - > sess . spectatorState = = SPECTATOR_FOLLOW ) {
StopFollowing ( ent ) ;
}
// move to the spot
VectorCopy ( level . intermission_origin , es - > origin ) ;
VectorCopy ( level . intermission_origin , ps - > origin ) ;
VectorCopy ( level . intermission_angle , ps - > viewangles ) ;
ps - > pm_type = PM_INTERMISSION ;
ps - > eFlags ^ = EF_TELEPORT_BIT ;
// clean up powerup info
memset ( ps - > powerups , 0 , sizeof ( ps - > powerups ) ) ;
ps - > eFlags = 0 ;
es - > eFlags = 0 ;
es - > eType = ET_GENERAL ;
es - > modelindex = 0 ;
es - > loopSound = 0 ;
es - > event = 0 ;
ent - > r . contents = 0 ;
}
/*
= = = = = = = = = = = = = = = = = =
FindIntermissionPoint
This is also used for spectator spawns
= = = = = = = = = = = = = = = = = =
*/
void FindIntermissionPoint ( void ) {
gentity_t * ent , * target ;
vec3_t dir ;
// find the intermission spot
ent = G_Find ( NULL , FOFS ( classname ) , " info_player_intermission " ) ;
if ( ! ent ) { // the map creator forgot to put in an intermission point...
SelectSpawnPoint ( vec3_origin , level . intermission_origin , level . intermission_angle ) ;
} else {
VectorCopy ( ent - > s . origin , level . intermission_origin ) ;
VectorCopy ( ent - > s . angles , level . intermission_angle ) ;
// if it has a target, look towards it
if ( ent - > target ) {
target = G_PickTarget ( ent - > target ) ;
if ( target ) {
VectorSubtract ( target - > s . origin , level . intermission_origin , dir ) ;
vectoangles ( dir , level . intermission_angle ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = =
ClearFiringFlags
= = = = = = = = = = = = = = = = = =
*/
void ClearFiringFlags ( )
{
int i = 0 ;
gentity_t * ent = NULL ;
for ( i = 0 ; i < level . maxclients ; i + + )
{
ent = g_entities + i ;
if ( ! ent - > inuse )
continue ;
// clear the firing flag
if ( ent - > client )
{
ent - > client - > ps . eFlags & = ~ EF_FIRING ;
}
}
}
/*
= = = = = = = = = = = = = = = = = =
BeginIntermission
= = = = = = = = = = = = = = = = = =
*/
void BeginIntermission ( void ) {
int i ;
gentity_t * client ;
qboolean doingLevelshot ;
if ( level . intermissiontime = = - 1 )
doingLevelshot = qtrue ;
else
doingLevelshot = qfalse ;
if ( level . intermissiontime & & level . intermissiontime ! = - 1 ) {
return ; // already active
}
G_CheckResetEliminationClients ( ) ;
// if in tournament mode, change the wins / losses
if ( g_gametype . integer = = GT_TOURNAMENT ) {
AdjustTournamentScores ( ) ;
}
level . intermissiontime = level . time ;
FindIntermissionPoint ( ) ;
// kef -- make sure none of the players are still firing (cuz we don't want weapons fx going off while
//they're on the podium)
ClearFiringFlags ( ) ;
// cdr - Want to generate victory pads for all game types - except level shots (gametype 10)
UpdateTournamentInfo ( ) ;
if ( ! doingLevelshot )
SpawnModelsOnVictoryPads ( ) ;
// move all clients to the intermission point
for ( i = 0 ; i < level . maxclients ; i + + ) {
client = g_entities + i ;
if ( ! client - > inuse )
continue ;
// respawn if dead
//if ( BG_BorgTransporting( &client->client->ps ) )
//{//in borg teleport fly around mode, turn it off
// client->client->ps.stats[STAT_USEABLE_PLACED] = 0;
// client->client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
// client->client->ps.eFlags &= ~EF_NODRAW;
// client->s.eFlags &= ~EF_NODRAW;
// client->flags &= ~FL_NOTARGET;
//}
if ( client - > health < = 0 ) {
respawn ( client ) ;
}
MoveClientToIntermission ( client ) ;
}
// send the current scoring to all clients
SendScoreboardMessageToAllClients ( ) ;
}
void G_ClearObjectives ( void )
{
gentity_t * tent ;
tent = G_TempEntity ( vec3_origin , EV_OBJECTIVE_COMPLETE ) ;
//Be sure to send the event to everyone
tent - > r . svFlags | = SVF_BROADCAST ;
tent - > s . eventParm = 0 ; //tells it to clear all
}
/*
= = = = = = = = = = = = =
ExitLevel
When the intermission has been exited , the server is either killed
or moved to a new level based on the " nextmap " cvar
= = = = = = = = = = = = =
*/
qboolean levelExiting = qfalse ;
void ExitLevel ( void ) {
int i ;
levelExiting = qtrue ;
//bot interbreeding
BotInterbreedEndMatch ( ) ;
G_ClearObjectives ( ) ;
// if we are running a tournement map, kick the loser to spectator status,
// which will automatically grab the next spectator and restart
if ( g_gametype . integer = = GT_TOURNAMENT ) {
if ( ! level . restarted ) {
RemoveTournamentLoser ( ) ;
trap_SendConsoleCommand ( EXEC_APPEND , " map_restart 0 \n " ) ;
level . restarted = qtrue ;
level . changemap = NULL ;
level . intermissiontime = 0 ;
}
return ;
}
trap_SendConsoleCommand ( EXEC_APPEND , " vstr nextmap \n " ) ;
level . changemap = NULL ;
level . intermissiontime = 0 ;
//don't reset the bots until after level.intermission is off so that it doesn't send 5 billion score updates
G_CheckResetAssimilationClients ( ) ;
// we need to do this here before chaning to CON_CONNECTING
G_WriteSessionData ( ) ;
// change all client states to connecting, so the early players into the
// next level will know the others aren't done reconnecting
for ( i = 0 ; i < g_maxclients . integer ; i + + ) {
if ( level . clients [ i ] . pers . connected = = CON_CONNECTED ) {
level . clients [ i ] . pers . connected = CON_CONNECTING ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
CheckIntermissionExit
The level will stay at the intermission for a minimum of 5 seconds
If all players wish to continue , the level will then exit .
If one or more players have not acknowledged the continue , the game will
wait 20 seconds before going on .
= = = = = = = = = = = = = = = = =
*/
void CheckIntermissionExit ( void ) {
int ready , notReady ;
int i ;
gclient_t * cl ;
int readyMask ;
if ( levelExiting )
{ //already on our way out, skip the check
return ;
}
if ( level . time < level . intermissiontime + 5000 )
{
// bring up the scoreboard after 5 seconds
}
// Single player exit does not happen until menu event
if ( g_gametype . integer = = GT_SINGLE_PLAYER ) {
return ;
}
// see which players are ready
ready = 0 ;
notReady = 0 ;
readyMask = 0 ;
for ( i = 0 ; i < g_maxclients . integer ; i + + ) {
cl = level . clients + i ;
if ( cl - > pers . connected ! = CON_CONNECTED ) {
continue ;
}
if ( g_entities [ cl - > ps . clientNum ] . r . svFlags & SVF_BOT ) {
continue ;
}
if ( cl - > readyToExit ) {
ready + + ;
if ( i < 16 ) {
readyMask | = 1 < < i ;
}
} else {
notReady + + ;
}
}
// copy the readyMask to each player's stats so
// it can be displayed on the scoreboard
for ( i = 0 ; i < g_maxclients . integer ; i + + ) {
cl = level . clients + i ;
if ( cl - > pers . connected ! = CON_CONNECTED ) {
continue ;
}
cl - > ps . stats [ STAT_CLIENTS_READY ] = readyMask ;
}
// never exit in less than five seconds
if ( level . time < level . intermissiontime + 5000 ) {
return ;
}
// if nobody wants to go, clear timer
if ( ! ready ) {
level . readyToExit = qfalse ;
return ;
}
// if everyone wants to go, go now
if ( ! notReady ) {
ExitLevel ( ) ;
return ;
}
// the first person to ready starts the ten second timeout
if ( ! level . readyToExit ) {
level . readyToExit = qtrue ;
level . exitTime = level . time ;
}
// if we have waited g_intermissionTime seconds since at least one player
// wanted to exit, go ahead
if ( level . time < level . exitTime + ( 1000 * g_intermissionTime . integer ) ) {
return ;
}
ExitLevel ( ) ;
}
/*
= = = = = = = = = = = = =
ScoreIsTied
= = = = = = = = = = = = =
*/
qboolean ScoreIsTied ( void ) {
int a , b ;
if ( level . numPlayingClients < 2 ) {
return qfalse ;
}
if ( g_gametype . integer > = GT_TEAM ) {
return level . teamScores [ TEAM_RED ] = = level . teamScores [ TEAM_BLUE ] ;
}
a = level . clients [ level . sortedClients [ 0 ] ] . ps . persistant [ PERS_SCORE ] ;
b = level . clients [ level . sortedClients [ 1 ] ] . ps . persistant [ PERS_SCORE ] ;
return a = = b ;
}
/*
= = = = = = = = = = = = = = = = =
CheckExitRules
There will be a delay between the time the exit is qualified for
and the time everyone is moved to the intermission spot , so you
can see the last frag .
= = = = = = = = = = = = = = = = =
*/
extern int borgQueenClientNum ;
void CheckExitRules ( void ) {
//RPG-X: RedTechie - No exit in RPG Your TRAPED! MHAHAHA
return ;
/*int i;
gclient_t * cl ;
// if at the intermission, wait for all non-bots to
// signal ready, then go to next level
if ( level . intermissiontime ) {
CheckIntermissionExit ( ) ;
return ;
}
if ( level . intermissionQueued ) {
if ( level . time - level . intermissionQueued > = INTERMISSION_DELAY_TIME ) {
level . intermissionQueued = 0 ;
BeginIntermission ( ) ;
}
return ;
}
//RPG-X: RedTechie - hihohiho is off to commenting out warmup code i go
//if ( g_doWarmup.integer )
//{
// if ( level.warmupTime != 0 )
// {
// if ( level.warmupTime < 0 || level.time - level.startTime <= level.warmupTime )
// {//don't win until warmup is done
// if ( g_pModAssimilation.integer != 0 || g_pModElimination.integer != 0 )
// {
// numKilled = 0;
// }
// return;
// }
// }
//}
// check for sudden death
if ( ScoreIsTied ( ) & & g_pModAssimilation . integer = = 0 & & g_pModElimination . integer = = 0 )
{
// always wait for sudden death
return ;
}
if ( g_timelimit . integer & & ! level . warmupTime & & g_pModAssimilation . integer = = 0 & & g_pModElimination . integer = = 0 )
{
if ( level . time - level . startTime > = g_timelimit . integer * 60000 )
{
trap_SendServerCommand ( - 1 , " print \" Timelimit hit. \n \" " ) ;
G_LogExit ( " Timelimit hit. " ) ;
return ;
}
}
if ( level . numPlayingClients < 2 )
{
//not enough players
if ( g_pModAssimilation . integer ! = 0 | | g_pModElimination . integer ! = 0 )
{
numKilled = 0 ;
}
return ;
}
if ( g_pModAssimilation . integer ! = 0 )
{ //check assimilation rules
if ( level . numConnectedClients > 1 & & numKilled > 0 )
{
gclient_t * survivor = NULL ;
if ( borgQueenClientNum ! = - 1 )
{ //see if borg queen is dead first
if ( g_entities [ borgQueenClientNum ] . health < = 0 )
{ //the queen is dead!
//FIXME: What if the queen disconnects somehow...? Shouldn't be possible
G_LogExit ( " The Borg Queen has been killed! " ) ;
return ;
}
}
//See if only one player remains alive, if so, end it.
for ( i = 0 ; i < level . maxclients ; i + + )
{
cl = & level . clients [ i ] ;
if ( cl - > pers . connected = = CON_CONNECTED & & cl - > sess . sessionTeam ! = TEAM_SPECTATOR & & cl - > sess . sessionClass ! = PC_BORG )
{
survivor = cl ;
break ;
}
}
if ( survivor = = NULL )
{
G_LogExit ( " Assimilation Complete. " ) ;
return ;
}
}
//don't check anything else
return ;
}
if ( g_pModElimination . integer ! = 0 )
{ //check elimination rules
gclient_t * survivor = NULL ;
//See if only one player remains alive, if so, end it.
if ( level . numConnectedClients > 1 & & numKilled > 0 )
{
for ( i = 0 ; i < level . numConnectedClients ; i + + )
{
cl = & level . clients [ level . sortedClients [ i ] ] ;
if ( cl - > sess . sessionTeam ! = TEAM_SPECTATOR & & ! ( cl - > ps . eFlags & EF_ELIMINATED ) )
{
if ( survivor ! = NULL )
{
if ( g_gametype . integer < GT_TEAM | | cl - > sess . sessionTeam ! = survivor - > sess . sessionTeam )
{ //not in a team game or survivor is on same team as previously found survivor, keep looking
survivor = NULL ;
break ;
}
}
else
{
survivor = cl ;
}
}
}
}
if ( survivor ! = NULL )
{
G_LogExit ( " Last Man Standing. " ) ;
}
//don't check anything else
return ;
}
if ( g_gametype . integer ! = GT_CTF & & g_fraglimit . integer )
{ //check fraglimit
if ( level . teamScores [ TEAM_RED ] > = g_fraglimit . integer ) {
trap_SendServerCommand ( - 1 , " print \" Red hit the point limit. \n \" " ) ;
G_LogExit ( " Fraglimit hit. " ) ;
return ;
}
if ( level . teamScores [ TEAM_BLUE ] > = g_fraglimit . integer ) {
trap_SendServerCommand ( - 1 , " print \" Blue hit the point limit. \n \" " ) ;
G_LogExit ( " Fraglimit hit. " ) ;
return ;
}
for ( i = 0 ; i < g_maxclients . integer ; i + + ) {
cl = level . clients + i ;
if ( cl - > pers . connected ! = CON_CONNECTED ) {
continue ;
}
if ( cl - > sess . sessionTeam ! = TEAM_FREE ) {
continue ;
}
if ( cl - > ps . persistant [ PERS_SCORE ] > = g_fraglimit . integer ) {
G_LogExit ( " Fraglimit hit. " ) ;
trap_SendServerCommand ( - 1 , va ( " print \" %s " S_COLOR_WHITE " hit the point limit. \n \" " ,
cl - > pers . netname ) ) ;
return ;
}
}
}
if ( g_gametype . integer = = GT_CTF & & g_capturelimit . integer )
{ //check CTF
if ( level . teamScores [ TEAM_RED ] > = g_capturelimit . integer ) {
trap_SendServerCommand ( - 1 , " print \" Red hit the capturelimit. \n \" " ) ;
G_LogExit ( " Capturelimit hit. " ) ;
return ;
}
if ( level . teamScores [ TEAM_BLUE ] > = g_capturelimit . integer ) {
trap_SendServerCommand ( - 1 , " print \" Blue hit the capturelimit. \n \" " ) ;
G_LogExit ( " Capturelimit hit. " ) ;
return ;
}
} */
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
FUNCTIONS CALLED EVERY FRAME
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = =
CheckTournement
Once a frame , check for changes in tournement player state
= = = = = = = = = = = = =
*/
void CheckTournement ( void ) {
if ( level . numPlayingClients = = 0 ) {
return ;
}
if ( g_gametype . integer = = GT_TOURNAMENT ) {
// pull in a spectator if needed
//RPG-X: RedTechie - pulling on people isnt nice
/*if ( level.numPlayingClients < 2 ) {
AddTournamentPlayer ( ) ;
} */
// if we don't have two players, go back to "waiting for players"
//RPG-X: RedTechie - No warmup!
/*if ( level.numPlayingClients != 2 ) {
if ( level . warmupTime ! = - 1 ) {
level . warmupTime = - 1 ;
trap_SetConfigstring ( CS_WARMUP , va ( " %i " , level . warmupTime ) ) ;
G_LogPrintf ( " Warmup: \n " ) ;
}
return ;
} */
if ( level . warmupTime = = 0 | | level . warmupTime ! = 0 ) { //RPG-X: RedTechie - No warmup Fail safe
return ;
}
// if the warmup is changed at the console, restart it
//RPG-X: RedTechie - No warmup!
/*if ( g_warmup.modificationCount != level.warmupModificationCount ) {
level . warmupModificationCount = g_warmup . modificationCount ;
level . warmupTime = - 1 ;
} */
// if all players have arrived, start the countdown
//RPG-X: RedTechie - No warmup!
/*if ( level.warmupTime < 0 )
{
if ( level . numPlayingClients = = 2 )
{
if ( g_warmup . integer > 1 )
{
// fudge by -1 to account for extra delays
level . warmupTime = level . time + ( g_warmup . integer - 1 ) * 1000 ;
trap_SetConfigstring ( CS_WARMUP , va ( " %i " , level . warmupTime ) ) ;
}
else
{
level . warmupTime = 0 ;
}
}
return ;
} */
//RPG-X: RedTechie - No warmup!
// if the warmup time has counted down, restart
/*if ( level.time > level.warmupTime ) {
level . warmupTime + = 10000 ;
trap_Cvar_Set ( " g_restarted " , " 1 " ) ;
trap_SendConsoleCommand ( EXEC_APPEND , " map_restart 0 \n " ) ;
level . restarted = qtrue ;
return ;
} */
} else if ( g_gametype . integer ! = GT_SINGLE_PLAYER /*&& g_doWarmup.integer*/ ) { //RPG-X: RedTechie - No warmup!
int counts [ TEAM_NUM_TEAMS ] ;
//qboolean notEnough = qfalse;
if ( g_gametype . integer > GT_TEAM ) {
counts [ TEAM_BLUE ] = TeamCount ( - 1 , TEAM_BLUE ) ;
counts [ TEAM_RED ] = TeamCount ( - 1 , TEAM_RED ) ;
//RPG-X: RedTechie - Enough players always
/* if (counts[TEAM_RED] < 1 || counts[TEAM_BLUE] < 1) {
notEnough = qtrue ;
}
} else if ( level . numPlayingClients < 2 ) {
notEnough = qtrue ;
} */
//RPG-X: RedTechie - No warmup!
/*if ( notEnough ) {
if ( level . warmupTime ! = - 1 ) {
level . warmupTime = - 1 ;
trap_SetConfigstring ( CS_WARMUP , va ( " %i " , level . warmupTime ) ) ;
G_LogPrintf ( " Warmup: \n " ) ;
}
return ; // still waiting for team members
} */
if ( level . warmupTime = = 0 ) {
return ;
}
// if the warmup is changed at the console, restart it
//RPG-X: RedTechie - No warmup!
/*if ( g_warmup.modificationCount != level.warmupModificationCount ) {
level . warmupModificationCount = g_warmup . modificationCount ;
level . warmupTime = - 1 ;
} */
// if all players have arrived, start the countdown
//RPG-X: RedTechie - No warmup!
/*if ( level.warmupTime < 0 ) {
// fudge by -1 to account for extra delays
level . warmupTime = level . time + ( g_warmup . integer - 1 ) * 1000 ;
trap_SetConfigstring ( CS_WARMUP , va ( " %i " , level . warmupTime ) ) ;
return ;
} */
// if the warmup time has counted down, restart
//RPG-X: RedTechie - No warmup!
/*if ( level.time > level.warmupTime ) {
level . warmupTime + = 10000 ;
trap_Cvar_Set ( " g_restarted " , " 1 " ) ;
trap_SendConsoleCommand ( EXEC_APPEND , " map_restart 0 \n " ) ;
level . restarted = qtrue ;
return ; */
}
}
}
/*
= = = = = = = = = = = = = = = = = =
CheckVote
= = = = = = = = = = = = = = = = = =
*/
void CheckVote ( void ) {
if ( ! level . voteTime ) {
return ;
}
if ( level . time - level . voteTime > = VOTE_TIME ) {
trap_SendServerCommand ( - 1 , " print \" Vote failed. \n \" " ) ;
} else {
if ( level . voteYes > level . numVotingClients / 2 ) {
// execute the command, then remove the vote
trap_SendServerCommand ( - 1 , " print \" Vote passed. \n \" " ) ;
trap_SendConsoleCommand ( EXEC_APPEND , va ( " %s \n " , level . voteString ) ) ;
} else if ( level . voteNo > = level . numVotingClients / 2 ) {
// same behavior as a timeout
trap_SendServerCommand ( - 1 , " print \" Vote failed. \n \" " ) ;
} else {
// still waiting for a majority
return ;
}
}
level . voteTime = 0 ;
trap_SetConfigstring ( CS_VOTE_TIME , " " ) ;
}
/*
= = = = = = = = = = = = = = = = = =
CheckCvars
= = = = = = = = = = = = = = = = = =
*/
void CheckCvars ( void ) {
static int lastMod = - 1 ;
if ( g_password . modificationCount ! = lastMod ) {
lastMod = g_password . modificationCount ;
if ( * g_password . string & & Q_stricmp ( g_password . string , " none " ) ) {
trap_Cvar_Set ( " g_needpass " , " 1 " ) ;
} else {
trap_Cvar_Set ( " g_needpass " , " 0 " ) ;
}
}
}
/*
= = = = = = = = = = = = =
G_RunThink
Runs thinking code for this frame if necessary
= = = = = = = = = = = = =
*/
void G_RunThink ( gentity_t * ent ) {
float thinktime ;
thinktime = ent - > nextthink ;
if ( thinktime < = 0 ) {
return ;
}
if ( thinktime > level . time ) {
return ;
}
ent - > nextthink = 0 ;
if ( ! ent - > think ) {
G_Error ( " NULL ent->think " ) ;
}
# ifdef G_LUA
if ( ent - > luaThink & & ! ent - > client )
{
LuaHook_G_EntityThink ( ent - > luaThink , ent - > s . number ) ;
}
# endif
ent - > think ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
G_RunFrame
Advances the non - player objects in the world
= = = = = = = = = = = = = = = =
*/
extern void SetClass ( gentity_t * ent , char * s , char * teamName , qboolean SaveToCvar ) ;
void DragCheck ( void ) ; //RPG-X: J2J - Added to rid warning.
void CheckHealthInfoMessage ( void ) ;
extern void G_PickBorgQueen ( void ) ;
extern void INeedAHero ( void ) ;
extern qboolean levelExiting ;
extern int actionHeroClientNum ;
void G_RunFrame ( int levelTime ) {
int i ;
gentity_t * ent ;
gclient_t * client ;
playerState_t * ps ;
entityState_t * es ;
int msec ;
int start , end ;
// if we are waiting for the level to restart, do nothing
if ( level . restarted ) {
return ;
}
level . framenum + + ;
level . previousTime = level . time ;
level . time = levelTime ;
msec = level . time - level . previousTime ;
// get any cvar changes
G_UpdateCvars ( ) ;
//
// go through all allocated objects
//
start = trap_Milliseconds ( ) ;
ent = & g_entities [ 0 ] ;
for ( i = 0 ; i < level . num_entities ; i + + , ent + + ) {
if ( ! ent - > inuse ) {
continue ;
}
es = & ent - > s ;
ps = & ent - > client - > ps ;
// clear events that are too old
if ( level . time - ent - > eventTime > EVENT_VALID_MSEC ) {
if ( es - > event ) {
es - > event = 0 ; // &= EV_EVENT_BITS;
if ( ent - > client ) {
ps - > externalEvent = 0 ;
ps - > events [ 0 ] = 0 ;
ps - > events [ 1 ] = 0 ;
ps - > events [ 2 ] = 0 ;
ps - > events [ 3 ] = 0 ;
}
}
if ( ent - > freeAfterEvent ) {
// tempEntities or dropped items completely go away after their event
G_FreeEntity ( ent ) ;
continue ;
} else if ( ent - > unlinkAfterEvent ) {
// items that will respawn will hide themselves after their pickup event
ent - > unlinkAfterEvent = qfalse ;
trap_UnlinkEntity ( ent ) ;
}
}
// temporary entities don't think
if ( ent - > freeAfterEvent ) {
continue ;
}
if ( ! ent - > r . linked & & ent - > neverFree ) {
continue ;
}
if ( ! ent - > client )
{
if ( es - > eFlags & EF_ANIM_ONCE )
{ //this must be capped render-side
es - > frame + + ;
}
}
if ( ( es - > eType = = ET_MISSILE ) | | ( es - > eType = = ET_ALT_MISSILE ) ) {
G_RunMissile ( ent ) ;
continue ;
}
if ( es - > eType = = ET_ITEM | | ent - > physicsObject ) {
G_RunItem ( ent ) ;
continue ;
}
if ( es - > eType = = ET_MOVER | | es - > eType = = ET_MOVER_STR ) { //RPG-X | GSIO01 | 13/05/2009
G_RunMover ( ent ) ;
continue ;
}
if ( i < MAX_CLIENTS ) {
G_RunClient ( ent ) ;
continue ;
}
G_RunThink ( ent ) ;
}
end = trap_Milliseconds ( ) ;
start = trap_Milliseconds ( ) ;
// perform final fixups on the players
ent = & g_entities [ 0 ] ;
for ( i = 0 ; i < level . maxclients ; i + + , ent + + ) {
if ( ent - > inuse ) {
ClientEndFrame ( ent ) ;
}
}
end = trap_Milliseconds ( ) ;
// see if it is time to do a tournement restart
CheckTournement ( ) ;
// see if it is time to end the level
CheckExitRules ( ) ;
// update to team status?
CheckTeamStatus ( ) ;
// update to health status
//CheckHealthInfoMessage();//done from inside CheckTeamStatus now
// cancel vote if timed out
CheckVote ( ) ;
// for tracking changes
CheckCvars ( ) ;
if ( ! levelExiting )
{
//keep looking for a borgQueen if we don't have one yet
if ( borgQueenClientNum = = - 1 )
{
G_PickBorgQueen ( ) ;
}
//keep looking for an actionHero if we don't have one yet
if ( actionHeroClientNum = = - 1 )
{
INeedAHero ( ) ;
}
}
//RPG-X: RedTechie - Count down our shake camera timer
//TiM: NOT NECESSARY
/*if(rpg_servershakeallclients.integer == 1){
if ( shaketimer < level . time ) {
trap_SendConsoleCommand ( EXEC_APPEND , " set rpg_servershakeallclients 0 \n " ) ;
}
} */
//RPG-X: J2J - This will check for drag movements that need to be calculated.
DragCheck ( ) ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
ent = & g_entities [ i ] ;
if ( ! ent | | ! ent - > client )
continue ;
client = ent - > client ;
if ( ! ( client - > pers . cmd . buttons & BUTTON_USE ) ) {
client - > pressedUse = qfalse ;
}
if ( g_classData [ client - > sess . sessionClass ] . isn00b /*ent->client->sess.sessionClass == PC_N00B*/ )
{
if ( ( client - > n00bTime ! = - 1 ) & & ( client - > n00bTime < = level . time ) & & client - > origClass [ 0 ] )
{
SetClass ( ent , client - > origClass , NULL , qtrue ) ;
}
}
}
//RPG-X: Marcin: To clear pressedUse. - 30/12/2008
# ifdef G_LUA
LuaHook_G_RunFrame ( levelTime ) ;
# endif
}