Maelstrom: When you're in co-op multiplayer mode, the game isn't over until the last life is lost. Until then, the other players can...

https://github.com/libsdl-org/Maelstrom/commit/2b56aa33fead121785b0aa154f2c164bc746c682

From 2b56aa33fead121785b0aa154f2c164bc746c682 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 25 Nov 2011 12:10:57 -0500
Subject: [PATCH] When you're in co-op multiplayer mode, the game isn't over
 until the last life is lost.  Until then, the other players can still play as
 ghosts.

---
 game/player.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++----
 game/player.h   |  3 ++-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/game/player.cpp b/game/player.cpp
index ee8e0259..4798e520 100644
--- a/game/player.cpp
+++ b/game/player.cpp
@@ -82,6 +82,7 @@ Player::NewGame(int lives)
 	Score = 0;
 	Frags = 0;
 	special = 0;
+	Ghost = 0;
 	NewShip();
 }
 void 
@@ -120,8 +121,14 @@ Player::NewWave(void)
 int 
 Player::NewShip(void)
 {
-	if ( Lives == 0 )
-		return(-1);
+	if ( Lives == 0 ) {
+		if (gGameInfo.IsMultiplayer() && !gGameInfo.IsDeathmatch()) {
+			// We can live on!
+			Ghost = 1;
+		} else {
+			return(-1);
+		}
+	}
 	controlState = 0;
 	solid = 1;
 	shootable = 1;
@@ -145,8 +152,11 @@ Player::NewShip(void)
 	Dead = 0;
 	Exploding = 0;
 	Set_TTL(-1);
-	if ( ! gGameInfo.IsDeathmatch() )
-		--Lives;
+	if ( ! gGameInfo.IsDeathmatch() ) {
+		if (Lives > 0) {
+			--Lives;
+		}
+	}
 
 	// In Kid Mode you automatically get air brakes and full shields
 	if ( gGameInfo.IsKidMode() ) {
@@ -245,6 +255,30 @@ Player::BeenTimedOut(void)
 		Dead = (DEAD_DELAY/2);
 	else
 		Dead = DEAD_DELAY;
+
+	// If we're the last life in a co-op multiplayer game, we're done
+	if (gGameInfo.IsMultiplayer() && !gGameInfo.IsDeathmatch() && !Lives) {
+		int i;
+		bool allGhosts = true;
+		OBJ_LOOP(i, MAX_PLAYERS) {
+			if (!gPlayers[i]->IsValid()) {
+				continue;
+			}
+			if ( i != Index && !gPlayers[i]->Ghost) {
+				allGhosts = false;
+				break;
+			}
+		}
+		if (allGhosts) {
+			OBJ_LOOP(i, MAX_PLAYERS) {
+				if (!gPlayers[i]->IsValid()) {
+					continue;
+				}
+				gPlayers[i]->Playing = 0;
+			}
+		}
+	}
+
 	return(0);
 }
 
@@ -611,7 +645,15 @@ Player::BlitSprite(void)
 	}
 
 	/* Draw our ship */
+	if (Ghost) {
+		SDL_SetTextureAlphaMod(myblit->sprite[phase], 0x80);
+	}
+
 	Object::BlitSprite();
+
+	if (Ghost) {
+		SDL_SetTextureAlphaMod(myblit->sprite[phase], 0xFF);
+	}
 }
 void 
 Player::HitSound(void)
diff --git a/game/player.h b/game/player.h
index 33095dfa..5960660a 100644
--- a/game/player.h
+++ b/game/player.h
@@ -51,7 +51,7 @@ class Player : public Object {
 		return(!Dead);
 	}
 	virtual int Kicking(void) {
-		return(Playing);
+		return(Playing && !Ghost);
 	}
 	virtual void NewGame(int lives);
 	virtual void NewWave(void);
@@ -159,6 +159,7 @@ class Player : public Object {
 	unsigned char special;
 	int Playing;
 	int Dead;
+	int Ghost;
 
 	Shot *shots[MAX_SHOTS];
 	int nextshot;