diff --git a/src/deh_tables.c b/src/deh_tables.c
index b53cd00c8fc23149a9a9310776335d59e7edd27a..baa8ece163ecff24dc6392ad7f48e9477f7409bc 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -370,8 +370,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
 	"S_XDEATHSTATE",
 	"S_RAISESTATE",
 
-	// Thok
+	// Thok effect and spin trail
 	"S_THOK",
+	"S_THOKEFFECT",
 
 	// Player
 	"S_PLAY_STND",
@@ -3560,7 +3561,8 @@ const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for sanity t
 	"MT_NULL",
 	"MT_UNKNOWN",
 
-	"MT_THOK", // Thok! mobj
+	"MT_THOK", // Spin trail mobj
+	"MT_THOKEFFECT", // Thok boom effect
 	"MT_PLAYER",
 	"MT_TAILSOVERLAY", // c:
 	"MT_METALJETFUME",
diff --git a/src/g_demo.c b/src/g_demo.c
index f39efad8e68fe81a37eed65925dc8c1ae394dae3..8a8ad1259f9c39d4666b64c0cbdd0108400a6dc9 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -801,6 +801,19 @@ void G_GhostTicker(void)
 						if (!P_MobjWasRemoved(mobj))
 							mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
 					}
+					else if (type == MT_THOKEFFECT)
+					{
+						mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, FixedDiv(g->mo->height, g->mo->scale)*3/4, type);
+						mobj->angle = g->mo->angle + ANGLE_90;
+						mobj->fuse = 7;
+						mobj->scale = g->mo->scale / 3;
+						mobj->destscale = 10 * g->mo->scale;
+						mobj->colorized = true;
+						mobj->color = g->mo->color;
+						mobj->momx = -g->mo->momx / 2;
+						mobj->momy = -g->mo->momy / 2;
+					}
+
 					else
 					{
 						mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
@@ -1107,6 +1120,18 @@ void G_ReadMetalTic(mobj_t *metal)
 				{
 					mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
 				}
+				else if (type == MT_THOKEFFECT)
+				{
+					mobj = P_SpawnMobjFromMobj(metal, 0, 0, FixedDiv(metal->height, metal->scale)*3/4, type);
+					mobj->angle = metal->angle + ANGLE_90;
+					mobj->fuse = 7;
+					mobj->scale = metal->scale / 3;
+					mobj->destscale = 10 * metal->scale;
+					mobj->colorized = true;
+					mobj->color = metal->color;
+					mobj->momx = -metal->momx / 2;
+					mobj->momy = -metal->momy / 2;
+				}
 				else
 				{
 					mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index bcfdfa960d7b723ecb0be2437667bcf09b1030e9..94f01e2991ab8629676198272d76696c42d3afe1 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -138,6 +138,7 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[NOLIGHT],     // SPR_UNKN
 
 	&lspr[NOLIGHT],     // SPR_THOK
+	&lspr[NOLIGHT],     // SPR_THKE
 	&lspr[SUPERSONIC_L],// SPR_PLAY
 
 	// Enemies
diff --git a/src/info.c b/src/info.c
index 5790dd7c56ce3ee5f625f63581903a6d185a3a73..d1707c86a597902fdbbba249387cfa591a11c661 100644
--- a/src/info.c
+++ b/src/info.c
@@ -33,7 +33,8 @@ char sprnames[NUMSPRITES + 1][5] =
 	"NULL", // invisible object
 	"UNKN",
 
-	"THOK", // Thok! mobj
+	"THOK", // Spin trail mobj
+	"THKE", // Thok boom effect
 	"PLAY",
 
 	// Enemies
@@ -703,8 +704,9 @@ state_t states[NUMSTATES] =
 	{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 5, 0, S_NULL}, // S_XDEATHSTATE
 	{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE
 
-	// Thok
+	// Spin trail and thok boom effect
 	{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
+	{SPR_THKE, FF_TRANS50|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_THOKEFFECT
 
 	// Player
 	{SPR_PLAY, SPR2_STND|FF_ANIMATE,    105, {NULL}, 0,  7, S_PLAY_WAIT}, // S_PLAY_STND
@@ -4078,6 +4080,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
 		S_NULL          // raisestate
 	},
+	
+	{           // MT_THOKEFFECT
+		-1,             // doomednum
+		S_THOKEFFECT,   // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		8,              // speed
+		32*FRACUNIT,    // radius
+		64*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_NULL          // raisestate
+	},
 
 	{           // MT_PLAYER
 		-1,             // doomednum
diff --git a/src/info.h b/src/info.h
index a2d87dbdc10644edaaf34187d45495d70ba49f85..32aff18fbd27b94eb60505cc9dd0028304f8241b 100644
--- a/src/info.h
+++ b/src/info.h
@@ -580,7 +580,8 @@ typedef enum sprite
 	SPR_NULL, // invisible object
 	SPR_UNKN,
 
-	SPR_THOK, // Thok! mobj
+	SPR_THOK, // Spin trail mobj
+	SPR_THKE, // Thok boom effect
 	SPR_PLAY,
 
 	// Enemies
@@ -1182,8 +1183,9 @@ typedef enum state
 	S_XDEATHSTATE,
 	S_RAISESTATE,
 
-	// Thok
+	// Thok boom effect and spin trail
 	S_THOK,
+	S_THOKEFFECT,
 
 	// Player
 	S_PLAY_STND,
@@ -4392,7 +4394,8 @@ typedef enum mobj_type
 	MT_NULL,
 	MT_UNKNOWN,
 
-	MT_THOK, // Thok! mobj
+	MT_THOK, // Spin trail mobj
+	MT_THOKEFFECT, // Thok boom effect
 	MT_PLAYER,
 	MT_TAILSOVERLAY, // c:
 	MT_METALJETFUME,
diff --git a/src/p_user.c b/src/p_user.c
index 0c21a1cc15fdcf310276222879c0fb04e232a01e..5cb1d9d5aea95422c58b41493d308eb0382bd673 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -2122,7 +2122,19 @@ void P_SpawnThokMobj(player_t *player)
 
 	if (type == MT_GHOST)
 		mobj = P_SpawnGhostMobj(player->mo); // virtually does everything here for us
-	else
+	else if (type == MT_THOKEFFECT) // Thok boom effect for Sonic
+	{
+		mobj = P_SpawnMobjFromMobj(player->mo, 0, 0, FixedDiv(player->mo->height, player->mo->scale)*3/4, type);
+		mobj->angle = player->mo->angle + ANGLE_90;
+		mobj->fuse = 7;
+		mobj->scale = player->mo->scale / 3;
+		mobj->destscale = 10 * player->mo->scale;
+		mobj->colorized = true;
+		mobj->color = player->mo->color;
+		mobj->momx = -player->mo->momx / 2;
+		mobj->momy = -player->mo->momy / 2;
+	}
+	else // Normal thok object handling
 	{
 		if (player->mo->eflags & MFE_VERTICALFLIP)
 			zheight = player->mo->z + player->mo->height + FixedDiv(P_GetPlayerHeight(player) - player->mo->height, 3*FRACUNIT) - FixedMul(mobjinfo[type].height, player->mo->scale);