From 9e9289b46d1efad930f09d691ad62fab7f84e8fe Mon Sep 17 00:00:00 2001
From: Petr Pudlak <petr.mvd@gmail.com>
Date: Sun, 12 Oct 2014 16:39:46 +0200
Subject: Add support for Weak Sudden Death

After it strikes, it's not possible to build near the Reactor/Overmind
and it's not possible to build refineries/creep colonies. This still
allows teams to build forward within the BP limit, but not strengthen
their main bases any more.
---
 src/game/bg_public.h   |  2 ++
 src/game/g_buildable.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/game/g_cmds.c      |  5 +++++
 src/game/g_local.h     |  6 ++++++
 src/game/g_main.c      | 35 +++++++++++++++++++++++++++++++++++
 5 files changed, 96 insertions(+)

(limited to 'src/game')

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" );
@@ -1166,6 +1169,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 )
   {
-- 
cgit 


From c8e426354b1b42a6870e7e44c8e92a7fc0531ede Mon Sep 17 00:00:00 2001
From: Petr Pudlak <petr.mvd@gmail.com>
Date: Fri, 17 Oct 2014 21:01:54 +0200
Subject: Add a command for starting Weak Sudden Death

---
 src/game/g_svcmds.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

(limited to 'src/game')

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 }
 };
 
-- 
cgit