summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--misc/server.cfg2
-rw-r--r--src/cgame/cg_servercmds.c18
-rw-r--r--src/game/bg_public.h2
-rw-r--r--src/game/g_buildable.c48
-rw-r--r--src/game/g_cmds.c5
-rw-r--r--src/game/g_local.h6
-rw-r--r--src/game/g_main.c35
-rw-r--r--src/game/g_svcmds.c14
8 files changed, 130 insertions, 0 deletions
diff --git a/misc/server.cfg b/misc/server.cfg
index 184e9ea..3897452 100644
--- a/misc/server.cfg
+++ b/misc/server.cfg
@@ -18,6 +18,8 @@ set sv_allowdownload 0
//greater than 24 is not recommended from a gameplay point of view
set sv_maxclients 24
+//after 25 minutes, refineries/collonies are disallowed
+set g_weakSuddenDeathTime 25
//after 50 minutes, all build points are removed
set g_suddenDeathTime 50
//after 60 minutes, the game will end as a draw
diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c
index a5de53d..084e3f1 100644
--- a/src/cgame/cg_servercmds.c
+++ b/src/cgame/cg_servercmds.c
@@ -648,6 +648,24 @@ void CG_Menu( int menu, int arg )
+ case MN_B_WSD_INBASE:
+ longMsg = "Neither team has prevailed after a certain time and the "
+ "game has entered Weak Sudden Death. During Sudden Death "
+ "building creep colonies or refineries is not allowed, "
+ "and neither is allowed building near the Overmind or the Reactor.";
+ shortMsg = "^5Cannot build near the Reactor/Overmind during Weak Sudden Death";
+ type = DT_BUILD;
+ break;
+
+ case MN_B_WSD_REFSCOLS:
+ longMsg = "Neither team has prevailed after a certain time and the "
+ "game has entered Weak Sudden Death. During Weak Sudden Death "
+ "building creep colonies or refineries is not allowed, "
+ "and neither is allowed building near the Overmind or the Reactor.";
+ shortMsg = "^5Cannot build refineries/colonies during Weak Sudden Death";
+ type = DT_BUILD;
+ break;
+
case MN_B_SUDDENDEATH:
longMsg = "Neither team has prevailed after a certain time and the "
"game has entered Sudden Death. During Sudden Death "
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index f8a2f9d..b7df340 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -606,6 +606,8 @@ typedef enum
MN_B_NORMAL,
MN_B_CANNOT,
MN_B_LASTSPAWN,
+ MN_B_WSD_INBASE,
+ MN_B_WSD_REFSCOLS,
MN_B_SUDDENDEATH,
MN_B_REVOKED,
MN_B_SURRENDER,
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 65e7077..841038f 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -3894,6 +3894,46 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
return IBE_NONE;
}
+ if( G_TimeTilWeakSuddenDeath( ) <= 0 )
+ {
+ // No refineries/colonies after WSD
+ if( ( buildable == BA_H_REFINERY ) || ( buildable == BA_A_CREEPCOLONY ) )
+ return IBE_WSD_REFSCOLS;
+
+ // No building near OM/RC after WSD, unless it's a replacement
+ if( buildable != core )
+ {
+ vec3_t temp_v;
+
+ // Iterate through entities
+ distance = 0;
+ for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ {
+ if( ent->s.eType != ET_BUILDABLE )
+ continue;
+
+ // If entity is a power item calculate the distance to it
+ if( ent->s.modelindex == core )
+ {
+ if( ent->spawned && ent->health > 0 )
+ {
+ VectorSubtract( origin, ent->s.origin, temp_v );
+ distance = VectorLength( temp_v );
+ }
+ break;
+ }
+ }
+
+ if( distance > 0 ) // RC/OM found and it's alive
+ {
+ if( ( team == TEAM_ALIENS ) && ( distance <= CREEP_BASESIZE ) )
+ return IBE_WSD_INBASE;
+ if( ( team == TEAM_HUMANS ) && ( distance <= REACTOR_BASESIZE ) )
+ return IBE_WSD_INBASE;
+ }
+ }
+ }
+
// Simple non-marking case
if( !g_markDeconstruct.integer )
{
@@ -4776,6 +4816,14 @@ qboolean G_BuildIfValid( gentity_t *ent, buildable_t buildable )
G_TriggerMenu( ent->client->ps.clientNum, MN_B_GTHRBLOCKED );
return qfalse;
+ case IBE_WSD_INBASE:
+ G_TriggerMenu( ent->client->ps.clientNum, MN_B_WSD_INBASE );
+ return qfalse;
+
+ case IBE_WSD_REFSCOLS:
+ G_TriggerMenu( ent->client->ps.clientNum, MN_B_WSD_REFSCOLS );
+ return qfalse;
+
default:
break;
}
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index fa6b6c9..39a87b9 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -2742,6 +2742,7 @@ void Cmd_Build_f( gentity_t *ent )
case IBE_NOPOWERHERE:
case IBE_BLOCKEDBYENEMY:
case IBE_GTHRBLOCKED:
+ case IBE_WSD_INBASE:
err = MN_NONE;
break;
@@ -2778,6 +2779,10 @@ void Cmd_Build_f( gentity_t *ent )
err = MN_B_LASTSPAWN;
break;
+ case IBE_WSD_REFSCOLS:
+ err = MN_B_WSD_REFSCOLS;
+ break;
+
default:
err = -1; // stop uninitialised warning
break;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 522bdb7..4e6cec1 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -666,6 +666,8 @@ typedef struct
team_t lastWin;
+ int weakSuddenDeathBeginTime;
+ timeWarning_t weakSuddenDeathWarning;
int suddenDeathBeginTime;
timeWarning_t suddenDeathWarning;
timeWarning_t timelimitWarning;
@@ -812,6 +814,9 @@ typedef enum
IBE_LASTSPAWN,
IBE_BLOCKEDBYENEMY,
IBE_GTHRBLOCKED,
+ IBE_WSD_INBASE,
+ IBE_WSD_REFSCOLS,
+
IBE_MAXERRORS
} itemBuildError_t;
@@ -1159,6 +1164,7 @@ extern vmCvar_t g_minNameChangePeriod;
extern vmCvar_t g_maxNameChanges;
extern vmCvar_t g_timelimit;
extern vmCvar_t g_suddenDeathTime;
+extern vmCvar_t g_weakSuddenDeathTime;
extern vmCvar_t g_armageddonTimeStep;
extern vmCvar_t g_armageddonInitialTimeStep;
extern vmCvar_t g_armageddonDefensiveKillPercent;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 965fdc0..481e1d1 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -51,6 +51,7 @@ gclient_t g_clients[ MAX_CLIENTS ];
vmCvar_t g_timelimit;
vmCvar_t g_suddenDeathTime;
+vmCvar_t g_weakSuddenDeathTime;
vmCvar_t g_armageddonTimeStep;
vmCvar_t g_armageddonInitialTimeStep;
vmCvar_t g_armageddonDefensiveKillPercent;
@@ -225,6 +226,7 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_humanMedkitRange, "g_humanMedkitRange", "200", CVAR_ARCHIVE, 0, qfalse },
{ &g_humanMedkitWidth, "g_humanMedkitWidth", "20", CVAR_ARCHIVE, 0, qfalse },
{ &g_suddenDeathTime, "g_suddenDeathTime", "40", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
+ { &g_weakSuddenDeathTime, "g_weakSuddenDeathTime", "25", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_armageddonTimeStep, "g_armageddonTimeStep", "5", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_armageddonInitialTimeStep, "g_armageddonInitialTimeStep", "10", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_armageddonDefensiveKillPercent, "g_armageddonDefensiveKillPercent", "10", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
@@ -726,6 +728,7 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
if( g_ForceRandomTeams.integer == 2)
trap_Cvar_Set( "g_ForceRandomTeams", 0 );
level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
+ level.weakSuddenDeathBeginTime = g_weakSuddenDeathTime.integer * 60000;
level.nextArmageddonKillTime = (g_suddenDeathTime.integer+g_armageddonInitialTimeStep.integer) * 60000;
level.nextCommandTime = g_TimerPeriod.integer;
G_Printf( "-----------------------------------\n" );
@@ -1168,6 +1171,20 @@ void G_CountSpawns( void )
/*
============
+G_TimeTilWeakSuddenDeath
+============
+*/
+#define WEAKSUDDENDEATHWARNING 60000
+int G_TimeTilWeakSuddenDeath( void )
+{
+ if( ( !g_weakSuddenDeathTime.integer && level.weakSuddenDeathBeginTime == 0 ) ||
+ ( level.weakSuddenDeathBeginTime < 0 ) )
+ return WEAKSUDDENDEATHWARNING + 1; // Always some time away
+ return ( ( level.weakSuddenDeathBeginTime ) - ( level.time - level.startTime ) );
+}
+
+/*
+============
G_TimeTilSuddenDeath
============
*/
@@ -1259,6 +1276,24 @@ void G_CalculateBuildPoints( void )
g_humanBuildQueueTime.integer );
}
+ // Weak Sudden Death checks
+ if( G_TimeTilWeakSuddenDeath( ) <= 0 && level.weakSuddenDeathWarning < TW_PASSED )
+ {
+ G_LogPrintf( "^5Beginning Weak Sudden Death\n" );
+ trap_SendServerCommand( -1, "cp \"^5Weak Sudden Death!\"" );
+ trap_SendServerCommand( -1, "print \"^5Beginning Weak Sudden Death.\n\"" );
+ level.weakSuddenDeathWarning = TW_PASSED;
+ }
+ else if( G_TimeTilWeakSuddenDeath( ) <= WEAKSUDDENDEATHWARNING &&
+ level.weakSuddenDeathWarning < TW_IMMINENT )
+ {
+ trap_SendServerCommand( -1, va( "cp \"Weak Sudden Death in %d seconds!\"",
+ (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) );
+ trap_SendServerCommand( -1, va( "print \"Weak Sudden Death will begin in %d seconds.\n\"",
+ (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) );
+ level.weakSuddenDeathWarning = TW_IMMINENT;
+ }
+
// Sudden Death checks
if( G_TimeTilSuddenDeath( ) <= 0 && level.suddenDeathWarning < TW_PASSED )
{
diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c
index 915709d..775b4ed 100644
--- a/src/game/g_svcmds.c
+++ b/src/game/g_svcmds.c
@@ -541,6 +541,19 @@ static void Svcmd_MapLogWrapper( void )
Cmd_MapLog_f( NULL );
}
+static void Svcmd_WeakSuddenDeath_f( void )
+{
+ char secs[ 5 ];
+ int offset;
+ trap_Argv( 1, secs, sizeof( secs ) );
+ offset = atoi( secs );
+
+ level.weakSuddenDeathBeginTime = level.time - level.startTime + offset * 1000;
+ trap_SendServerCommand( -1,
+ va( "cp \"Weak Sudden Death will begin in %d second%s\"",
+ offset, offset == 1 ? "" : "s" ) );
+}
+
static void Svcmd_SuddenDeath_f( void )
{
char secs[ 5 ];
@@ -646,6 +659,7 @@ struct svcmd
{ "say_team", qtrue, Svcmd_TeamMessage_f },
{ "status", qfalse, Svcmd_Status_f },
{ "stopMapRotation", qfalse, G_StopMapRotation },
+ { "weaksuddendeath", qfalse, Svcmd_WeakSuddenDeath_f },
{ "suddendeath", qfalse, Svcmd_SuddenDeath_f }
};