summaryrefslogtreecommitdiff
path: root/src/game/g_main.c
diff options
context:
space:
mode:
authorIronClawTrem <louie.nutman@gmail.com>2020-02-16 03:40:06 +0000
committerIronClawTrem <louie.nutman@gmail.com>2020-02-16 03:40:06 +0000
commit425decdf7e9284d15aa726e3ae96b9942fb0e3ea (patch)
tree6c0dd7edfefff1be7b9e75fe0b3a0a85fe1595f3 /src/game/g_main.c
parentccb0b2e4d6674a7a00c9bf491f08fc73b6898c54 (diff)
create tremded branch
Diffstat (limited to 'src/game/g_main.c')
-rw-r--r--src/game/g_main.c1808
1 files changed, 621 insertions, 1187 deletions
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 6623959..f0f2158 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -1,13 +1,14 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
-Copyright (C) 2000-2006 Tim Angus
+Copyright (C) 2000-2013 Darklegion Development
+Copyright (C) 2015-2019 GrangerHub
This file is part of Tremulous.
Tremulous is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
+published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
Tremulous is distributed in the hope that it will be
@@ -16,44 +17,38 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Tremulous; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+along with Tremulous; if not, see <https://www.gnu.org/licenses/>
+
===========================================================================
*/
#include "g_local.h"
-#define QVM_NAME "AA-QVM"
-#define QVM_VERSIONNUM "MULTIPROTOCOL"
-
level_locals_t level;
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
- qboolean teamShader; // track and if changed, update shader state
+ char *cvarName;
+ char *defaultString;
+ int cvarFlags;
+ int modificationCount; // for tracking changes
+ qboolean trackChange; // track this variable, and announce if changed
+ /* certain cvars can be set in worldspawn, but we don't want those values to
+ persist, so keep track of non-worldspawn changes and restore that on map
+ end. unfortunately, if the server crashes, the value set in worldspawn may
+ persist */
+ char *explicit;
} cvarTable_t;
gentity_t g_entities[ MAX_GENTITIES ];
gclient_t g_clients[ MAX_CLIENTS ];
-vmCvar_t g_fraglimit;
vmCvar_t g_timelimit;
vmCvar_t g_suddenDeathTime;
-vmCvar_t g_suddenDeath;
-vmCvar_t g_suddenDeathMode;
-vmCvar_t g_capturelimit;
vmCvar_t g_friendlyFire;
-vmCvar_t g_friendlyFireAliens;
-vmCvar_t g_friendlyFireHumans;
-vmCvar_t g_friendlyFireMovementAttacks;
-vmCvar_t g_retribution;
vmCvar_t g_friendlyBuildableFire;
+vmCvar_t g_dretchPunt;
vmCvar_t g_password;
vmCvar_t g_needpass;
vmCvar_t g_maxclients;
@@ -63,79 +58,47 @@ vmCvar_t g_speed;
vmCvar_t g_gravity;
vmCvar_t g_cheats;
vmCvar_t g_knockback;
-vmCvar_t g_quadfactor;
vmCvar_t g_inactivity;
vmCvar_t g_debugMove;
vmCvar_t g_debugDamage;
-vmCvar_t g_debugAlloc;
-vmCvar_t g_weaponRespawn;
-vmCvar_t g_weaponTeamRespawn;
vmCvar_t g_motd;
vmCvar_t g_synchronousClients;
vmCvar_t g_warmup;
-vmCvar_t g_warmupMode;
vmCvar_t g_doWarmup;
vmCvar_t g_restarted;
vmCvar_t g_lockTeamsAtStart;
vmCvar_t g_logFile;
vmCvar_t g_logFileSync;
-vmCvar_t g_blood;
-vmCvar_t g_podiumDist;
-vmCvar_t g_podiumDrop;
vmCvar_t g_allowVote;
-vmCvar_t g_requireVoteReasons;
vmCvar_t g_voteLimit;
vmCvar_t g_suddenDeathVotePercent;
vmCvar_t g_suddenDeathVoteDelay;
-vmCvar_t g_extendVotesPercent;
-vmCvar_t g_extendVotesTime;
-vmCvar_t g_extendVotesCount;
-vmCvar_t g_kickVotesPercent;
-vmCvar_t g_customVote1;
-vmCvar_t g_customVote2;
-vmCvar_t g_customVote3;
-vmCvar_t g_customVote4;
-vmCvar_t g_customVote5;
-vmCvar_t g_customVote6;
-vmCvar_t g_customVote7;
-vmCvar_t g_customVote8;
-vmCvar_t g_customVotePercent;
-vmCvar_t g_mapVotesPercent;
-vmCvar_t g_extendVotesPercent;
-vmCvar_t g_extendVotesTime;
-vmCvar_t g_extendVotesCount;
-vmCvar_t g_mapRotationVote;
-vmCvar_t g_readyPercent;
-vmCvar_t g_designateVotes;
-vmCvar_t g_teamAutoJoin;
vmCvar_t g_teamForceBalance;
-vmCvar_t g_banIPs;
-vmCvar_t g_filterBan;
vmCvar_t g_smoothClients;
-vmCvar_t g_outdatedClientMessage;
vmCvar_t pmove_fixed;
vmCvar_t pmove_msec;
-vmCvar_t g_rankings;
-vmCvar_t g_listEntity;
-vmCvar_t g_minCommandPeriod;
vmCvar_t g_minNameChangePeriod;
vmCvar_t g_maxNameChanges;
-vmCvar_t g_newbieNumbering;
-vmCvar_t g_newbieNamePrefix;
-vmCvar_t g_humanBuildPoints;
vmCvar_t g_alienBuildPoints;
+vmCvar_t g_alienBuildQueueTime;
+vmCvar_t g_humanBuildPoints;
+vmCvar_t g_humanBuildQueueTime;
+vmCvar_t g_humanRepeaterBuildPoints;
+vmCvar_t g_humanRepeaterBuildQueueTime;
+vmCvar_t g_humanRepeaterMaxZones;
vmCvar_t g_humanStage;
-vmCvar_t g_humanKills;
+vmCvar_t g_humanCredits;
vmCvar_t g_humanMaxStage;
vmCvar_t g_humanStage2Threshold;
vmCvar_t g_humanStage3Threshold;
vmCvar_t g_alienStage;
-vmCvar_t g_alienKills;
+vmCvar_t g_alienCredits;
vmCvar_t g_alienMaxStage;
vmCvar_t g_alienStage2Threshold;
vmCvar_t g_alienStage3Threshold;
vmCvar_t g_teamImbalanceWarnings;
+vmCvar_t g_freeFundPeriod;
vmCvar_t g_unlagged;
@@ -144,105 +107,52 @@ vmCvar_t g_disabledClasses;
vmCvar_t g_disabledBuildables;
vmCvar_t g_markDeconstruct;
-vmCvar_t g_markDeconstructMode;
-vmCvar_t g_deconDead;
vmCvar_t g_debugMapRotation;
vmCvar_t g_currentMapRotation;
-vmCvar_t g_currentMap;
+vmCvar_t g_mapRotationNodes;
+vmCvar_t g_mapRotationStack;
vmCvar_t g_nextMap;
vmCvar_t g_initialMapRotation;
+vmCvar_t g_debugVoices;
+vmCvar_t g_voiceChats;
+
vmCvar_t g_shove;
vmCvar_t g_mapConfigs;
-vmCvar_t g_chatTeamPrefix;
-vmCvar_t g_actionPrefix;
+vmCvar_t g_sayAreaRange;
+
vmCvar_t g_floodMaxDemerits;
vmCvar_t g_floodMinTime;
-vmCvar_t g_spamTime;
-vmCvar_t g_layouts;
+vmCvar_t g_nextLayout;
+vmCvar_t g_layouts[ 9 ];
vmCvar_t g_layoutAuto;
+vmCvar_t g_emoticonsAllowedInNames;
+
vmCvar_t g_admin;
-vmCvar_t g_adminLog;
-vmCvar_t g_adminParseSay;
-vmCvar_t g_adminSayFilter;
-vmCvar_t g_adminNameProtect;
-vmCvar_t g_adminTempMute;
vmCvar_t g_adminTempBan;
vmCvar_t g_adminMaxBan;
-vmCvar_t g_adminTempSpec;
-vmCvar_t g_adminMapLog;
-vmCvar_t g_minLevelToJoinTeam;
-vmCvar_t g_minDeconLevel;
-vmCvar_t g_minDeconAffectsMark;
-vmCvar_t g_forceAutoSelect;
vmCvar_t g_privateMessages;
-vmCvar_t g_fullIgnore;
-vmCvar_t g_decolourLogfiles;
-vmCvar_t g_minLevelToSpecMM1;
-vmCvar_t g_publicSayadmins;
-vmCvar_t g_myStats;
-vmCvar_t g_AllStats;
-vmCvar_t g_AllStatsTime;
-vmCvar_t g_teamStatus;
-vmCvar_t g_antiSpawnBlock;
-vmCvar_t g_banNotice;
-
-vmCvar_t g_devmapKillerHP;
-vmCvar_t g_killerHP;
-
-vmCvar_t g_buildLogMaxLength;
-
-vmCvar_t g_tag;
-
-vmCvar_t g_dretchPunt;
-
-vmCvar_t g_allowShare;
-vmCvar_t g_creditOverflow;
-
-vmCvar_t g_devmapNoGod;
-vmCvar_t g_devmapNoStructDmg;
-
-vmCvar_t g_slapKnockback;
-vmCvar_t g_slapDamage;
-
-vmCvar_t g_voteMinTime;
-vmCvar_t g_mapvoteMaxTime;
-vmCvar_t g_votableMaps;
+vmCvar_t g_specChat;
+vmCvar_t g_publicAdminMessages;
+vmCvar_t g_allowTeamOverlay;
-vmCvar_t g_msg;
-vmCvar_t g_msgTime;
-vmCvar_t g_welcomeMsg;
-vmCvar_t g_welcomeMsgTime;
-vmCvar_t g_deconBanTime;
+vmCvar_t g_censorship;
+vmCvar_t g_tag;
-vmCvar_t mod_jetpackFuel;
-vmCvar_t mod_jetpackConsume;
-vmCvar_t mod_jetpackRegen;
-
-vmCvar_t g_adminExpireTime;
-
-vmCvar_t g_autoGhost;
-
-vmCvar_t g_teamKillThreshold;
-
-vmCvar_t g_aimbotAdvertBan;
-vmCvar_t g_aimbotAdvertBanTime;
-vmCvar_t g_aimbotAdvertBanReason;
-vmCvar_t g_Bubbles;
-vmCvar_t g_scrimMode;
-vmCvar_t g_gradualFreeFunds;
-vmCvar_t g_bleedingSpree;
-vmCvar_t g_schachtmeisterClearThreshold;
-vmCvar_t g_schachtmeisterAutobahnThreshold;
-vmCvar_t g_schachtmeisterAutobahnMessage;
-vmCvar_t g_adminAutobahnNotify;
+// copy cvars that can be set in worldspawn so they can be restored later
+static char cv_gravity[ MAX_CVAR_VALUE_STRING ];
+static char cv_humanMaxStage[ MAX_CVAR_VALUE_STRING ];
+static char cv_alienMaxStage[ MAX_CVAR_VALUE_STRING ];
+static char cv_humanRepeaterBuildPoints[ MAX_CVAR_VALUE_STRING ];
+static char cv_humanBuildPoints[ MAX_CVAR_VALUE_STRING ];
+static char cv_alienBuildPoints[ MAX_CVAR_VALUE_STRING ];
static cvarTable_t gameCvarTable[ ] =
{
@@ -251,223 +161,133 @@ static cvarTable_t gameCvarTable[ ] =
// noset vars
{ NULL, "gamename", GAME_VERSION , CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
- { NULL, "gamedate", __DATE__ , CVAR_ROM, 0, qfalse },
{ &g_restarted, "g_restarted", "0", CVAR_ROM, 0, qfalse },
{ &g_lockTeamsAtStart, "g_lockTeamsAtStart", "0", CVAR_ROM, 0, qfalse },
{ NULL, "sv_mapname", "", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
{ NULL, "P", "", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
- { NULL, "ff", "0", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
- { NULL, "qvm_version", QVM_NAME " " QVM_VERSIONNUM " (" __DATE__ ", " __TIME__ ")", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
// latched vars
{ &g_maxclients, "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse },
- { &g_maxGameClients, "g_maxGameClients", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
// change anytime vars
- { &g_timelimit, "timelimit", "45", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
- { &g_suddenDeathTime, "g_suddenDeathTime", "30", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
- { &g_suddenDeathMode, "g_suddenDeathMode", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
- { &g_suddenDeath, "g_suddenDeath", "0", CVAR_SERVERINFO | CVAR_NORESTART, 0, qtrue },
+ { &g_maxGameClients, "g_maxGameClients", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse },
- { &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse },
+ { &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
+ { &g_suddenDeathTime, "g_suddenDeathTime", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
- { &g_friendlyFire, "g_friendlyFire", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qtrue },
- { &g_friendlyFireAliens, "g_friendlyFireAliens", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_friendlyFireHumans, "g_friendlyFireHumans", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_retribution, "g_retribution", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_friendlyBuildableFire, "g_friendlyBuildableFire", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qtrue },
- { &g_friendlyFireMovementAttacks, "g_friendlyFireMovementAttacks", "1", CVAR_ARCHIVE, 0, qtrue },
- { &g_devmapNoGod, "g_devmapNoGod", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_devmapNoStructDmg, "g_devmapNoStructDmg", "0", CVAR_ARCHIVE, 0, qtrue },
+ { &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse },
- { &g_slapKnockback, "g_slapKnockback", "200", CVAR_ARCHIVE, 0, qfalse},
- { &g_slapDamage, "g_slapDamage", "0", CVAR_ARCHIVE, 0, qfalse},
+ { &g_friendlyFire, "g_friendlyFire", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
+ { &g_friendlyBuildableFire, "g_friendlyBuildableFire", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
+ { &g_dretchPunt, "g_dretchPunt", "1", CVAR_ARCHIVE, 0, qtrue },
- { &g_teamAutoJoin, "g_teamAutoJoin", "0", CVAR_ARCHIVE },
- { &g_teamForceBalance, "g_teamForceBalance", "1", CVAR_ARCHIVE },
+ { &g_teamForceBalance, "g_teamForceBalance", "0", CVAR_ARCHIVE, 0, qtrue },
{ &g_warmup, "g_warmup", "10", CVAR_ARCHIVE, 0, qtrue },
- { &g_warmupMode, "g_warmupMode", "1", CVAR_ARCHIVE, 0, qtrue },
- { &g_doWarmup, "g_doWarmup", "1", CVAR_ARCHIVE, 0, qtrue },
+ { &g_doWarmup, "g_doWarmup", "0", CVAR_ARCHIVE, 0, qtrue },
{ &g_logFile, "g_logFile", "games.log", CVAR_ARCHIVE, 0, qfalse },
{ &g_logFileSync, "g_logFileSync", "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_needpass, "g_needpass", "0", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse },
-
- { &g_autoGhost, "g_autoGhost", "1", CVAR_SERVERINFO, 0, qfalse },
{ &g_dedicated, "dedicated", "0", 0, 0, qfalse },
- { &g_speed, "g_speed", "320", CVAR_SERVERINFO, 0, qtrue },
- { &g_gravity, "g_gravity", "800", CVAR_SERVERINFO, 0, qtrue },
- { &g_knockback, "g_knockback", "1000", CVAR_SERVERINFO, 0, qtrue },
- { &g_quadfactor, "g_quadfactor", "3", 0, 0, qtrue },
- { &g_weaponRespawn, "g_weaponrespawn", "5", 0, 0, qtrue },
- { &g_weaponTeamRespawn, "g_weaponTeamRespawn", "30", 0, 0, qtrue },
+ { &g_speed, "g_speed", "320", 0, 0, qtrue },
+ { &g_gravity, "g_gravity", "800", 0, 0, qtrue, cv_gravity },
+ { &g_knockback, "g_knockback", "1000", 0, 0, qtrue },
{ &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_blood, "com_blood", "1", 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_ARCHIVE, 0, qfalse },
- { &g_requireVoteReasons, "g_requireVoteReasons", "0", CVAR_ARCHIVE, 0, qfalse },
{ &g_voteLimit, "g_voteLimit", "5", CVAR_ARCHIVE, 0, qfalse },
- { &g_voteMinTime, "g_voteMinTime", "120", CVAR_ARCHIVE, 0, qfalse },
- { &g_mapvoteMaxTime, "g_mapvoteMaxTime", "240", CVAR_ARCHIVE, 0, qfalse },
- { &g_votableMaps, "g_votableMaps", "", CVAR_ARCHIVE, 0, qtrue },
{ &g_suddenDeathVotePercent, "g_suddenDeathVotePercent", "74", CVAR_ARCHIVE, 0, qfalse },
{ &g_suddenDeathVoteDelay, "g_suddenDeathVoteDelay", "180", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote1, "g_customVote1", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote2, "g_customVote2", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote3, "g_customVote3", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote4, "g_customVote4", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote5, "g_customVote5", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote6, "g_customVote6", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote7, "g_customVote7", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVote8, "g_customVote8", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_customVotePercent, "g_customVotePercent", "50", CVAR_ARCHIVE, 0, qfalse },
- { &g_mapVotesPercent, "g_mapVotesPercent", "50", CVAR_ARCHIVE, 0, qfalse },
- { &g_extendVotesPercent, "g_extendVotesPercent", "74", CVAR_ARCHIVE, 0, qfalse },
- { &g_extendVotesTime, "g_extendVotesTime", "10", CVAR_ARCHIVE, 0, qfalse },
- { &g_extendVotesCount, "g_extendVotesCount", "2", CVAR_ARCHIVE, 0, qfalse },
- { &g_mapRotationVote, "g_mapRotationVote", "15", CVAR_ARCHIVE, 0, qfalse },
- { &g_readyPercent, "g_readyPercent", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_designateVotes, "g_designateVotes", "0", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_listEntity, "g_listEntity", "0", 0, 0, qfalse },
- { &g_minCommandPeriod, "g_minCommandPeriod", "500", 0, 0, qfalse},
{ &g_minNameChangePeriod, "g_minNameChangePeriod", "5", 0, 0, qfalse},
{ &g_maxNameChanges, "g_maxNameChanges", "5", 0, 0, qfalse},
- { &g_newbieNumbering, "g_newbieNumbering", "0", CVAR_ARCHIVE, 0, qfalse},
- { &g_newbieNamePrefix, "g_newbieNamePrefix", "Newbie#", CVAR_ARCHIVE, 0, qfalse},
{ &g_smoothClients, "g_smoothClients", "1", 0, 0, qfalse},
- { &g_outdatedClientMessage, "g_outdatedClientMessage", "", CVAR_ARCHIVE, 0, qfalse},
{ &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse},
{ &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse},
- { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, CVAR_SERVERINFO, 0, qfalse },
- { &g_alienBuildPoints, "g_alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, CVAR_SERVERINFO, 0, qfalse },
+ { &g_alienBuildPoints, "g_alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, 0, 0, qfalse, cv_alienBuildPoints },
+ { &g_alienBuildQueueTime, "g_alienBuildQueueTime", DEFAULT_ALIEN_QUEUE_TIME, CVAR_ARCHIVE, 0, qfalse },
+ { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse, cv_humanBuildPoints },
+ { &g_humanBuildQueueTime, "g_humanBuildQueueTime", DEFAULT_HUMAN_QUEUE_TIME, CVAR_ARCHIVE, 0, qfalse },
+ { &g_humanRepeaterBuildPoints, "g_humanRepeaterBuildPoints", DEFAULT_HUMAN_REPEATER_BUILDPOINTS, CVAR_ARCHIVE, 0, qfalse, cv_humanRepeaterBuildPoints },
+ { &g_humanRepeaterMaxZones, "g_humanRepeaterMaxZones", DEFAULT_HUMAN_REPEATER_MAX_ZONES, CVAR_ARCHIVE, 0, qfalse },
+ { &g_humanRepeaterBuildQueueTime, "g_humanRepeaterBuildQueueTime", DEFAULT_HUMAN_REPEATER_QUEUE_TIME, CVAR_ARCHIVE, 0, qfalse },
{ &g_humanStage, "g_humanStage", "0", 0, 0, qfalse },
- { &g_humanKills, "g_humanKills", "0", 0, 0, qfalse },
- { &g_humanMaxStage, "g_humanMaxStage", DEFAULT_HUMAN_MAX_STAGE, 0, 0, qfalse },
+ { &g_humanCredits, "g_humanCredits", "0", 0, 0, qfalse },
+ { &g_humanMaxStage, "g_humanMaxStage", DEFAULT_HUMAN_MAX_STAGE, 0, 0, qfalse, cv_humanMaxStage },
{ &g_humanStage2Threshold, "g_humanStage2Threshold", DEFAULT_HUMAN_STAGE2_THRESH, 0, 0, qfalse },
{ &g_humanStage3Threshold, "g_humanStage3Threshold", DEFAULT_HUMAN_STAGE3_THRESH, 0, 0, qfalse },
{ &g_alienStage, "g_alienStage", "0", 0, 0, qfalse },
- { &g_alienKills, "g_alienKills", "0", 0, 0, qfalse },
- { &g_alienMaxStage, "g_alienMaxStage", DEFAULT_ALIEN_MAX_STAGE, 0, 0, qfalse },
+ { &g_alienCredits, "g_alienCredits", "0", 0, 0, qfalse },
+ { &g_alienMaxStage, "g_alienMaxStage", DEFAULT_ALIEN_MAX_STAGE, 0, 0, qfalse, cv_alienMaxStage },
{ &g_alienStage2Threshold, "g_alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, 0, 0, qfalse },
{ &g_alienStage3Threshold, "g_alienStage3Threshold", DEFAULT_ALIEN_STAGE3_THRESH, 0, 0, qfalse },
-
{ &g_teamImbalanceWarnings, "g_teamImbalanceWarnings", "30", CVAR_ARCHIVE, 0, qfalse },
-
+ { &g_freeFundPeriod, "g_freeFundPeriod", DEFAULT_FREEKILL_PERIOD, CVAR_ARCHIVE, 0, qtrue },
+
{ &g_unlagged, "g_unlagged", "1", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
- { &g_disabledEquipment, "g_disabledEquipment", "", CVAR_ROM, 0, qfalse },
- { &g_disabledClasses, "g_disabledClasses", "", CVAR_ROM, 0, qfalse },
- { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse },
+ { &g_disabledEquipment, "g_disabledEquipment", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse },
+ { &g_disabledClasses, "g_disabledClasses", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse },
+ { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse },
+
+ { &g_sayAreaRange, "g_sayAreaRange", "1000", CVAR_ARCHIVE, 0, qtrue },
- { &g_chatTeamPrefix, "g_chatTeamPrefix", "1", CVAR_ARCHIVE },
- { &g_actionPrefix, "g_actionPrefix", "* ", CVAR_ARCHIVE, 0, qfalse },
{ &g_floodMaxDemerits, "g_floodMaxDemerits", "5000", CVAR_ARCHIVE, 0, qfalse },
{ &g_floodMinTime, "g_floodMinTime", "2000", CVAR_ARCHIVE, 0, qfalse },
- { &g_spamTime, "g_spamTime", "2", CVAR_ARCHIVE, 0, qfalse },
- { &g_markDeconstruct, "g_markDeconstruct", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_markDeconstructMode, "g_markDeconstructMode", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_deconDead, "g_deconDead", "0", CVAR_ARCHIVE, 0, qtrue },
+ { &g_markDeconstruct, "g_markDeconstruct", "3", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
{ &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse },
{ &g_currentMapRotation, "g_currentMapRotation", "-1", 0, 0, qfalse }, // -1 = NOT_ROTATING
- { &g_currentMap, "g_currentMap", "0", 0, 0, qfalse },
+ { &g_mapRotationNodes, "g_mapRotationNodes", "", CVAR_ROM, 0, qfalse },
+ { &g_mapRotationStack, "g_mapRotationStack", "", CVAR_ROM, 0, qfalse },
{ &g_nextMap, "g_nextMap", "", 0 , 0, qtrue },
{ &g_initialMapRotation, "g_initialMapRotation", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_shove, "g_shove", "15", CVAR_ARCHIVE, 0, qfalse },
+ { &g_debugVoices, "g_debugVoices", "0", 0, 0, qfalse },
+ { &g_voiceChats, "g_voiceChats", "1", CVAR_ARCHIVE, 0, qfalse },
+ { &g_shove, "g_shove", "0.0", CVAR_ARCHIVE, 0, qfalse },
{ &g_mapConfigs, "g_mapConfigs", "", CVAR_ARCHIVE, 0, qfalse },
{ NULL, "g_mapConfigsLoaded", "0", CVAR_ROM, 0, qfalse },
- { &g_layouts, "g_layouts", "", CVAR_LATCH, 0, qfalse },
+ { &g_nextLayout, "g_nextLayout", "", 0, 0, qfalse },
+ { &g_layouts[ 0 ], "g_layouts", "", 0, 0, qfalse },
+ { &g_layouts[ 1 ], "g_layouts2", "", 0, 0, qfalse },
+ { &g_layouts[ 2 ], "g_layouts3", "", 0, 0, qfalse },
+ { &g_layouts[ 3 ], "g_layouts4", "", 0, 0, qfalse },
+ { &g_layouts[ 4 ], "g_layouts5", "", 0, 0, qfalse },
+ { &g_layouts[ 5 ], "g_layouts6", "", 0, 0, qfalse },
+ { &g_layouts[ 6 ], "g_layouts7", "", 0, 0, qfalse },
+ { &g_layouts[ 7 ], "g_layouts8", "", 0, 0, qfalse },
+ { &g_layouts[ 8 ], "g_layouts9", "", 0, 0, qfalse },
{ &g_layoutAuto, "g_layoutAuto", "1", CVAR_ARCHIVE, 0, qfalse },
+ { &g_emoticonsAllowedInNames, "g_emoticonsAllowedInNames", "1", CVAR_LATCH|CVAR_ARCHIVE, 0, qfalse },
+
{ &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminLog, "g_adminLog", "admin.log", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminParseSay, "g_adminParseSay", "1", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminSayFilter, "g_adminSayFilter", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminNameProtect, "g_adminNameProtect", "1", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminTempMute, "g_adminTempMute", "5m", CVAR_ARCHIVE, 0, qfalse },
{ &g_adminTempBan, "g_adminTempBan", "2m", CVAR_ARCHIVE, 0, qfalse },
{ &g_adminMaxBan, "g_adminMaxBan", "2w", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminTempSpec, "g_adminTempSpec", "2m", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminMapLog, "g_adminMapLog", "", CVAR_ROM, 0, qfalse },
- { &g_minLevelToJoinTeam, "g_minLevelToJoinTeam", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_minDeconLevel, "g_minDeconLevel", "0", CVAR_ARCHIVE, 0, qfalse},
- { &g_minDeconAffectsMark, "g_minDeconAffectsMark", "0", CVAR_ARCHIVE, 0, qfalse},
- { &g_forceAutoSelect, "g_forceAutoSelect", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_adminExpireTime, "g_adminExpireTime", "0", CVAR_ARCHIVE, 0, qfalse },
-
+
{ &g_privateMessages, "g_privateMessages", "1", CVAR_ARCHIVE, 0, qfalse },
- { &g_fullIgnore, "g_fullIgnore", "1", CVAR_ARCHIVE, 0, qtrue },
- { &g_decolourLogfiles, "g_decolourLogfiles", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_buildLogMaxLength, "g_buildLogMaxLength", "50", CVAR_ARCHIVE, 0, qfalse },
- { &g_myStats, "g_myStats", "1", CVAR_ARCHIVE, 0, qtrue },
- { &g_AllStats, "g_AllStats", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_AllStatsTime, "g_AllStatsTime", "60", CVAR_ARCHIVE, 0, qfalse },
- { &g_teamStatus, "g_teamStatus", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_publicSayadmins, "g_publicSayadmins", "1", CVAR_ARCHIVE, 0, qfalse },
- { &g_minLevelToSpecMM1, "g_minLevelToSpecMM1", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_antiSpawnBlock, "g_antiSpawnBlock", "0", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_devmapKillerHP, "g_devmapKillerHP", "0", CVAR_ARCHIVE, 0, qtrue },
- { &g_killerHP, "g_killerHP", "0", CVAR_ARCHIVE, 0, qtrue },
-
- { &g_tag, "g_tag", "main", CVAR_INIT, 0, qfalse },
-
- { &g_dretchPunt, "g_dretchPunt", "1", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_msg, "g_msg", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_msgTime, "g_msgTime", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_welcomeMsg, "g_welcomeMsg", "", CVAR_ARCHIVE, 0, qfalse },
- { &g_welcomeMsgTime, "g_welcomeMsgTime", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_deconBanTime, "g_deconBanTime", "2h", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_rankings, "g_rankings", "0", 0, 0, qfalse },
- { &g_allowShare, "g_allowShare", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse},
- { &g_creditOverflow, "g_creditOverflow", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse},
- { &g_banNotice, "g_banNotice", "", CVAR_ARCHIVE, 0, qfalse },
-
- { &mod_jetpackFuel, "mod_jetpackFuel", "0", CVAR_ARCHIVE, 0, qtrue },
- { &mod_jetpackConsume, "mod_jetpackConsume", "2", CVAR_ARCHIVE, 0, qfalse },
- { &mod_jetpackRegen, "mod_jetpackRegen", "3", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_teamKillThreshold, "g_teamKillThreshold", "0", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_aimbotAdvertBan, "g_aimbotAdvertBan", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_aimbotAdvertBanTime, "g_aimbotAdvertBanTime", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_aimbotAdvertBanReason, "g_aimbotAdvertBanReason", "AUTOBAN: AIMBOT", CVAR_ARCHIVE, 0, qfalse },
-
- { &g_Bubbles, "g_Bubbles", "1", CVAR_ARCHIVE, 0, qfalse },
- { &g_scrimMode, "g_scrimMode", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_gradualFreeFunds, "g_gradualFreeFunds", "2", CVAR_ARCHIVE, 0, qtrue },
- { &g_bleedingSpree, "g_bleedingSpree", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_gradualFreeFunds, "g_gradualFreeFunds", "2", CVAR_ARCHIVE, 0, qtrue },
- { &g_schachtmeisterClearThreshold, "g_schachtmeisterClearThreshold", "-10", CVAR_ARCHIVE, 0, qfalse },
- { &g_schachtmeisterAutobahnThreshold, "g_schachtmeisterAutobahnThreshold", "-30", CVAR_ARCHIVE, 0, qfalse },
- { &g_schachtmeisterAutobahnMessage, "g_schachtmeisterAutobahnMessage", "Your host is blacklisted.", CVAR_ARCHIVE, 0, qfalse },
- { &g_adminAutobahnNotify, "g_adminAutobahnNotify", "1", CVAR_ARCHIVE, 0, qfalse }
+ { &g_specChat, "g_specChat", "1", CVAR_ARCHIVE, 0, qfalse },
+ { &g_publicAdminMessages, "g_publicAdminMessages", "1", CVAR_ARCHIVE, 0, qfalse },
+ { &g_allowTeamOverlay, "g_allowTeamOverlay", "1", CVAR_ARCHIVE, 0, qtrue },
+
+ { &g_censorship, "g_censorship", "", CVAR_ARCHIVE, 0, qfalse },
+
+ { &g_tag, "g_tag", "main", CVAR_INIT, 0, qfalse }
};
-static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] );
+static size_t gameCvarTableSize = ARRAY_LEN( gameCvarTable );
void G_InitGame( int levelTime, int randomSeed, int restart );
@@ -486,9 +306,7 @@ This is the only way control passes into the module.
This must be the very first function compiled into the .q3vm file
================
*/
-Q_EXPORT intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4,
- int arg5, int arg6, int arg7, int arg8, int arg9,
- int arg10, int arg11 )
+Q_EXPORT intptr_t vmMain( int command, int arg0, int arg1, int arg2 )
{
switch( command )
{
@@ -541,10 +359,10 @@ void QDECL G_Printf( const char *fmt, ... )
char text[ 1024 ];
va_start( argptr, fmt );
- vsprintf( text, fmt, argptr );
+ Q_vsnprintf( text, sizeof( text ), fmt, argptr );
va_end( argptr );
- trap_Printf( text );
+ trap_Print( text );
}
void QDECL G_Error( const char *fmt, ... )
@@ -553,7 +371,7 @@ void QDECL G_Error( const char *fmt, ... )
char text[ 1024 ];
va_start( argptr, fmt );
- vsprintf( text, fmt, argptr );
+ Q_vsnprintf( text, sizeof( text ), fmt, argptr );
va_end( argptr );
trap_Error( text );
@@ -579,11 +397,8 @@ void G_FindTeams( void )
c = 0;
c2 = 0;
- for( i = 1, e = g_entities+i; i < level.num_entities; i++, e++ )
+ for( i = MAX_CLIENTS, e = g_entities + i; i < level.num_entities; i++, e++ )
{
- if( !e->inuse )
- continue;
-
if( !e->team )
continue;
@@ -596,9 +411,6 @@ void G_FindTeams( void )
for( j = i + 1, e2 = e + 1; j < level.num_entities; j++, e2++ )
{
- if( !e2->inuse )
- continue;
-
if( !e2->team )
continue;
@@ -626,10 +438,6 @@ void G_FindTeams( void )
G_Printf( "%i teams with %i entities\n", c, c2 );
}
-void G_RemapTeamShaders( void )
-{
-}
-
/*
=================
@@ -640,7 +448,6 @@ void G_RegisterCvars( void )
{
int i;
cvarTable_t *cv;
- qboolean remapped = qfalse;
for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ )
{
@@ -650,12 +457,9 @@ void G_RegisterCvars( void )
if( cv->vmCvar )
cv->modificationCount = cv->vmCvar->modificationCount;
- if( cv->teamShader )
- remapped = qtrue;
+ if( cv->explicit )
+ strcpy( cv->explicit, cv->vmCvar->string );
}
-
- if( remapped )
- G_RemapTeamShaders( );
}
/*
@@ -667,7 +471,6 @@ void G_UpdateCvars( void )
{
int i;
cvarTable_t *cv;
- qboolean remapped = qfalse;
for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ )
{
@@ -680,21 +483,31 @@ void G_UpdateCvars( void )
cv->modificationCount = cv->vmCvar->modificationCount;
if( cv->trackChange )
- {
trap_SendServerCommand( -1, va( "print \"Server: %s changed to %s\n\"",
cv->cvarName, cv->vmCvar->string ) );
- // update serverinfo in case this cvar is passed to clients indirectly
- CalculateRanks( );
- }
- if( cv->teamShader )
- remapped = qtrue;
+ if( !level.spawning && cv->explicit )
+ strcpy( cv->explicit, cv->vmCvar->string );
}
}
}
+}
+
+/*
+=================
+G_RestoreCvars
+=================
+*/
+void G_RestoreCvars( void )
+{
+ int i;
+ cvarTable_t *cv;
- if( remapped )
- G_RemapTeamShaders( );
+ for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ )
+ {
+ if( cv->vmCvar && cv->explicit )
+ trap_Cvar_Set( cv->cvarName, cv->explicit );
+ }
}
/*
@@ -713,7 +526,7 @@ void G_MapConfigs( const char *mapname )
trap_SendConsoleCommand( EXEC_APPEND,
va( "exec \"%s/default.cfg\"\n", g_mapConfigs.string ) );
-
+
trap_SendConsoleCommand( EXEC_APPEND,
va( "exec \"%s/%s.cfg\"\n", g_mapConfigs.string, mapname ) );
@@ -736,11 +549,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
G_Printf( "------- Game Initialization -------\n" );
G_Printf( "gamename: %s\n", GAME_VERSION );
- G_Printf( "gamedate: %s\n", __DATE__ );
- G_ProcessIPBans( );
-
- G_InitMemory( );
+ BG_InitMemory( );
// set some level globals
memset( &level, 0, sizeof( level ) );
@@ -751,9 +561,6 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
level.snd_fry = G_SoundIndex( "sound/misc/fry.wav" ); // FIXME standing in lava / slime
- trap_Cvar_Set( "qvm_version",
- QVM_NAME " " QVM_VERSIONNUM " (" __DATE__ ", " __TIME__ ")" );
-
if( g_logFile.string[ 0 ] )
{
if( g_logFileSync.integer )
@@ -767,17 +574,15 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
{
char serverinfo[ MAX_INFO_STRING ];
qtime_t qt;
- int t;
-
trap_GetServerinfo( serverinfo, sizeof( serverinfo ) );
G_LogPrintf( "------------------------------------------------------------\n" );
G_LogPrintf( "InitGame: %s\n", serverinfo );
- t = trap_RealTime( &qt );
- G_LogPrintf("RealTime: %04i/%02i/%02i %02i:%02i:%02i\n",
- qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday,
+ trap_RealTime( &qt );
+ G_LogPrintf("RealTime: %04i-%02i-%02i %02i:%02i:%02i\n",
+ qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday,
qt.tm_hour, qt.tm_min, qt.tm_sec );
}
@@ -785,19 +590,28 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
else
G_Printf( "Not logging to disk\n" );
+ if( g_mapConfigs.string[ 0 ] && !trap_Cvar_VariableIntegerValue( "g_mapConfigsLoaded" ) )
{
char map[ MAX_CVAR_VALUE_STRING ] = {""};
+ G_Printf( "InitGame: executing map configuration scripts and restarting\n" );
trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
G_MapConfigs( map );
+ trap_SendConsoleCommand( EXEC_APPEND, "wait\nmap_restart 0\n" );
+ }
+ else
+ {
+ // we're done with g_mapConfigs, so reset this for the next map
+ trap_Cvar_Set( "g_mapConfigsLoaded", "0" );
}
- // we're done with g_mapConfigs, so reset this for the next map
- trap_Cvar_Set( "g_mapConfigsLoaded", "0" );
+ // set this cvar to 0 if it exists, but otherwise avoid its creation
+ if( trap_Cvar_VariableIntegerValue( "g_rangeMarkerWarningGiven" ) )
+ trap_Cvar_Set( "g_rangeMarkerWarningGiven", "0" );
- if ( g_admin.string[ 0 ] ) {
- G_admin_readconfig( NULL, 0 );
- }
+ G_RegisterCommands( );
+ G_admin_readconfig( NULL );
+ G_LoadCensors( );
// initialize all entities for this game
memset( g_entities, 0, MAX_GENTITIES * sizeof( g_entities[ 0 ] ) );
@@ -817,26 +631,29 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
// range are NEVER anything but clients
level.num_entities = MAX_CLIENTS;
+ for( i = 0; i < MAX_CLIENTS; i++ )
+ g_entities[ i ].classname = "clientslot";
+
// 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 ] ) );
+ level.emoticonCount = BG_LoadEmoticons( level.emoticons, MAX_EMOTICONS );
+
trap_SetConfigstring( CS_INTERMISSION, "0" );
- // update maplog
- G_admin_maplog_update( );
+ G_InitPlayerModel();
// test to see if a custom buildable layout will be loaded
G_LayoutSelect( );
+ // this has to be flipped after the first UpdateCvars
+ level.spawning = qtrue;
// parse the key/value pairs and spawn gentities
G_SpawnEntitiesFromString( );
// load up a custom building layout if there is one
- G_LayoutLoad( );
-
- // load any nobuild markers that have been saved
- G_NobuildLoad( );
+ G_LayoutLoad( level.layout );
// the map might disable some things
BG_InitAllowedGameElements( );
@@ -844,9 +661,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
// general initialization
G_FindTeams( );
- //TA:
- BG_InitClassOverrides( );
- BG_InitBuildableOverrides( );
+ BG_InitClassConfigs( );
+ BG_InitBuildableConfigs( );
G_InitDamageLocations( );
G_InitMapRotations( );
G_InitSpawnQueue( &level.alienSpawnQueue );
@@ -855,27 +671,27 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
if( g_debugMapRotation.integer )
G_PrintRotations( );
+ level.voices = BG_VoiceInit( );
+ BG_PrintVoices( level.voices, g_debugVoices.integer );
+
//reset stages
trap_Cvar_Set( "g_alienStage", va( "%d", S1 ) );
trap_Cvar_Set( "g_humanStage", va( "%d", S1 ) );
- trap_Cvar_Set( "g_alienKills", 0 );
- trap_Cvar_Set( "g_humanKills", 0 );
- trap_Cvar_Set( "g_suddenDeath", 0 );
+ trap_Cvar_Set( "g_alienCredits", 0 );
+ trap_Cvar_Set( "g_humanCredits", 0 );
level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
G_Printf( "-----------------------------------\n" );
- G_RemapTeamShaders( );
-
- //TA: so the server counts the spawns without a client attached
+ // So the server counts the spawns without a client attached
G_CountSpawns( );
- G_ResetPTRConnections( );
-
- if(g_lockTeamsAtStart.integer)
+ G_UpdateTeamConfigStrings( );
+
+ if( g_lockTeamsAtStart.integer )
{
- level.alienTeamLocked=qtrue;
- level.humanTeamLocked=qtrue;
+ level.alienTeamLocked = qtrue;
+ level.humanTeamLocked = qtrue;
trap_Cvar_Set( "g_lockTeamsAtStart", "0" );
}
}
@@ -889,15 +705,13 @@ remove all currently active votes
*/
static void G_ClearVotes( void )
{
- level.voteTime = 0;
- trap_SetConfigstring( CS_VOTE_TIME, "" );
- trap_SetConfigstring( CS_VOTE_STRING, "" );
- level.teamVoteTime[ 0 ] = 0;
- trap_SetConfigstring( CS_TEAMVOTE_TIME, "" );
- trap_SetConfigstring( CS_TEAMVOTE_STRING, "" );
- level.teamVoteTime[ 1 ] = 0;
- trap_SetConfigstring( CS_TEAMVOTE_TIME + 1, "" );
- trap_SetConfigstring( CS_TEAMVOTE_STRING + 1, "" );
+ int i;
+ memset( level.voteTime, 0, sizeof( level.voteTime ) );
+ for( i = 0; i < NUM_TEAMS; i++ )
+ {
+ trap_SetConfigstring( CS_VOTE_TIME + i, "" );
+ trap_SetConfigstring( CS_VOTE_STRING + i, "" );
+ }
}
/*
@@ -910,6 +724,8 @@ void G_ShutdownGame( int restart )
// in case of a map_restart
G_ClearVotes( );
+ G_RestoreCvars( );
+
G_Printf( "==== ShutdownGame ====\n" );
if( level.logFile )
@@ -917,20 +733,21 @@ void G_ShutdownGame( int restart )
G_LogPrintf( "ShutdownGame:\n" );
G_LogPrintf( "------------------------------------------------------------\n" );
trap_FS_FCloseFile( level.logFile );
+ level.logFile = 0;
}
- // write admin.dat for !seen data
- admin_writeconfig();
-
// write all the client session data so we can get it back
G_WriteSessionData( );
G_admin_cleanup( );
- G_admin_namelog_cleanup( );
- G_admin_adminlog_cleanup( );
+ G_namelog_cleanup( );
+ G_UnregisterCommands( );
+
+ G_FreePlayerModel( );
+ G_ShutdownMapRotations( );
level.restarted = qfalse;
- level.surrenderTeam = PTE_NONE;
+ level.surrenderTeam = TEAM_NONE;
trap_SetConfigstring( CS_WINNER, "" );
}
@@ -944,7 +761,7 @@ void QDECL Com_Error( int level, const char *error, ... )
char text[ 1024 ];
va_start( argptr, error );
- vsprintf( text, error, argptr );
+ Q_vsnprintf( text, sizeof( text ), error, argptr );
va_end( argptr );
G_Error( "%s", text );
@@ -956,7 +773,7 @@ void QDECL Com_Printf( const char *msg, ... )
char text[ 1024 ];
va_start( argptr, msg );
- vsprintf( text, msg, argptr );
+ Q_vsnprintf( text, sizeof( text ), msg, argptr );
va_end( argptr );
G_Printf( "%s", text );
@@ -985,9 +802,9 @@ int QDECL SortRanks( const void *a, const void *b )
cb = &level.clients[ *(int *)b ];
// then sort by score
- if( ca->pers.score > cb->pers.score )
+ if( ca->ps.persistant[ PERS_SCORE ] > cb->ps.persistant[ PERS_SCORE ] )
return -1;
- else if( ca->pers.score < cb->pers.score )
+ if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] )
return 1;
else
return 0;
@@ -1016,7 +833,7 @@ void G_InitSpawnQueue( spawnQueue_t *sq )
============
G_GetSpawnQueueLength
-Return tha length of a spawn queue
+Return the length of a spawn queue
============
*/
int G_GetSpawnQueueLength( spawnQueue_t *sq )
@@ -1047,6 +864,7 @@ int G_PopSpawnQueue( spawnQueue_t *sq )
{
sq->clients[ sq->front ] = -1;
sq->front = QUEUE_PLUS1( sq->front );
+ G_StopFollowing( g_entities + clientNum );
g_entities[ clientNum ].client->ps.pm_flags &= ~PMF_QUEUED;
return clientNum;
@@ -1079,8 +897,11 @@ qboolean G_SearchSpawnQueue( spawnQueue_t *sq, int clientNum )
int i;
for( i = 0; i < MAX_CLIENTS; i++ )
+ {
if( sq->clients[ i ] == clientNum )
return qtrue;
+ }
+
return qfalse;
}
@@ -1211,24 +1032,20 @@ G_SpawnClients
Spawn queued clients
============
*/
-void G_SpawnClients( pTeam_t team )
+void G_SpawnClients( team_t team )
{
int clientNum;
gentity_t *ent, *spawn;
vec3_t spawn_origin, spawn_angles;
spawnQueue_t *sq = NULL;
int numSpawns = 0;
- if( g_doWarmup.integer && ( g_warmupMode.integer==1 || g_warmupMode.integer == 2 ) &&
- level.time - level.startTime < g_warmup.integer * 1000 )
- {
- return;
- }
- if( team == PTE_ALIENS )
+
+ if( team == TEAM_ALIENS )
{
sq = &level.alienSpawnQueue;
numSpawns = level.numAlienSpawns;
}
- else if( team == PTE_HUMANS )
+ else if( team == TEAM_HUMANS )
{
sq = &level.humanSpawnQueue;
numSpawns = level.numHumanSpawns;
@@ -1250,7 +1067,7 @@ void G_SpawnClients( pTeam_t team )
ent = &g_entities[ clientNum ];
- ent->client->sess.sessionTeam = TEAM_FREE;
+ ent->client->sess.spectatorState = SPECTATOR_NOT;
ClientUserinfoChanged( clientNum, qfalse );
ClientSpawn( ent, spawn, spawn_origin, spawn_angles );
}
@@ -1271,33 +1088,31 @@ void G_CountSpawns( void )
level.numAlienSpawns = 0;
level.numHumanSpawns = 0;
-
for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
{
- if( !ent->inuse )
+ if( !ent->inuse || ent->s.eType != ET_BUILDABLE || ent->health <= 0 )
continue;
- if( ent->s.modelindex == BA_A_SPAWN && ent->health > 0 )
+ if( ent->s.modelindex == BA_A_SPAWN )
level.numAlienSpawns++;
- if( ent->s.modelindex == BA_H_SPAWN && ent->health > 0 )
+ if( ent->s.modelindex == BA_H_SPAWN )
level.numHumanSpawns++;
}
-
- //let the client know how many spawns there are
- trap_SetConfigstring( CS_SPAWNS, va( "%d %d",
- level.numAlienSpawns, level.numHumanSpawns ) );
}
+
/*
============
G_TimeTilSuddenDeath
============
*/
+#define SUDDENDEATHWARNING 60000
int G_TimeTilSuddenDeath( void )
{
- if( (!g_suddenDeathTime.integer && level.suddenDeathBeginTime==0 ) || level.suddenDeathBeginTime<0 )
- return 999999999; // Always some time away
+ if( ( !g_suddenDeathTime.integer && level.suddenDeathBeginTime == 0 ) ||
+ ( level.suddenDeathBeginTime < 0 ) )
+ return SUDDENDEATHWARNING + 1; // Always some time away
return ( ( level.suddenDeathBeginTime ) - ( level.time - level.startTime ) );
}
@@ -1314,180 +1129,152 @@ Recalculate the quantity of building points available to the teams
*/
void G_CalculateBuildPoints( void )
{
- int i;
- buildable_t buildable;
- gentity_t *ent;
- int localHTP = g_humanBuildPoints.integer,
- localATP = g_alienBuildPoints.integer;
-
- // g_suddenDeath sets what state we want it to be.
- // level.suddenDeath says whether we've calculated BPs at the 'start' of SD or not
+ int i;
+ buildable_t buildable;
+ buildPointZone_t *zone;
- // reset if SD was on, but now it's off
- if(!g_suddenDeath.integer && level.suddenDeath)
+ // BP queue updates
+ while( level.alienBuildPointQueue > 0 &&
+ level.alienNextQueueTime < level.time )
{
- level.suddenDeath = qfalse;
- level.suddenDeathWarning = 0;
- level.suddenDeathBeginTime = -1;
- if((level.time - level.startTime) < (g_suddenDeathTime.integer * 60000 ) )
- level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
- else
- level.suddenDeathBeginTime = -1;
+ level.alienBuildPointQueue--;
+ level.alienNextQueueTime += G_NextQueueTime( level.alienBuildPointQueue,
+ g_alienBuildPoints.integer,
+ g_alienBuildQueueTime.integer );
}
- if(!level.suddenDeath)
+ while( level.humanBuildPointQueue > 0 &&
+ level.humanNextQueueTime < level.time )
{
- if(g_suddenDeath.integer || G_TimeTilSuddenDeath( ) <= 0 ) //Conditions to enter SD
- {
- //begin sudden death
- if( level.suddenDeathWarning < TW_PASSED )
- {
- trap_SendServerCommand( -1, "cp \"Sudden Death!\"" );
- G_LogPrintf("Beginning Sudden Death (Mode %d)\n",g_suddenDeathMode.integer);
- localHTP = 0;
- localATP = 0;
+ level.humanBuildPointQueue--;
+ level.humanNextQueueTime += G_NextQueueTime( level.humanBuildPointQueue,
+ g_humanBuildPoints.integer,
+ g_humanBuildQueueTime.integer );
+ }
- if( g_suddenDeathMode.integer == SDMODE_SELECTIVE )
- {
- for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
- {
- if( ent->s.eType != ET_BUILDABLE )
- continue;
-
- if( BG_FindReplaceableTestForBuildable( ent->s.modelindex ) )
- {
- int t = BG_FindTeamForBuildable( ent->s.modelindex );
-
- if( t == BIT_HUMANS )
- localHTP += BG_FindBuildPointsForBuildable( ent->s.modelindex );
- else if( t == BIT_ALIENS )
- localATP += BG_FindBuildPointsForBuildable( ent->s.modelindex );
- }
- }
- }
- level.suddenDeathHBuildPoints = localHTP;
- level.suddenDeathABuildPoints = localATP;
- level.suddenDeathBeginTime = level.time;
- level.suddenDeath=qtrue;
- trap_Cvar_Set( "g_suddenDeath", "1" );
+ // Sudden Death checks
+ if( G_TimeTilSuddenDeath( ) <= 0 && level.suddenDeathWarning < TW_PASSED )
+ {
+ G_LogPrintf( "Beginning Sudden Death\n" );
+ trap_SendServerCommand( -1, "cp \"Sudden Death!\"" );
+ trap_SendServerCommand( -1, "print \"Beginning Sudden Death.\n\"" );
+ level.suddenDeathWarning = TW_PASSED;
+ G_ClearDeconMarks( );
- level.suddenDeathWarning = TW_PASSED;
- }
- }
- else
+ // Clear blueprints, or else structs that cost 0 BP can still be built after SD
+ for( i = 0; i < level.maxclients; i++ )
{
- //warn about sudden death
- if( ( G_TimeTilSuddenDeath( ) <= 60000 ) &&
- ( level.suddenDeathWarning < TW_IMMINENT ) )
- {
- trap_SendServerCommand( -1, va("cp \"Sudden Death in %d seconds!\"",
- (int)(G_TimeTilSuddenDeath() / 1000 ) ) );
- level.suddenDeathWarning = TW_IMMINENT;
- }
+ if( g_entities[ i ].client->ps.stats[ STAT_BUILDABLE ] != BA_NONE )
+ g_entities[ i ].client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
}
}
-
- //set BP at each cycle
- if( g_suddenDeath.integer )
+ else if( G_TimeTilSuddenDeath( ) <= SUDDENDEATHWARNING &&
+ level.suddenDeathWarning < TW_IMMINENT )
{
- localHTP = level.suddenDeathHBuildPoints;
- localATP = level.suddenDeathABuildPoints;
+ trap_SendServerCommand( -1, va( "cp \"Sudden Death in %d seconds!\"",
+ (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) );
+ trap_SendServerCommand( -1, va( "print \"Sudden Death will begin in %d seconds.\n\"",
+ (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) );
+ level.suddenDeathWarning = TW_IMMINENT;
}
- else
+
+ level.humanBuildPoints = g_humanBuildPoints.integer - level.humanBuildPointQueue;
+ level.alienBuildPoints = g_alienBuildPoints.integer - level.alienBuildPointQueue;
+
+ // Reset buildPointZones
+ for( i = 0; i < g_humanRepeaterMaxZones.integer; i++ )
{
- localHTP = g_humanBuildPoints.integer;
- localATP = g_alienBuildPoints.integer;
+ buildPointZone_t *zone = &level.buildPointZones[ i ];
+
+ zone->active = qfalse;
+ zone->totalBuildPoints = g_humanRepeaterBuildPoints.integer;
}
- level.humanBuildPoints = level.humanBuildPointsPowered = localHTP;
- level.alienBuildPoints = localATP;
+ // Iterate through entities
+ for( i = MAX_CLIENTS; i < level.num_entities; i++ )
+ {
+ gentity_t *ent = &g_entities[ i ];
+ buildPointZone_t *zone;
+ buildable_t buildable;
+ int cost;
- level.reactorPresent = qfalse;
- level.overmindPresent = qfalse;
+ if( ent->s.eType != ET_BUILDABLE || ent->s.eFlags & EF_DEAD )
+ continue;
- for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
+ // mark a zone as active
+ if( ent->usesBuildPointZone )
+ {
+ assert( ent->buildPointZone >= 0 && ent->buildPointZone < g_humanRepeaterMaxZones.integer );
+
+ zone = &level.buildPointZones[ ent->buildPointZone ];
+ zone->active = qtrue;
+ }
+
+ // Subtract the BP from the appropriate pool
+ buildable = ent->s.modelindex;
+ cost = BG_Buildable( buildable )->buildPoints;
+
+ if( ent->buildableTeam == TEAM_ALIENS )
+ level.alienBuildPoints -= cost;
+ if( buildable == BA_H_REPEATER )
+ level.humanBuildPoints -= cost;
+ else if( buildable != BA_H_REACTOR )
+ {
+ gentity_t *power = G_PowerEntityForEntity( ent );
+
+ if( power )
+ {
+ if( power->s.modelindex == BA_H_REACTOR )
+ level.humanBuildPoints -= cost;
+ else if( power->s.modelindex == BA_H_REPEATER && power->usesBuildPointZone )
+ level.buildPointZones[ power->buildPointZone ].totalBuildPoints -= cost;
+ }
+ }
+ }
+
+ // Finally, update repeater zones and their queues
+ // note that this has to be done after the used BP is calculated
+ for( i = MAX_CLIENTS; i < level.num_entities; i++ )
{
- if( !ent->inuse )
- continue;
+ gentity_t *ent = &g_entities[ i ];
- if( ent->s.eType != ET_BUILDABLE )
+ if( ent->s.eType != ET_BUILDABLE || ent->s.eFlags & EF_DEAD ||
+ ent->buildableTeam != TEAM_HUMANS )
continue;
buildable = ent->s.modelindex;
- if( buildable != BA_NONE )
- {
- if( buildable == BA_H_REACTOR && ent->spawned && ent->health > 0 )
- level.reactorPresent = qtrue;
+ if( buildable != BA_H_REPEATER )
+ continue;
- if( buildable == BA_A_OVERMIND && ent->spawned && ent->health > 0 )
- level.overmindPresent = qtrue;
+ if( ent->usesBuildPointZone && level.buildPointZones[ ent->buildPointZone ].active )
+ {
+ zone = &level.buildPointZones[ ent->buildPointZone ];
- if( !g_suddenDeath.integer || BG_FindReplaceableTestForBuildable( buildable ) )
+ if( G_TimeTilSuddenDeath( ) > 0 )
{
- if( BG_FindTeamForBuildable( buildable ) == BIT_HUMANS )
- {
- level.humanBuildPoints -= BG_FindBuildPointsForBuildable( buildable );
- if( ent->powered )
- level.humanBuildPointsPowered -= BG_FindBuildPointsForBuildable( buildable );
- }
- else
+ // BP queue updates
+ while( zone->queuedBuildPoints > 0 &&
+ zone->nextQueueTime < level.time )
{
- level.alienBuildPoints -= BG_FindBuildPointsForBuildable( buildable );
+ zone->queuedBuildPoints--;
+ zone->nextQueueTime += G_NextQueueTime( zone->queuedBuildPoints,
+ zone->totalBuildPoints,
+ g_humanRepeaterBuildQueueTime.integer );
}
}
+ else
+ {
+ zone->totalBuildPoints = zone->queuedBuildPoints = 0;
+ }
}
}
if( level.humanBuildPoints < 0 )
- {
- localHTP -= level.humanBuildPoints;
- level.humanBuildPointsPowered -= level.humanBuildPoints;
level.humanBuildPoints = 0;
- }
if( level.alienBuildPoints < 0 )
- {
- localATP -= level.alienBuildPoints;
level.alienBuildPoints = 0;
- }
-
- trap_SetConfigstring( CS_BUILDPOINTS, va( "%d %d %d %d %d",
- level.alienBuildPoints, localATP,
- level.humanBuildPoints, localHTP,
- level.humanBuildPointsPowered ) );
-
- //may as well pump the stages here too
- {
- float alienPlayerCountMod = level.averageNumAlienClients / PLAYER_COUNT_MOD;
- float humanPlayerCountMod = level.averageNumHumanClients / PLAYER_COUNT_MOD;
- int alienNextStageThreshold, humanNextStageThreshold;
-
- if( alienPlayerCountMod < 0.1f )
- alienPlayerCountMod = 0.1f;
-
- if( humanPlayerCountMod < 0.1f )
- humanPlayerCountMod = 0.1f;
-
- if( g_alienStage.integer == S1 && g_alienMaxStage.integer > S1 )
- alienNextStageThreshold = (int)( ceil( (float)g_alienStage2Threshold.integer * alienPlayerCountMod ) );
- else if( g_alienStage.integer == S2 && g_alienMaxStage.integer > S2 )
- alienNextStageThreshold = (int)( ceil( (float)g_alienStage3Threshold.integer * alienPlayerCountMod ) );
- else
- alienNextStageThreshold = -1;
-
- if( g_humanStage.integer == S1 && g_humanMaxStage.integer > S1 )
- humanNextStageThreshold = (int)( ceil( (float)g_humanStage2Threshold.integer * humanPlayerCountMod ) );
- else if( g_humanStage.integer == S2 && g_humanMaxStage.integer > S2 )
- humanNextStageThreshold = (int)( ceil( (float)g_humanStage3Threshold.integer * humanPlayerCountMod ) );
- else
- humanNextStageThreshold = -1;
-
- trap_SetConfigstring( CS_STAGES, va( "%d %d %d %d %d %d",
- g_alienStage.integer, g_humanStage.integer,
- g_alienKills.integer, g_humanKills.integer,
- alienNextStageThreshold, humanNextStageThreshold ) );
- }
}
/*
@@ -1499,8 +1286,11 @@ void G_CalculateStages( void )
{
float alienPlayerCountMod = level.averageNumAlienClients / PLAYER_COUNT_MOD;
float humanPlayerCountMod = level.averageNumHumanClients / PLAYER_COUNT_MOD;
+ int alienNextStageThreshold, humanNextStageThreshold;
static int lastAlienStageModCount = 1;
static int lastHumanStageModCount = 1;
+ static int alienTriggerStage = 0;
+ static int humanTriggerStage = 0;
if( alienPlayerCountMod < 0.1f )
alienPlayerCountMod = 0.1f;
@@ -1508,7 +1298,7 @@ void G_CalculateStages( void )
if( humanPlayerCountMod < 0.1f )
humanPlayerCountMod = 0.1f;
- if( g_alienKills.integer >=
+ if( g_alienCredits.integer >=
(int)( ceil( (float)g_alienStage2Threshold.integer * alienPlayerCountMod ) ) &&
g_alienStage.integer == S1 && g_alienMaxStage.integer > S1 )
{
@@ -1518,7 +1308,7 @@ void G_CalculateStages( void )
G_LogPrintf("Stage: A 2: Aliens reached Stage 2\n");
}
- if( g_alienKills.integer >=
+ if( g_alienCredits.integer >=
(int)( ceil( (float)g_alienStage3Threshold.integer * alienPlayerCountMod ) ) &&
g_alienStage.integer == S2 && g_alienMaxStage.integer > S2 )
{
@@ -1528,7 +1318,7 @@ void G_CalculateStages( void )
G_LogPrintf("Stage: A 3: Aliens reached Stage 3\n");
}
- if( g_humanKills.integer >=
+ if( g_humanCredits.integer >=
(int)( ceil( (float)g_humanStage2Threshold.integer * humanPlayerCountMod ) ) &&
g_humanStage.integer == S1 && g_humanMaxStage.integer > S1 )
{
@@ -1538,30 +1328,33 @@ void G_CalculateStages( void )
G_LogPrintf("Stage: H 2: Humans reached Stage 2\n");
}
- if( g_humanKills.integer >=
+ if( g_humanCredits.integer >=
(int)( ceil( (float)g_humanStage3Threshold.integer * humanPlayerCountMod ) ) &&
g_humanStage.integer == S2 && g_humanMaxStage.integer > S2 )
{
trap_Cvar_Set( "g_humanStage", va( "%d", S3 ) );
level.humanStage3Time = level.time;
- G_LogPrintf("Stage: H 3: Humans reached Stage 3\n");
lastHumanStageModCount = g_humanStage.modificationCount;
+ G_LogPrintf("Stage: H 3: Humans reached Stage 3\n");
}
-
+
if( g_alienStage.modificationCount > lastAlienStageModCount )
{
- G_Checktrigger_stages( PTE_ALIENS, g_alienStage.integer );
- if( g_alienStage.integer == S2 )
+ while( alienTriggerStage < MIN( g_alienStage.integer, S3 ) )
+ G_Checktrigger_stages( TEAM_ALIENS, ++alienTriggerStage );
+
+ if( g_alienStage.integer == S2 )
level.alienStage2Time = level.time;
else if( g_alienStage.integer == S3 )
level.alienStage3Time = level.time;
-
+
lastAlienStageModCount = g_alienStage.modificationCount;
}
-
+
if( g_humanStage.modificationCount > lastHumanStageModCount )
{
- G_Checktrigger_stages( PTE_HUMANS, g_humanStage.integer );
+ while( humanTriggerStage < MIN( g_humanStage.integer, S3 ) )
+ G_Checktrigger_stages( TEAM_HUMANS, ++humanTriggerStage );
if( g_humanStage.integer == S2 )
level.humanStage2Time = level.time;
@@ -1570,6 +1363,35 @@ void G_CalculateStages( void )
lastHumanStageModCount = g_humanStage.modificationCount;
}
+
+ if( g_alienStage.integer == S1 && g_alienMaxStage.integer > S1 )
+ alienNextStageThreshold = (int)( ceil( (float)g_alienStage2Threshold.integer * alienPlayerCountMod ) );
+ else if( g_alienStage.integer == S2 && g_alienMaxStage.integer > S2 )
+ alienNextStageThreshold = (int)( ceil( (float)g_alienStage3Threshold.integer * alienPlayerCountMod ) );
+ else
+ alienNextStageThreshold = -1;
+
+ if( g_humanStage.integer == S1 && g_humanMaxStage.integer > S1 )
+ humanNextStageThreshold = (int)( ceil( (float)g_humanStage2Threshold.integer * humanPlayerCountMod ) );
+ else if( g_humanStage.integer == S2 && g_humanMaxStage.integer > S2 )
+ humanNextStageThreshold = (int)( ceil( (float)g_humanStage3Threshold.integer * humanPlayerCountMod ) );
+ else
+ humanNextStageThreshold = -1;
+
+ // save a lot of bandwidth by rounding thresholds up to the nearest 100
+ if( alienNextStageThreshold > 0 )
+ alienNextStageThreshold = ceil( (float)alienNextStageThreshold / 100 ) * 100;
+
+ if( humanNextStageThreshold > 0 )
+ humanNextStageThreshold = ceil( (float)humanNextStageThreshold / 100 ) * 100;
+
+ trap_SetConfigstring( CS_ALIEN_STAGES, va( "%d %d %d",
+ g_alienStage.integer, g_alienCredits.integer,
+ alienNextStageThreshold ) );
+
+ trap_SetConfigstring( CS_HUMAN_STAGES, va( "%d %d %d",
+ g_humanStage.integer, g_humanCredits.integer,
+ humanNextStageThreshold ) );
}
/*
@@ -1587,13 +1409,13 @@ void G_CalculateAvgPlayers( void )
if( !level.numAlienClients )
{
level.numAlienSamples = 0;
- trap_Cvar_Set( "g_alienKills", "0" );
+ trap_Cvar_Set( "g_alienCredits", "0" );
}
if( !level.numHumanClients )
{
level.numHumanSamples = 0;
- trap_Cvar_Set( "g_humanKills", "0" );
+ trap_Cvar_Set( "g_humanCredits", "0" );
}
//calculate average number of clients for stats
@@ -1623,16 +1445,14 @@ void CalculateRanks( void )
{
int i;
char P[ MAX_CLIENTS + 1 ] = {""};
- int ff = 0;
level.numConnectedClients = 0;
- level.numNonSpectatorClients = 0;
level.numPlayingClients = 0;
- level.numVotingClients = 0; // don't count bots
+ memset( level.numVotingClients, 0, sizeof( level.numVotingClients ) );
level.numAlienClients = 0;
level.numHumanClients = 0;
- level.numLiveAlienClients = 0;
- level.numLiveHumanClients = 0;
+ level.numAlienClientsAlive = 0;
+ level.numHumanClientsAlive = 0;
for( i = 0; i < level.maxclients; i++ )
{
@@ -1643,46 +1463,36 @@ void CalculateRanks( void )
level.numConnectedClients++;
P[ i ] = (char)'0' + level.clients[ i ].pers.teamSelection;
+ level.numVotingClients[ TEAM_NONE ]++;
+
if( level.clients[ i ].pers.connected != CON_CONNECTED )
continue;
- level.numVotingClients++;
- if( level.clients[ i ].pers.teamSelection != PTE_NONE )
+ if( level.clients[ i ].pers.teamSelection != TEAM_NONE )
{
level.numPlayingClients++;
- if( level.clients[ i ].sess.sessionTeam != TEAM_SPECTATOR )
- level.numNonSpectatorClients++;
-
- if( level.clients[ i ].pers.teamSelection == PTE_ALIENS )
+ if( level.clients[ i ].pers.teamSelection == TEAM_ALIENS )
{
level.numAlienClients++;
- if( level.clients[ i ].sess.sessionTeam != TEAM_SPECTATOR )
- level.numLiveAlienClients++;
+ if( level.clients[ i ].sess.spectatorState == SPECTATOR_NOT )
+ level.numAlienClientsAlive++;
}
- else if( level.clients[ i ].pers.teamSelection == PTE_HUMANS )
+ else if( level.clients[ i ].pers.teamSelection == TEAM_HUMANS )
{
level.numHumanClients++;
- if( level.clients[ i ].sess.sessionTeam != TEAM_SPECTATOR )
- level.numLiveHumanClients++;
+ if( level.clients[ i ].sess.spectatorState == SPECTATOR_NOT )
+ level.numHumanClientsAlive++;
}
}
}
}
- level.numteamVotingClients[ 0 ] = level.numHumanClients;
- level.numteamVotingClients[ 1 ] = level.numAlienClients;
+ level.numNonSpectatorClients = level.numAlienClientsAlive +
+ level.numHumanClientsAlive;
+ level.numVotingClients[ TEAM_ALIENS ] = level.numAlienClients;
+ level.numVotingClients[ TEAM_HUMANS ] = level.numHumanClients;
P[ i ] = '\0';
trap_Cvar_Set( "P", P );
- if( g_friendlyFire.value>0 )
- ff |= ( FFF_HUMANS | FFF_ALIENS );
- if( g_friendlyFireHumans.value>0 )
- ff |= FFF_HUMANS;
- if( g_friendlyFireAliens.value>0 )
- ff |= FFF_ALIENS;
- if( g_friendlyBuildableFire.value>0 )
- ff |= FFF_BUILDABLES;
- trap_Cvar_Set( "ff", va( "%i", ff ) );
-
qsort( level.sortedClients, level.numConnectedClients,
sizeof( level.sortedClients[ 0 ] ), SortRanks );
@@ -1690,7 +1500,7 @@ void CalculateRanks( void )
CheckExitRules( );
// if we are at the intermission, send the new info to everyone
- if( level.intermissiontime && !level.mapRotationVoteTime )
+ if( level.intermissiontime )
SendScoreboardMessageToAllClients( );
}
@@ -1737,8 +1547,10 @@ void MoveClientToIntermission( gentity_t *ent )
G_StopFollowing( ent );
// move to the spot
- VectorCopy( level.intermission_origin, ent->s.origin );
+ VectorCopy( level.intermission_origin, ent->s.pos.trBase );
+ VectorCopy( level.intermission_origin, ent->r.currentOrigin );
VectorCopy( level.intermission_origin, ent->client->ps.origin );
+ VectorCopy( level.intermission_angle, ent->s.apos.trBase );
VectorCopy( level.intermission_angle, ent->client->ps.viewangles );
ent->client->ps.pm_type = PM_INTERMISSION;
@@ -1748,7 +1560,6 @@ void MoveClientToIntermission( gentity_t *ent )
ent->client->ps.eFlags = 0;
ent->s.eFlags = 0;
ent->s.eType = ET_GENERAL;
- ent->s.modelindex = 0;
ent->s.loopSound = 0;
ent->s.event = 0;
ent->r.contents = 0;
@@ -1775,8 +1586,8 @@ void FindIntermissionPoint( void )
}
else
{
- VectorCopy( ent->s.origin, level.intermission_origin );
- VectorCopy( ent->s.angles, level.intermission_angle );
+ VectorCopy( ent->r.currentOrigin, level.intermission_origin );
+ VectorCopy( ent->r.currentAngles, level.intermission_angle );
// if it has a target, look towards it
if( ent->target )
{
@@ -1784,7 +1595,7 @@ void FindIntermissionPoint( void )
if( target )
{
- VectorSubtract( target->s.origin, level.intermission_origin, dir );
+ VectorSubtract( target->r.currentOrigin, level.intermission_origin, dir );
vectoangles( dir, level.intermission_angle );
}
}
@@ -1805,12 +1616,12 @@ void BeginIntermission( void )
if( level.intermissiontime )
return; // already active
- level.numTeamWarnings = 99;
-
level.intermissiontime = level.time;
G_ClearVotes( );
+ G_UpdateTeamConfigStrings( );
+
FindIntermissionPoint( );
// move all clients to the intermission point
@@ -1830,42 +1641,8 @@ void BeginIntermission( void )
// send the current scoring to all clients
SendScoreboardMessageToAllClients( );
-
- if( g_nextMap.string[ 0 ] )
- {
- trap_SendServerCommand( -1,
- va( "print \"next map has been set to %s^7%s\n\"",
- g_nextMap.string,
- ( G_CheckMapRotationVote() ) ? ", voting will be skipped" : "" ) );
- }
}
-void BeginMapRotationVote( void )
-{
- gentity_t *ent;
- int length;
- int i;
-
- if( level.mapRotationVoteTime )
- return;
-
- length = g_mapRotationVote.integer;
- if( length > 60 )
- length = 60;
- level.mapRotationVoteTime = level.time + ( length * 1000 );
-
- for( i = 0; i < level.maxclients; i++ )
- {
- ent = g_entities + i;
-
- if( !ent->inuse )
- continue;
-
- ent->client->ps.pm_type = PM_SPECTATOR;
- ent->client->sess.sessionTeam = TEAM_SPECTATOR;
- ent->client->sess.spectatorState = SPECTATOR_LOCKED;
- }
-}
/*
=============
@@ -1879,44 +1656,22 @@ void ExitLevel( void )
{
int i;
gclient_t *cl;
- buildHistory_t *tmp, *mark;
-
- char currentmap[ MAX_CVAR_VALUE_STRING ];
-
- trap_Cvar_VariableStringBuffer( "mapname", currentmap, sizeof( currentmap ));
-
- if( level.mapRotationVoteTime )
- {
- if( level.time < level.mapRotationVoteTime &&
- !G_IntermissionMapVoteWinner( ) )
- return;
- }
- else if( g_mapRotationVote.integer > 0 &&
- G_CheckMapRotationVote() &&
- !g_nextMap.string[ 0 ] )
- {
- BeginMapRotationVote( );
- return;
- }
- while( ( tmp = level.buildHistory ) )
+ if ( G_MapExists( g_nextMap.string ) )
{
- level.buildHistory = level.buildHistory->next;
- while( ( mark = tmp ) )
- {
- tmp = tmp->marked;
- G_Free( mark );
- }
+ G_MapConfigs( g_nextMap.string );
+ trap_SendConsoleCommand( EXEC_APPEND, va( "%smap \"%s\"\n",
+ ( g_cheats.integer ? "dev" : "" ), g_nextMap.string ) );
}
-
- if( !Q_stricmp( currentmap, g_nextMap.string ) )
- trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" );
- else if ( G_MapExists( g_nextMap.string ) )
- trap_SendConsoleCommand( EXEC_APPEND, va("!map %s\n", g_nextMap.string ) );
else if( G_MapRotationActive( ) )
- G_AdvanceMapRotation( );
+ G_AdvanceMapRotation( 0 );
else
+ {
+ char map[ MAX_CVAR_VALUE_STRING ];
+ trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
+ G_MapConfigs( map );
trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" );
+ }
trap_Cvar_Set( "g_nextMap", "" );
@@ -1934,7 +1689,7 @@ void ExitLevel( void )
cl->ps.persistant[ PERS_SCORE ] = 0;
}
- // we need to do this here before chaning to CON_CONNECTING
+ // we need to do this here before changing to CON_CONNECTING
G_WriteSessionData( );
// change all client states to connecting, so the early players into the
@@ -1946,79 +1701,48 @@ void ExitLevel( void )
}
}
+
/*
=================
-G_AdminsPrintf
+G_AdminMessage
-Print to all active admins, and the logfile with a time stamp if it is open, and to the console
+Print to all active server admins, and to the logfile, and to the server console
=================
*/
-void QDECL G_AdminsPrintf( const char *fmt, ... )
+void G_AdminMessage( gentity_t *ent, const char *msg )
{
- va_list argptr;
char string[ 1024 ];
- gentity_t *tempent;
- int j;
-
- va_start( argptr, fmt );
- vsprintf( string, fmt,argptr );
- va_end( argptr );
+ int i;
- for( j = 0; j < level.maxclients; j++ )
- {
- tempent = &g_entities[ j ];
- if( G_admin_permission( tempent, ADMF_ADMINCHAT ) &&
- !tempent->client->pers.ignoreAdminWarnings )
- {
- trap_SendServerCommand(tempent-g_entities,va( "print \"^6[Admins]^7 %s\"", string) );
- }
- }
-
- G_LogPrintf("%s",string);
+ Com_sprintf( string, sizeof( string ), "chat %d %d \"%s\"",
+ (int)( ent ? ent - g_entities : -1 ),
+ G_admin_permission( ent, ADMF_ADMINCHAT ) ? SAY_ADMINS : SAY_ADMINS_PUBLIC,
+ msg );
+ // Send to all appropriate clients
+ for( i = 0; i < level.maxclients; i++ )
+ if( G_admin_permission( &g_entities[ i ], ADMF_ADMINCHAT ) )
+ trap_SendServerCommand( i, string );
+
+ // Send to the logfile and server console
+ G_LogPrintf( "%s: %d \"%s" S_COLOR_WHITE "\": " S_COLOR_MAGENTA "%s\n",
+ G_admin_permission( ent, ADMF_ADMINCHAT ) ? "AdminMsg" : "AdminMsgPublic",
+ (int)( ent ? ent - g_entities : -1 ), ent ? ent->client->pers.netname : "console",
+ msg );
}
-/*
-=================
-G_WarningsPrintf
-
-Print to everyone with a certain flag, and the logfile with a time stamp if it is open, and to the console
-(just a copy of the G_AdminsPrintf with flag suport)
-=================
-*/
-void QDECL G_WarningsPrintf( char *flag, const char *fmt, ... )
-{
- va_list argptr;
- char string[ 1024 ];
- gentity_t *tempent;
- int j;
- va_start( argptr, fmt );
- vsprintf( string, fmt,argptr );
- va_end( argptr );
-
- for( j = 0; j < level.maxclients; j++ )
- {
- tempent = &g_entities[ j ];
- if( G_admin_permission( tempent, flag ) )
- {
- trap_SendServerCommand(tempent-g_entities,va( "print \"^6[Warnings]^7 %s\"", string) );
- }
- }
-
- G_LogPrintf("%s",string);
-}
/*
=================
G_LogPrintf
-Print to the logfile with a time stamp if it is open
+Print to the logfile with a time stamp if it is open, and to the server console
=================
*/
void QDECL G_LogPrintf( const char *fmt, ... )
{
va_list argptr;
- char string[ 1024 ], decoloured[ 1024 ];
+ char string[ 1024 ], decolored[ 1024 ];
int min, tens, sec;
sec = ( level.time - level.startTime ) / 1000;
@@ -2031,186 +1755,20 @@ void QDECL G_LogPrintf( const char *fmt, ... )
Com_sprintf( string, sizeof( string ), "%3i:%i%i ", min, tens, sec );
va_start( argptr, fmt );
- vsprintf( string +7 , fmt,argptr );
+ Q_vsnprintf( string + 7, sizeof( string ) - 7, fmt, argptr );
va_end( argptr );
if( g_dedicated.integer )
- G_Printf( "%s", string + 7 );
-
- if( !level.logFile )
- return;
-
- if( g_decolourLogfiles.integer )
- {
- G_DecolorString( string, decoloured );
- trap_FS_Write( decoloured, strlen( decoloured ), level.logFile );
- }
- else
{
- trap_FS_Write( string, strlen( string ), level.logFile );
+ G_UnEscapeString( string, decolored, sizeof( decolored ) );
+ G_Printf( "%s", decolored + 7 );
}
-}
-
-/*
-=================
-G_LogPrintfColoured
-
-Bypasses g_decolourLogfiles for events that need colors in the logs
-=================
-*/
-void QDECL G_LogPrintfColoured( const char *fmt, ... )
-{
- va_list argptr;
- char string[ 1024 ];
- int min, tens, sec;
-
- sec = (level.time - level.startTime) / 1000;
-
- min = sec / 60;
- sec -= min * 60;
- tens = sec / 10;
- sec -= tens * 10;
-
- Com_sprintf( string, sizeof( string ), "%3i:%i%i ", min, tens, sec );
-
- va_start( argptr, fmt );
- vsprintf( string +7 , fmt,argptr );
- va_end( argptr );
-
- if( g_dedicated.integer )
- G_Printf( "%s", string + 7 );
if( !level.logFile )
return;
- trap_FS_Write( string, strlen( string ), level.logFile );
-}
-
-/*
-=================
-G_LogOnlyPrintf
-
-Print to the logfile only (not console) with a time stamp if it is open
-=================
-*/
-void QDECL G_LogOnlyPrintf( const char *fmt, ... )
-{
- va_list argptr;
- char string[ 1024 ], decoloured[ 1024 ];
- int min, tens, sec;
-
- sec = (level.time - level.startTime) / 1000;
-
- min = sec / 60;
- sec -= min * 60;
- tens = sec / 10;
- sec -= tens * 10;
-
- Com_sprintf( string, sizeof( string ), "%3i:%i%i ", min, tens, sec );
-
- va_start( argptr, fmt );
- vsprintf( string +7 , fmt,argptr );
- va_end( argptr );
-
- if( !level.logFile )
- return;
-
- if( g_decolourLogfiles.integer )
- {
- G_DecolorString( string, decoloured );
- trap_FS_Write( decoloured, strlen( decoloured ), level.logFile );
- }
- else
- {
- trap_FS_Write( string, strlen( string ), level.logFile );
- }
-}
-
-/*
-=================
-G_SendGameStat
-=================
-*/
-void G_SendGameStat( pTeam_t team )
-{
- char map[ MAX_STRING_CHARS ];
- char teamChar;
- char data[ BIG_INFO_STRING ];
- char entry[ MAX_STRING_CHARS ];
- int i, dataLength, entryLength;
- gclient_t *cl;
-
- trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
-
- switch( team )
- {
- case PTE_ALIENS: teamChar = 'A'; break;
- case PTE_HUMANS: teamChar = 'H'; break;
- case PTE_NONE: teamChar = 'L'; break;
- default: return;
- }
-
- Com_sprintf( data, BIG_INFO_STRING,
- "%s %s T:%c A:%f H:%f M:%s D:%d SD:%d AS:%d AS2T:%d AS3T:%d HS:%d HS2T:%d HS3T:%d CL:%d",
- Q3_VERSION,
- g_tag.string,
- teamChar,
- level.averageNumAlienClients,
- level.averageNumHumanClients,
- map,
- level.time - level.startTime,
- G_TimeTilSuddenDeath( ),
- g_alienStage.integer,
- level.alienStage2Time - level.startTime,
- level.alienStage3Time - level.startTime,
- g_humanStage.integer,
- level.humanStage2Time - level.startTime,
- level.humanStage3Time - level.startTime,
- level.numConnectedClients );
-
- dataLength = strlen( data );
-
- for( i = 0; i < level.numConnectedClients; i++ )
- {
- int ping;
-
- cl = &level.clients[ level.sortedClients[ i ] ];
-
- // Ignore invisible players
- if ( cl->sess.invisible == qtrue )
- continue;
-
- if( cl->pers.connected == CON_CONNECTING )
- ping = -1;
- else
- ping = cl->ps.ping < 999 ? cl->ps.ping : 999;
-
- switch( cl->ps.stats[ STAT_PTEAM ] )
- {
- case PTE_ALIENS: teamChar = 'A'; break;
- case PTE_HUMANS: teamChar = 'H'; break;
- case PTE_NONE: teamChar = 'S'; break;
- default: return;
- }
-
- Com_sprintf( entry, MAX_STRING_CHARS,
- " \"%s\" %c %d %d %d",
- cl->pers.netname,
- teamChar,
- cl->ps.persistant[ PERS_SCORE ],
- ping,
- ( level.time - cl->pers.enterTime ) / 60000 );
-
- entryLength = strlen( entry );
-
- if( dataLength + entryLength >= BIG_INFO_STRING )
- break;
-
- strcpy( data + dataLength, entry );
- dataLength += entryLength;
- }
-
- trap_SendGameStat( data );
+ G_DecolorString( string, decolored, sizeof( decolored ) );
+ trap_FS_Write( decolored, strlen( decolored ), level.logFile );
}
/*
@@ -2226,6 +1784,8 @@ void LogExit( const char *string )
gclient_t *cl;
gentity_t *ent;
+ level.exited = qtrue;
+
G_LogPrintf( "Exit: %s\n", string );
level.intermissionQueued = level.time;
@@ -2245,7 +1805,7 @@ void LogExit( const char *string )
cl = &level.clients[ level.sortedClients[ i ] ];
- if( cl->ps.stats[ STAT_PTEAM ] == PTE_NONE )
+ if( cl->ps.stats[ STAT_TEAM ] == TEAM_NONE )
continue;
if( cl->pers.connected == CON_CONNECTING )
@@ -2270,8 +1830,6 @@ void LogExit( const char *string )
ent->use( ent, ent, ent );
}
}
-
- G_SendGameStat( level.lastWin );
}
@@ -2287,20 +1845,13 @@ wait 10 seconds before going on.
*/
void CheckIntermissionExit( void )
{
- int ready, notReady, numPlayers;
+ int ready, notReady;
int i;
gclient_t *cl;
- int readyMask;
+ clientList_t readyMasks;
//if no clients are connected, just exit
- if( !level.numConnectedClients )
- {
- ExitLevel( );
- return;
- }
-
- // map vote started
- if( level.mapRotationVoteTime )
+ if( level.numConnectedClients == 0 )
{
ExitLevel( );
return;
@@ -2309,30 +1860,28 @@ void CheckIntermissionExit( void )
// see which players are ready
ready = 0;
notReady = 0;
- readyMask = 0;
- numPlayers = 0;
+ Com_Memset( &readyMasks, 0, sizeof( readyMasks ) );
for( i = 0; i < g_maxclients.integer; i++ )
{
cl = level.clients + i;
+
if( cl->pers.connected != CON_CONNECTED )
continue;
- if( cl->ps.stats[ STAT_PTEAM ] == PTE_NONE )
+ if( cl->ps.stats[ STAT_TEAM ] == TEAM_NONE )
continue;
if( cl->readyToExit )
{
ready++;
- if( i < 16 )
- readyMask |= 1 << i;
+
+ Com_ClientListAdd( &readyMasks, i );
}
else
notReady++;
-
- numPlayers++;
}
- trap_SetConfigstring( CS_CLIENTS_READY, va( "%d", readyMask ) );
+ trap_SetConfigstring( CS_CLIENTS_READY, Com_ClientListString( &readyMasks ) );
// never exit in less than five seconds
if( level.time < level.intermissiontime + 5000 )
@@ -2346,22 +1895,14 @@ void CheckIntermissionExit( void )
}
// if nobody wants to go, clear timer
- if( !ready && numPlayers )
+ if( ready == 0 && notReady > 0 )
{
level.readyToExit = qfalse;
return;
}
// if everyone wants to go, go now
- if( !notReady )
- {
- ExitLevel( );
- return;
- }
-
- // if only a percent is needed to ready, check for it
- if( g_readyPercent.integer && numPlayers &&
- ready * 100 / numPlayers >= g_readyPercent.integer )
+ if( notReady == 0 )
{
ExitLevel( );
return;
@@ -2434,11 +1975,10 @@ void CheckExitRules( void )
{
if( level.time - level.startTime >= g_timelimit.integer * 60000 )
{
- level.lastWin = PTE_NONE;
+ level.lastWin = TEAM_NONE;
trap_SendServerCommand( -1, "print \"Timelimit hit\n\"" );
trap_SetConfigstring( CS_WINNER, "Stalemate" );
LogExit( "Timelimit hit." );
- G_admin_maplog_result( "t" );
return;
}
else if( level.time - level.startTime >= ( g_timelimit.integer - 5 ) * 60000 &&
@@ -2456,295 +1996,177 @@ void CheckExitRules( void )
}
if( level.uncondHumanWin ||
- ( ( level.time > level.startTime + 1000 ) &&
+ ( !level.uncondAlienWin &&
+ ( level.time > level.startTime + 1000 ) &&
( level.numAlienSpawns == 0 ) &&
- ( level.numLiveAlienClients == 0 ) ) )
+ ( level.numAlienClientsAlive == 0 ) ) )
{
//humans win
- level.lastWin = PTE_HUMANS;
+ level.lastWin = TEAM_HUMANS;
trap_SendServerCommand( -1, "print \"Humans win\n\"");
trap_SetConfigstring( CS_WINNER, "Humans Win" );
LogExit( "Humans win." );
- G_admin_maplog_result( "h" );
}
else if( level.uncondAlienWin ||
( ( level.time > level.startTime + 1000 ) &&
( level.numHumanSpawns == 0 ) &&
- ( level.numLiveHumanClients == 0 ) ) )
+ ( level.numHumanClientsAlive == 0 ) ) )
{
//aliens win
- level.lastWin = PTE_ALIENS;
+ level.lastWin = TEAM_ALIENS;
trap_SendServerCommand( -1, "print \"Aliens win\n\"");
trap_SetConfigstring( CS_WINNER, "Aliens Win" );
LogExit( "Aliens win." );
- G_admin_maplog_result( "a" );
}
}
-
-
-/*
-========================================================================
-
-FUNCTIONS CALLED EVERY FRAME
-
-========================================================================
-*/
-
-
/*
==================
-CheckVote
+G_Vote
==================
*/
-void CheckVote( void )
+void G_Vote( gentity_t *ent, team_t team, qboolean voting )
{
- int votePassThreshold=level.votePassThreshold;
- int voteYesPercent;
-
- if( level.voteExecuteTime && level.voteExecuteTime < level.time )
- {
- level.voteExecuteTime = 0;
-
- if( !Q_stricmp( level.voteString, "map_restart" ) )
- {
- G_admin_maplog_result( "r" );
- }
- else if( !Q_stricmpn( level.voteString, "map", 3 ) )
- {
- G_admin_maplog_result( "m" );
- }
-
-
- if( !Q_stricmp( level.voteString, "suddendeath" ) )
- {
- level.suddenDeathBeginTime = level.time + ( 1000 * g_suddenDeathVoteDelay.integer ) - level.startTime;
-
- level.voteString[0] = '\0';
-
- if( g_suddenDeathVoteDelay.integer )
- trap_SendServerCommand( -1, va("cp \"Sudden Death will begin in %d seconds\n\"", g_suddenDeathVoteDelay.integer ) );
- }
-
- if( level.voteString[0] )
- trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) );
+ if( !level.voteTime[ team ] )
+ return;
- if( !Q_stricmp( level.voteString, "map_restart" ) ||
- !Q_stricmpn( level.voteString, "map", 3 ) )
- {
- level.restarted = qtrue;
- }
- }
+ if( voting && ent->client->pers.voted & ( 1 << team ) )
+ return;
- if( !level.voteTime )
+ if( !voting && !( ent->client->pers.voted & ( 1 << team ) ) )
return;
- if( level.voteYes + level.voteNo > 0 )
- voteYesPercent = (int)( 100 * ( level.voteYes ) / ( level.voteYes + level.voteNo ) );
- else
- voteYesPercent = 0;
-
- if( ( level.time - level.voteTime >= VOTE_TIME ) ||
- ( level.voteYes + level.voteNo == level.numConnectedClients ) )
+ ent->client->pers.voted |= 1 << team;
+
+ if( ent->client->pers.vote & ( 1 << team ) )
{
- if( voteYesPercent> votePassThreshold || level.voteNo == 0 )
- {
- // execute the command, then remove the vote
- trap_SendServerCommand( -1, va("print \"Vote passed (%d - %d)\n\"",
- level.voteYes, level.voteNo ) );
- G_LogPrintf( "Vote: Vote passed (%d-%d)\n", level.voteYes, level.voteNo );
- level.voteExecuteTime = level.time + 3000;
- }
+ if( voting )
+ level.voteYes[ team ]++;
else
- {
- // same behavior as a timeout
- trap_SendServerCommand( -1, va("print \"Vote failed (%d - %d)\n\"",
- level.voteYes, level.voteNo ) );
- G_LogPrintf( "Vote: Vote failed (%d - %d)\n", level.voteYes, level.voteNo );
- }
+ level.voteYes[ team ]--;
+
+ trap_SetConfigstring( CS_VOTE_YES + team,
+ va( "%d", level.voteYes[ team ] ) );
}
else
{
- if( level.voteYes > (int)( (double) level.numConnectedClients *
- ( (double) votePassThreshold/100.0 ) ) )
- {
- // execute the command, then remove the vote
- trap_SendServerCommand( -1, va("print \"Vote passed (%d - %d)\n\"",
- level.voteYes, level.voteNo ) );
- G_LogPrintf( "Vote: Vote passed (%d - %d)\n", level.voteYes, level.voteNo );
- level.voteExecuteTime = level.time + 3000;
- }
- else if( level.voteNo > (int)( (double) level.numConnectedClients *
- ( (double) ( 100.0-votePassThreshold )/ 100.0 ) ) )
- {
- // same behavior as a timeout
- trap_SendServerCommand( -1, va("print \"Vote failed (%d - %d)\n\"",
- level.voteYes, level.voteNo ) );
- G_LogPrintf("Vote failed\n");
- }
+ if( voting )
+ level.voteNo[ team ]++;
else
- {
- // still waiting for a majority
- return;
- }
- }
+ level.voteNo[ team ]--;
- level.voteTime = 0;
- trap_SetConfigstring( CS_VOTE_TIME, "" );
- trap_SetConfigstring( CS_VOTE_STRING, "" );
+ trap_SetConfigstring( CS_VOTE_NO + team,
+ va( "%d", level.voteNo[ team ] ) );
+ }
}
/*
-==================
-CheckTeamVote
-==================
+========================================================================
+
+FUNCTIONS CALLED EVERY FRAME
+
+========================================================================
*/
-void CheckTeamVote( int team )
-{
- int cs_offset;
- if ( team == PTE_HUMANS )
- cs_offset = 0;
- else if ( team == PTE_ALIENS )
- cs_offset = 1;
- else
- return;
- if( !level.teamVoteTime[ cs_offset ] )
- return;
+void G_ExecuteVote( team_t team )
+{
+ level.voteExecuteTime[ team ] = 0;
- if( level.time - level.teamVoteTime[ cs_offset ] >= VOTE_TIME )
+ if( !Q_stricmpn( level.voteString[ team ], "map_restart", 11 ) )
{
- if( level.teamVoteYes[ cs_offset ] > level.teamVoteNo[ cs_offset ] && level.teamVoteYes[ cs_offset ] >= 2 )
- {
- // execute the command, then remove the vote
- trap_SendServerCommand( -1, va("print \"Team vote passed (%d - %d)\n\"", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] ) );
- trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.teamVoteString[ cs_offset ] ) );
- }
- else
- {
- trap_SendServerCommand( -1, va("print \"Team vote failed (%d - %d)\n\"", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] ) );
- G_LogPrintf( "Teamvote: Team vote failed (%d - %d)\n", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] );
- }
+ char map[ MAX_QPATH ];
+ trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) );
+ G_MapConfigs( map );
}
- else
+ else if( !Q_stricmpn( level.voteString[ team ], "map", 3 ) )
{
- if( level.teamVoteYes[ cs_offset ] > level.numteamVotingClients[ cs_offset ] / 2 )
- {
- // execute the command, then remove the vote
- trap_SendServerCommand( -1, va("print \"Team vote passed (%d - %d)\n\"", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] ) );
- G_LogPrintf( "Teamvote: Team vote passed (%d - %d)\n", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] );
- //
- trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.teamVoteString[ cs_offset ] ) );
- }
- else if( level.teamVoteNo[ cs_offset ] >= level.numteamVotingClients[ cs_offset ] / 2 )
- {
- // same behavior as a timeout
- trap_SendServerCommand( -1, va("print \"Team vote failed (%d - %d)\n\"", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] ) );
- G_LogPrintf( "Teamvote: Team vote failed (%d - %d)\n", level.teamVoteYes[ cs_offset ], level.teamVoteNo[ cs_offset ] );
- }
- else
- {
- // still waiting for a majority
- return;
- }
+ char map[ MAX_QPATH ];
+ char *p;
+ Q_strncpyz( map, strchr( level.voteString[ team ], '"' ) + 1, sizeof( map ) );
+ if( ( p = strchr( map, '"' ) ) )
+ *p = '\0';
+ G_MapConfigs( map );
}
- level.teamVoteTime[ cs_offset ] = 0;
- trap_SetConfigstring( CS_TEAMVOTE_TIME + cs_offset, "" );
- trap_SetConfigstring( CS_TEAMVOTE_STRING + cs_offset, "" );
+ trap_SendConsoleCommand( EXEC_APPEND, va( "%s%s\n",
+ ( !Q_stricmp( level.voteString[ team ], "map" ) && g_cheats.integer ? "dev" : "" ),
+ level.voteString[ team ] ) );
+
+ if( !Q_stricmpn( level.voteString[ team ], "map", 3 ) )
+ level.restarted = qtrue;
}
/*
==================
-CheckMsgTimer
+G_CheckVote
==================
*/
-void CheckMsgTimer( void )
+void G_CheckVote( team_t team )
{
- static int LastTime = 0;
+ float votePassThreshold = (float)level.voteThreshold[ team ] / 100.0f;
+ qboolean pass = qfalse;
+ const char *msg;
+ int i;
- if( level.time - LastTime < 1000 )
- return;
+ if( level.voteExecuteTime[ team ] &&
+ level.voteExecuteTime[ team ] < level.time )
+ {
+ G_ExecuteVote( team );
+ }
- LastTime = level.time;
+ if( !level.voteTime[ team ] )
+ return;
- if( level.mapRotationVoteTime )
+ if( ( level.time - level.voteTime[ team ] >= VOTE_TIME ) ||
+ ( level.voteYes[ team ] + level.voteNo[ team ] == level.numVotingClients[ team ] ) )
{
- G_IntermissionMapVoteMessageAll( );
- return;
+ pass = ( level.voteYes[ team ] &&
+ (float)level.voteYes[ team ] / ( (float)level.voteYes[ team ] + (float)level.voteNo[ team ] ) > votePassThreshold );
}
-
- if( g_welcomeMsgTime.integer && g_welcomeMsg.string[ 0 ] )
+ else
{
- char buffer[ MAX_STRING_CHARS ];
- int wt;
- int i;
-
- buffer[ 0 ] = '\0';
- wt = g_welcomeMsgTime.integer * 1000;
- for( i = 0; i < level.maxclients; i++ )
+ if( (float)level.voteYes[ team ] >
+ (float)level.numVotingClients[ team ] * votePassThreshold )
{
- if( level.clients[ i ].pers.connected != CON_CONNECTED )
- continue;
-
- if( level.time - level.clients[ i ].pers.enterTime < wt )
- {
- if( buffer[ 0 ] == '\0' )
- {
- Q_strncpyz( buffer, g_welcomeMsg.string, sizeof( buffer ) );
- G_ParseEscapedString( buffer );
- }
- trap_SendServerCommand( i, va( "cp \"%s\"", buffer ) );
- }
+ pass = qtrue;
+ }
+ else if( (float)level.voteNo[ team ] <=
+ (float)level.numVotingClients[ team ] * ( 1.0f - votePassThreshold ) )
+ {
+ return;
}
}
- if( !g_msgTime.integer )
- return;
+ if( pass )
+ level.voteExecuteTime[ team ] = level.time + level.voteDelay[ team ];
- if( level.time - level.lastMsgTime < abs( g_msgTime.integer ) * 60000 )
- return;
+ G_LogPrintf( "EndVote: %s %s %d %d %d\n",
+ team == TEAM_NONE ? "global" : BG_TeamName( team ),
+ pass ? "pass" : "fail",
+ level.voteYes[ team ], level.voteNo[ team ], level.numVotingClients[ team ] );
- // negative settings only print once per map
- if( ( level.lastMsgTime ) && g_msgTime.integer < 0 )
- return;
+ msg = va( "print \"%sote %sed (%d - %d)\n\"",
+ team == TEAM_NONE ? "V" : "Team v", pass ? "pass" : "fail",
+ level.voteYes[ team ], level.voteNo[ team ] );
- level.lastMsgTime = level.time;
-
- if( g_msg.string[0] )
- {
- char buffer[ MAX_STRING_CHARS ];
-
- Q_strncpyz( buffer, g_msg.string, sizeof( buffer ) );
- G_ParseEscapedString( buffer );
- trap_SendServerCommand( -1, va( "cp \"%s\"", buffer ) );
- trap_SendServerCommand( -1, va( "print \"%s\n\"", buffer ) );
- }
-}
-
-/*
-==================
-CheckCountdown
-==================
-*/
-void CheckCountdown( void )
-{
- static int lastmsg = 0;
- int timeleft = g_warmup.integer - ( level.time - level.startTime ) / 1000;
+ if( team == TEAM_NONE )
+ trap_SendServerCommand( -1, msg );
+ else
+ G_TeamCommand( team, msg );
- if( !g_doWarmup.integer || timeleft < 0 )
- return;
+ level.voteTime[ team ] = 0;
+ level.voteYes[ team ] = 0;
+ level.voteNo[ team ] = 0;
- if( level.time - lastmsg < 1000 )
- return;
+ for( i = 0; i < level.maxclients; i++ )
+ level.clients[ i ].pers.voted &= ~( 1 << team );
- lastmsg = level.time;
- if( timeleft > 0 )
- trap_SendServerCommand( -1, va( "cp \"^1Warmup Time:^7\n^%i----- ^7%i ^%i-----\"", timeleft % 7, timeleft, timeleft % 7 ) );
- else if( timeleft == 0 )
- trap_SendServerCommand( -1, "cp \"^2----- GO! -----^7\"" );
+ trap_SetConfigstring( CS_VOTE_TIME + team, "" );
+ trap_SetConfigstring( CS_VOTE_STRING + team, "" );
+ trap_SetConfigstring( CS_VOTE_YES + team, "0" );
+ trap_SetConfigstring( CS_VOTE_NO + team, "0" );
}
@@ -2758,6 +2180,7 @@ void CheckCvars( void )
static int lastPasswordModCount = -1;
static int lastMarkDeconModCount = -1;
static int lastSDTimeModCount = -1;
+ static int lastNumZones = 0;
if( g_password.modificationCount != lastPasswordModCount )
{
@@ -2773,29 +2196,36 @@ void CheckCvars( void )
// the server setting is changed
if( g_markDeconstruct.modificationCount != lastMarkDeconModCount )
{
- int i;
- gentity_t *ent;
-
lastMarkDeconModCount = g_markDeconstruct.modificationCount;
-
- for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
- {
- if( !ent->inuse )
- continue;
-
- if( ent->s.eType != ET_BUILDABLE )
- continue;
-
- ent->deconstruct = qfalse;
- }
+ G_ClearDeconMarks( );
}
+ // If we change g_suddenDeathTime during a map, we need to update
+ // when sd will begin
if( g_suddenDeathTime.modificationCount != lastSDTimeModCount )
{
lastSDTimeModCount = g_suddenDeathTime.modificationCount;
level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
}
+ // If the number of zones changes, we need a new array
+ if( g_humanRepeaterMaxZones.integer != lastNumZones )
+ {
+ buildPointZone_t *newZones;
+ size_t newsize = g_humanRepeaterMaxZones.integer * sizeof( buildPointZone_t );
+ size_t oldsize = lastNumZones * sizeof( buildPointZone_t );
+
+ newZones = BG_Alloc( newsize );
+ if( level.buildPointZones )
+ {
+ Com_Memcpy( newZones, level.buildPointZones, MIN( oldsize, newsize ) );
+ BG_Free( level.buildPointZones );
+ }
+
+ level.buildPointZones = newZones;
+ lastNumZones = g_humanRepeaterMaxZones.integer;
+ }
+
level.frameMsec = trap_Milliseconds( );
}
@@ -2855,47 +2285,62 @@ Advances the non-player objects in the world
*/
void G_RunFrame( int levelTime )
{
- int i;
- gentity_t *ent;
- int msec;
- int start, end;
+ int i;
+ gentity_t *ent;
+ int msec;
+ static int ptime3000 = 0;
// if we are waiting for the level to restart, do nothing
if( level.restarted )
return;
-
- if( level.paused )
+
+ if( level.pausedTime )
{
- if( ( levelTime % 6000 ) == 0)
- trap_SendServerCommand( -1, "cp \"^3Game is paused.\"" );
+ msec = levelTime - level.time - level.pausedTime;
+ level.pausedTime = levelTime - level.time;
+
+ ptime3000 += msec;
+ while( ptime3000 > 3000 )
+ {
+ ptime3000 -= 3000;
+ trap_SendServerCommand( -1, "cp \"The game has been paused. Please wait.\"" );
- level.startTime += levelTime - level.time;
- trap_SetConfigstring( CS_LEVEL_START_TIME, va( "%i", level.startTime ) );
+ if( level.pausedTime >= 110000 && level.pausedTime <= 119000 )
+ trap_SendServerCommand( -1, va( "print \"Server: Game will auto-unpause in %d seconds\n\"",
+ (int) ( (float) ( 120000 - level.pausedTime ) / 1000.0f ) ) );
+ }
- if( levelTime - level.pauseTime > 3 * 60000 )
+ // Prevents clients from getting lagged-out messages
+ for( i = 0; i < level.maxclients; i++ )
{
- trap_SendConsoleCommand( EXEC_APPEND, "!unpause" );
+ if( level.clients[ i ].pers.connected == CON_CONNECTED )
+ level.clients[ i ].ps.commandTime = levelTime;
}
+
+ if( level.pausedTime > 120000 )
+ {
+ trap_SendServerCommand( -1, "print \"Server: The game has been unpaused automatically (2 minute max)\n\"" );
+ trap_SendServerCommand( -1, "cp \"The game has been unpaused!\"" );
+ level.pausedTime = 0;
+ }
+
+ return;
}
- CheckMsgTimer( );
- CheckCountdown( );
-
level.framenum++;
level.previousTime = level.time;
level.time = levelTime;
msec = level.time - level.previousTime;
- //TA: seed the rng
- srand( level.framenum );
-
// get any cvar changes
G_UpdateCvars( );
+ CheckCvars( );
+ // now we are done spawning
+ level.spawning = qfalse;
//
// go through all allocated objects
//
- start = trap_Milliseconds( );
ent = &g_entities[ 0 ];
for( i = 0; i < level.num_entities; i++, ent++ )
@@ -2935,7 +2380,7 @@ void G_RunFrame( int levelTime )
if( ent->freeAfterEvent )
continue;
- //TA: calculate the acceleration of this entity
+ // calculate the acceleration of this entity
if( ent->evaluateAcceleration )
G_EvaluateAcceleration( ent, msec );
@@ -2948,6 +2393,12 @@ void G_RunFrame( int levelTime )
continue;
}
+ if ( ent->s.eType == ET_WEAPON_DROP )
+ {
+ G_RunWeaponDrop( ent );
+ continue;
+ }
+
if( ent->s.eType == ET_BUILDABLE )
{
G_BuildableThink( ent, msec );
@@ -2974,9 +2425,6 @@ void G_RunFrame( int levelTime )
G_RunThink( ent );
}
- end = trap_Milliseconds();
-
- start = trap_Milliseconds();
// perform final fixups on the players
ent = &g_entities[ 0 ];
@@ -2987,19 +2435,20 @@ void G_RunFrame( int levelTime )
ClientEndFrame( ent );
}
- // save position information for all active clients
+ // save position information for all active clients
G_UnlaggedStore( );
- end = trap_Milliseconds();
-
- //TA:
G_CountSpawns( );
- G_CalculateBuildPoints( );
- G_CalculateStages( );
- G_SpawnClients( PTE_ALIENS );
- G_SpawnClients( PTE_HUMANS );
- G_CalculateAvgPlayers( );
- G_UpdateZaps( msec );
+ if( !g_doWarmup.integer || level.warmupTime <= level.time )
+ {
+ G_CalculateBuildPoints( );
+ G_CalculateStages( );
+ G_SpawnClients( TEAM_ALIENS );
+ G_SpawnClients( TEAM_HUMANS );
+ G_CalculateAvgPlayers( );
+ G_UpdateZaps( msec );
+ }
+ G_UpdateBuildableRangeMarkers( );
// see if it is time to end the level
CheckExitRules( );
@@ -3008,23 +2457,8 @@ void G_RunFrame( int levelTime )
CheckTeamStatus( );
// cancel vote if timed out
- CheckVote( );
-
- // check team votes
- CheckTeamVote( PTE_HUMANS );
- CheckTeamVote( PTE_ALIENS );
+ for( i = 0; i < NUM_TEAMS; i++ )
+ G_CheckVote( i );
- G_admin_schachtmeisterFrame();
-
- // for tracking changes
- CheckCvars( );
-
- if( g_listEntity.integer )
- {
- for( i = 0; i < MAX_GENTITIES; i++ )
- G_Printf( "%4i: %s\n", i, g_entities[ i ].classname );
-
- trap_Cvar_Set( "g_listEntity", "0" );
- }
+ level.frameMsec = trap_Milliseconds();
}
-