diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index f3fb1f6ae8d13b84c81d1517e857b1320e6cde6a..dbb0b0ff53d3c5b191f91c56887356fdd86ee545 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -822,6 +822,7 @@ void D_RegisterClientCommands(void)
 	COM_AddCommand("getallemeralds", Command_Getallemeralds_f);
 	COM_AddCommand("resetemeralds", Command_Resetemeralds_f);
 	COM_AddCommand("setrings", Command_Setrings_f);
+	COM_AddCommand("setspheres", Command_Setspheres_f);
 	COM_AddCommand("setlives", Command_Setlives_f);
 	COM_AddCommand("setcontinues", Command_Setcontinues_f);
 	COM_AddCommand("devmode", Command_Devmode_f);
diff --git a/src/d_player.h b/src/d_player.h
index 24c4f92521db281b14750bebf233abedb632d191..7bee5f337e60e305929143019f328176dde20ae4 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -462,6 +462,7 @@ typedef struct player_s
 	tic_t startedtime; // Time which you started this mare with.
 	tic_t finishedtime; // Time it took you to finish the mare (used for display)
 	INT16 finishedspheres; // The spheres you had left upon finishing the mare
+	INT16 finishedrings; // The rings/stars you had left upon finishing the mare
 	UINT32 marescore; // score for this nights stage
 	UINT32 lastmarescore; // score for the last mare
 	UINT8 lastmare; // previous mare
diff --git a/src/dehacked.c b/src/dehacked.c
index c4d0bc10468e3319984f40a8b24e67f729d1ccf3..fb0f958c3ffe0aeb2838db73dddb14f91b2e7b27 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6369,6 +6369,7 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_RING",
 	"MT_FLINGRING", // Lost ring
 	"MT_BLUESPHERE",  // Blue sphere for special stages
+	"MT_FLINGBLUESPHERE", // Lost blue sphere
 	"MT_BOMBSPHERE",
 	"MT_REDTEAMRING",  //Rings collectable by red team.
 	"MT_BLUETEAMRING", //Rings collectable by blue team.
@@ -6833,6 +6834,7 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_HOOPCENTER", // Center of a hoop
 	"MT_NIGHTSCORE",
 	"MT_NIGHTSCHIP", // NiGHTS Chip
+	"MT_FLINGNIGHTSCHIP", // Lost NiGHTS Chip
 	"MT_NIGHTSSTAR", // NiGHTS Star
 	"MT_NIGHTSSUPERLOOP",
 	"MT_NIGHTSDRILLREFILL",
diff --git a/src/info.c b/src/info.c
index 1489917b7768d598eb85e67f036c8e96763c981b..782ab638165d5d00cfc773c86967ed8d12dc1edb 100644
--- a/src/info.c
+++ b/src/info.c
@@ -5783,7 +5783,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
-		MT_NULL,        // reactiontime
+		MT_FLINGBLUESPHERE,        // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
 		0,              // painchance
@@ -5804,6 +5804,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_BLUESPHEREBONUS // raisestate
 	},
 
+	{           // MT_FLINGBLUESPHERE
+		-1,             // doomednum
+		S_BLUESPHERE,         // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		MT_FLINGBLUESPHERE,   // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		MT_BLUESPHERE,        // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_BLUESPHERESPARK, // deathstate
+		S_NULL,         // xdeathstate
+		sfx_s3k65,     // deathsound
+		38*FRACUNIT,    // speed
+		16*FRACUNIT,    // radius
+		24*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_SLIDEME|MF_SPECIAL, // flags
+		S_BLUESPHEREBONUS // raisestate
+	},
+
 	{           // MT_BOMBSPHERE
 		520,            // doomednum
 		S_BOMBSPHERE1,  // spawnstate
@@ -16320,7 +16347,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
-		8,              // reactiontime
+		MT_FLINGNIGHTSCHIP, // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
 		0,              // painchance
@@ -16341,6 +16368,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NIGHTSCHIPBONUS // raisestate
 	},
 
+	{           // MT_FLINGNIGHTSCHIP
+		-1,             // doomednum
+		S_NIGHTSCHIP,         // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		MT_FLINGNIGHTSCHIP,   // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		MT_NIGHTSCHIP,        // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_SPRK1,        // deathstate
+		S_NULL,         // xdeathstate
+		sfx_ncchip,     // deathsound
+		38*FRACUNIT,    // speed
+		16*FRACUNIT,    // radius
+		24*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_SLIDEME|MF_SPECIAL, // flags
+		S_NIGHTSCHIPBONUS // raisestate
+	},
+
 	{           // MT_NIGHTSSTAR
 		-1,             // doomednum
 		S_NIGHTSSTAR,   // spawnstate
diff --git a/src/info.h b/src/info.h
index c9f7299d80790b60b8564e075ecb3f523ae8d332..dfd30bc5b15c3a16347b66368f3d974fa2d63764 100644
--- a/src/info.h
+++ b/src/info.h
@@ -3742,6 +3742,7 @@ typedef enum mobj_type
 	MT_RING,
 	MT_FLINGRING, // Lost ring
 	MT_BLUESPHERE,  // Blue sphere for special stages
+	MT_FLINGBLUESPHERE, // Lost blue sphere
 	MT_BOMBSPHERE,
 	MT_REDTEAMRING,  //Rings collectable by red team.
 	MT_BLUETEAMRING, //Rings collectable by blue team.
@@ -4206,6 +4207,7 @@ typedef enum mobj_type
 	MT_HOOPCENTER, // Center of a hoop
 	MT_NIGHTSCORE,
 	MT_NIGHTSCHIP, // NiGHTS Chip
+	MT_FLINGNIGHTSCHIP, // Lost NiGHTS Chip
 	MT_NIGHTSSTAR, // NiGHTS Star
 	MT_NIGHTSSUPERLOOP,
 	MT_NIGHTSDRILLREFILL,
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 8a1079c364be25080301a2880364253d9c69d864..ff62f2459d514406dd80f0087257179603a0f013 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -298,6 +298,8 @@ static int player_get(lua_State *L)
 		lua_pushinteger(L, plr->finishedtime);
 	else if (fastcmp(field,"finishedspheres"))
 		lua_pushinteger(L, plr->finishedspheres);
+	else if (fastcmp(field,"finishedrings"))
+		lua_pushinteger(L, plr->finishedrings);
 	else if (fastcmp(field,"marescore"))
 		lua_pushinteger(L, plr->marescore);
 	else if (fastcmp(field,"lastmarescore"))
@@ -576,6 +578,8 @@ static int player_set(lua_State *L)
 		plr->finishedtime = (tic_t)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"finishedspheres"))
 		plr->finishedspheres = (INT16)luaL_checkinteger(L, 3);
+	else if (fastcmp(field,"finishedrings"))
+		plr->finishedrings = (INT16)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"marescore"))
 		plr->marescore = (UINT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"lastmarescore"))
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 5ac7422707c228f85bcaf3922704fb4281581faf..b572b84eb53d19975843b6e483ddea9bf543bad4 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -890,6 +890,23 @@ void Command_Setrings_f(void)
 	}
 }
 
+void Command_Setspheres_f(void)
+{
+	REQUIRE_INLEVEL;
+	REQUIRE_SINGLEPLAYER;
+	REQUIRE_NOULTIMATE;
+	REQUIRE_PANDORA;
+
+	if (COM_Argc() > 1)
+	{
+		// P_GivePlayerRings does value clamping
+		players[consoleplayer].spheres = 0;
+		P_GivePlayerSpheres(&players[consoleplayer], atoi(COM_Argv(1)));
+
+		G_SetGameModified(multiplayer);
+	}
+}
+
 void Command_Setlives_f(void)
 {
 	REQUIRE_INLEVEL;
diff --git a/src/m_cheat.h b/src/m_cheat.h
index 951c7a16a261f435fc464f37dd93585c0c156b2e..31f650b3fdeff5f2aaa24f4a346ac81106f63d92 100644
--- a/src/m_cheat.h
+++ b/src/m_cheat.h
@@ -51,6 +51,7 @@ void Command_Savecheckpoint_f(void);
 void Command_Getallemeralds_f(void);
 void Command_Resetemeralds_f(void);
 void Command_Setrings_f(void);
+void Command_Setspheres_f(void);
 void Command_Setlives_f(void);
 void Command_Setcontinues_f(void);
 void Command_Devmode_f(void);
diff --git a/src/m_menu.c b/src/m_menu.c
index b11873adb4500d00e60d965cc01b140a41549016..f99f5d860c73e3db25f8b746840d23f60d3e2a4b 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -5273,7 +5273,10 @@ static void M_HandleAddons(INT32 choice)
 static void M_PandorasBox(INT32 choice)
 {
 	(void)choice;
-	CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0));
+	if (maptol & TOL_NIGHTS)
+		CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].spheres, 0));
+	else
+		CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0));
 	if (players[consoleplayer].lives == 0x7f)
 		CV_StealthSetValue(&cv_dummylives, -1);
 	else
@@ -5291,7 +5294,12 @@ static void M_PandorasBox(INT32 choice)
 static boolean M_ExitPandorasBox(void)
 {
 	if (cv_dummyrings.value != max(players[consoleplayer].rings, 0))
-		COM_ImmedExecute(va("setrings %d", cv_dummyrings.value));
+	{
+		if (maptol & TOL_NIGHTS)
+			COM_ImmedExecute(va("setspheres %d", cv_dummyrings.value));
+		else
+			COM_ImmedExecute(va("setrings %d", cv_dummyrings.value));
+	}
 	if (cv_dummylives.value != players[consoleplayer].lives)
 		COM_ImmedExecute(va("setlives %d", cv_dummylives.value));
 	if (cv_dummycontinues.value != players[consoleplayer].continues)
diff --git a/src/p_inter.c b/src/p_inter.c
index 5737e2c2acb266561beffc2475e480aef596f49d..ce8bba6b6e7cc9a33c3d1e664b4846914be545ae 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -490,7 +490,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 				P_DoNightsScore(player);
 			break;
 		case MT_BLUESPHERE:
+		case MT_FLINGBLUESPHERE:
 		case MT_NIGHTSCHIP:
+		case MT_FLINGNIGHTSCHIP:
 			if (!(P_CanPickupItem(player, false)) && !(special->flags2 & MF2_NIGHTSPULL))
 				return;
 
@@ -2770,18 +2772,26 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
 		return true;
 	}
 
-	if (player->rings > 0) // Ring loss
+	if (player->powers[pw_carry] == CR_NIGHTSFALL)
+	{
+		if (player->spheres > 0)
+		{
+			P_PlayRinglossSound(target);
+			P_PlayerRingBurst(player, player->spheres);
+			player->spheres = 0;
+		}
+	}
+	else if (player->rings > 0) // Ring loss
 	{
 		P_PlayRinglossSound(target);
 		P_PlayerRingBurst(player, player->rings);
+		player->rings = 0;
 	}
 	else // Death
 	{
 		P_PlayDeathSound(target);
 		P_PlayVictorySound(source); // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!!
 	}
-
-	player->rings = 0;
 	return true;
 }
 
@@ -2996,7 +3006,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
 	}
 }
 
-static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
+static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype, boolean dospheres)
 {
 	P_DoPlayerPain(player, source, inflictor);
 
@@ -3026,9 +3036,19 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
 	// Ring loss sound plays despite hitting spikes
 	P_PlayRinglossSound(player->mo); // Ringledingle!
 	P_PlayerRingBurst(player, damage);
-	player->rings -= damage;
-	if (player->rings < 0)
-		player->rings = 0;
+
+	if (dospheres)
+	{
+		player->spheres -= damage;
+		if (player->spheres < 0)
+			player->spheres = 0;
+	}
+	else
+	{
+		player->rings -= damage;
+		if (player->rings < 0)
+			player->rings = 0;
+	}
 }
 
 //
@@ -3245,7 +3265,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 		if (damagetype & DMG_DEATHMASK)
 		{
 			P_KillPlayer(player, source, damage);
-			player->rings = 0;
+			player->rings = player->spheres = 0;
 		}
 		else if (metalrecording)
 		{
@@ -3289,10 +3309,19 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 			P_ShieldDamage(player, inflictor, source, damage, damagetype);
 			damage = 0;
 		}
+		else if (player->powers[pw_carry] == CR_NIGHTSFALL)
+		{
+			if (player->spheres > 0)
+			{
+				damage = player->spheres;
+				P_RingDamage(player, inflictor, source, damage, damagetype, true);
+				damage = 0;
+			}
+		}
 		else if (player->rings > 0) // No shield but have rings.
 		{
 			damage = player->rings;
-			P_RingDamage(player, inflictor, source, damage, damagetype);
+			P_RingDamage(player, inflictor, source, damage, damagetype, false);
 			damage = 0;
 		}
 		// To reduce griefing potential, don't allow players to be killed
@@ -3373,13 +3402,14 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 	angle_t fa;
 	fixed_t ns;
 	fixed_t z;
+	boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap));
 
 	// Better safe than sorry.
 	if (!player)
 		return;
 
 	// If no health, don't spawn ring!
-	if (player->rings <= 0)
+	if (((maptol & TOL_NIGHTS) && player->spheres <= 0) || (!(maptol & TOL_NIGHTS) && player->rings <= 0))
 		num_rings = 0;
 
 	if (num_rings > 32 && player->powers[pw_carry] != CR_NIGHTSFALL)
@@ -3396,6 +3426,8 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 		INT32 objType = mobjinfo[MT_RING].reactiontime;
 		if (mariomode)
 			objType = mobjinfo[MT_COIN].reactiontime;
+		else if (player->powers[pw_carry] == CR_NIGHTSFALL)
+			objType = mobjinfo[(nightsreplace ? MT_NIGHTSCHIP : MT_BLUESPHERE)].reactiontime;
 
 		z = player->mo->z;
 		if (player->mo->eflags & MFE_VERTICALFLIP)
@@ -3424,6 +3456,9 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 
 			P_SetObjectMomZ(mo, 8*FRACUNIT, false);
 			mo->fuse = 20*TICRATE; // Adjust fuse for NiGHTS
+
+			// Toggle bonus time colors
+			P_SetMobjState(mo, (player->bonustime ? mo->info->raisestate : mo->info->spawnstate));
 		}
 		else
 		{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index be373fbf4a3745a09eea481c7ef48342b8e65739..4353e67c392f13700790ced6df1330d8f791709c 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -1539,6 +1539,8 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
 			{
 				case MT_FLINGRING:
 				case MT_FLINGCOIN:
+				case MT_FLINGBLUESPHERE:
+				case MT_FLINGNIGHTSCHIP:
 				case MT_FLINGEMERALD:
 				case MT_BOUNCERING:
 				case MT_RAILRING:
@@ -2523,6 +2525,8 @@ static boolean P_ZMovement(mobj_t *mo)
 		case MT_BLUETEAMRING:
 		case MT_FLINGRING:
 		case MT_FLINGCOIN:
+		case MT_FLINGBLUESPHERE:
+		case MT_FLINGNIGHTSCHIP:
 		case MT_FLINGEMERALD:
 			// Remove flinged stuff from death pits.
 			if (P_CheckDeathPitCollide(mo))
@@ -2709,6 +2713,8 @@ static boolean P_ZMovement(mobj_t *mo)
 			// Flingrings bounce
 			if (mo->type == MT_FLINGRING
 				|| mo->type == MT_FLINGCOIN
+				|| mo->type == MT_FLINGBLUESPHERE
+				|| mo->type == MT_FLINGNIGHTSCHIP
 				|| P_WeaponOrPanel(mo->type)
 				|| mo->type == MT_FLINGEMERALD
 				|| mo->type == MT_BIGTUMBLEWEED
@@ -7941,6 +7947,8 @@ void P_MobjThinker(mobj_t *mobj)
 			// Flung items
 			case MT_FLINGRING:
 			case MT_FLINGCOIN:
+			case MT_FLINGBLUESPHERE:
+			case MT_FLINGNIGHTSCHIP:
 				if (mobj->flags2 & MF2_NIGHTSPULL)
 					P_NightsItemChase(mobj);
 				else
@@ -8278,6 +8286,8 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
 #ifdef ESLOPE // Sliding physics for slidey mobjs!
 	if (mobj->type == MT_FLINGRING
 		|| mobj->type == MT_FLINGCOIN
+		|| mobj->type == MT_FLINGBLUESPHERE
+		|| mobj->type == MT_FLINGNIGHTSCHIP
 		|| P_WeaponOrPanel(mobj->type)
 		|| mobj->type == MT_FLINGEMERALD
 		|| mobj->type == MT_BIGTUMBLEWEED
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 2e47f2077787bac16977c43c6b11ca79aafa3046..7cf43738463bce64297f60f54aa09a5d3687de03 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -203,6 +203,7 @@ static void P_NetArchivePlayers(void)
 		WRITEUINT32(save_p, players[i].startedtime);
 		WRITEUINT32(save_p, players[i].finishedtime);
 		WRITEINT16(save_p, players[i].finishedspheres);
+		WRITEINT16(save_p, players[i].finishedrings);
 		WRITEUINT32(save_p, players[i].marescore);
 		WRITEUINT32(save_p, players[i].lastmarescore);
 		WRITEUINT8(save_p, players[i].lastmare);
@@ -391,6 +392,7 @@ static void P_NetUnArchivePlayers(void)
 		players[i].startedtime = READUINT32(save_p);
 		players[i].finishedtime = READUINT32(save_p);
 		players[i].finishedspheres = READINT16(save_p);
+		players[i].finishedrings = READINT16(save_p);
 		players[i].marescore = READUINT32(save_p);
 		players[i].lastmarescore = READUINT32(save_p);
 		players[i].lastmare = READUINT8(save_p);
diff --git a/src/p_setup.c b/src/p_setup.c
index 80d004314ee9d9554b24c458e2d1629d9fb7005c..c62f281b3ee461eed4ccce49121c6a23d988bbb8 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -885,7 +885,8 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
 
 		mo = (mobj_t *)th;
 
-		if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP)
+		if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP
+			&& mo->type != MT_FLINGBLUESPHERE && mo->type != MT_FLINGNIGHTSCHIP)
 			continue;
 
 		if (!mo->health)
@@ -2379,12 +2380,13 @@ static void P_LevelInitStuff(void)
 		 players[i].marescore = players[i].lastmarescore =\
 		 players[i].maxlink = players[i].startedtime =\
 		 players[i].finishedtime = players[i].finishedspheres =\
-		 players[i].lastmare = players[i].marebegunat =\
-		 players[i].textvar = players[i].texttimer =\
-		 players[i].linkcount = players[i].linktimer =\
-		 players[i].flyangle = players[i].anotherflyangle =\
-		 players[i].nightstime = players[i].mare =\
-		 players[i].realtime = players[i].exiting = 0;
+		 players[i].finishedrings = players[i].lastmare =\
+		 players[i].marebegunat = players[i].textvar =\
+		 players[i].texttimer = players[i].linkcount =\
+		 players[i].linktimer = players[i].flyangle =\
+		 players[i].anotherflyangle = players[i].nightstime =\
+		 players[i].mare = players[i].realtime =\
+		 players[i].exiting = 0;
 
 		// i guess this could be part of the above but i feel mildly uncomfortable implicitly casting
 		players[i].gotcontinue = false;
diff --git a/src/p_user.c b/src/p_user.c
index 357933f1401d42291e955c850a3eab176e89ab89..fd09b084755a07215b8487ee56716f9e5b3da787 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -590,8 +590,9 @@ static void P_DeNightserizePlayer(player_t *player)
 	else if (player == &players[secondarydisplayplayer])
 		localaiming2 = 0;
 
-	// If you screwed up, kiss your score goodbye.
+	// If you screwed up, kiss your score and ring bonus goodbye.
 	player->marescore = 0;
+	player->rings = 0;
 
 	P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
 
@@ -684,6 +685,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 	{
 		INT32 i;
 		INT32 total_spheres = 0;
+		INT32 total_rings = 0;
 
 		P_SetTarget(&player->mo->target, NULL);
 
@@ -691,7 +693,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 		{
 			for (i = 0; i < MAXPLAYERS; i++)
 				if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/)
+				{
 					total_spheres += players[i].spheres;
+					total_rings += players[i].rings;
+				}
 		}
 
 		for (i = 0; i < MAXPLAYERS; i++)
@@ -705,11 +710,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 			if (G_IsSpecialStage(gamemap))
 			{
 				players[i].finishedspheres = (INT16)total_spheres;
+				players[i].finishedrings = (INT16)total_rings;
 				P_AddPlayerScore(player, total_spheres * 50);
 			}
 			else
 			{
 				players[i].finishedspheres = (INT16)(players[i].spheres);
+				players[i].finishedrings = (INT16)(players[i].rings);
 				P_AddPlayerScore(&players[i], (players[i].spheres) * 50);
 			}
 
@@ -721,7 +728,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 			players[i].lastmarescore = players[i].marescore;
 			players[i].marescore = 0;
 
-			players[i].spheres = 0;
+			players[i].spheres = players[i].rings = 0;
 			P_DoPlayerExit(&players[i]);
 		}
 	}
@@ -745,7 +752,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 		player->marescore = 0;
 		player->marebegunat = leveltime;
 
-		player->spheres = 0;
+		player->spheres = player->rings = 0;
 	}
 	else
 	{
@@ -7023,7 +7030,7 @@ static void P_MovePlayer(player_t *player)
 					if (playeringame[i])
 						players[i].exiting = (14*TICRATE)/5 + 1;
 			}
-			else if (player->rings > 0)
+			else if (player->spheres > 0)
 				P_DamageMobj(player->mo, NULL, NULL, 1, 0);
 			player->powers[pw_carry] = CR_NONE;
 		}