diff --git a/data/extras.png b/data/extras.png
index b2c6deea1..b2fd8aeb5 100644
Binary files a/data/extras.png and b/data/extras.png differ
diff --git a/datasrc/content.py b/datasrc/content.py
index 51c50b108..0bba8566a 100644
--- a/datasrc/content.py
+++ b/datasrc/content.py
@@ -454,6 +454,7 @@ container.sprites.Add(Sprite("hud_lock_mode", set_hud, 10,6,2,2))
 container.sprites.Add(Sprite("hud_team0_mode", set_hud, 12,6,2,2))
 
 container.sprites.Add(Sprite("part_snowflake", set_extras, 0,0,2,2))
+container.sprites.Add(Sprite("part_sparkle", set_extras, 2,0,2,2))
 
 
 anim = Animation("base")
diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp
index d5c7fd608..896a48f26 100644
--- a/src/game/client/components/effects.cpp
+++ b/src/game/client/components/effects.cpp
@@ -103,6 +103,30 @@ void CEffects::FreezingFlakes(vec2 Pos, vec2 Size, float Alpha)
 	m_pClient->m_Particles.Add(CParticles::GROUP_EXTRA, &p);
 }
 
+void CEffects::InvincibleSparkle(vec2 Pos, float Radius, float Alpha) {
+	if(!m_Add5hz)
+		return;
+
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_SPARKLE;
+	vec2 Direction = random_direction();
+	p.m_Pos = Pos + Direction * Radius;
+	p.m_Vel = Direction * 50.0f;
+	p.m_LifeSpan = 1.5f;
+	p.m_StartSize = 0.0f;
+	p.m_EndSize = random_float(20.0f, 30.0f);
+	p.m_UseAlphaFading = true;
+	p.m_StartAlpha = Alpha;
+	p.m_EndAlpha = 0.0f;
+	p.m_Rot = random_angle();
+	p.m_Rotspeed = 0.0f;
+	p.m_Gravity = 0.0f;
+	p.m_Friction = 0.9f;
+	p.m_Collides = false;
+	m_pClient->m_Particles.Add(CParticles::GROUP_GENERAL, &p);
+}
+
 void CEffects::SmokeTrail(vec2 Pos, vec2 Vel, float Alpha, float TimePassed)
 {
 	if(!m_Add50hz && TimePassed < 0.001f)
diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h
index de75e63c9..deddfc126 100644
--- a/src/game/client/components/effects.h
+++ b/src/game/client/components/effects.h
@@ -30,6 +30,7 @@ public:
 	void PlayerDeath(vec2 Pos, int ClientId, float Alpha = 1.0f);
 	void PowerupShine(vec2 Pos, vec2 Size, float Alpha = 1.0f);
 	void FreezingFlakes(vec2 Pos, vec2 Size, float Alpha = 1.0f);
+	void InvincibleSparkle(vec2 Pos, float Radius, float Alpha = 1.0f);
 	void Confetti(vec2 Pos, float Alpha = 1.0f);
 
 	void Update();
diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp
index fef6e886d..466057bc9 100644
--- a/src/game/client/components/particles.cpp
+++ b/src/game/client/components/particles.cpp
@@ -181,9 +181,11 @@ void CParticles::OnInit()
 
 	m_ExtraParticleQuadContainerIndex = Graphics()->CreateQuadContainer(false);
 
-	// TODO: Use a loop similar to the one for m_ParticleQuadContainerIndex if you add more additional particles
-	Graphics()->QuadsSetSubset(0, 0, 1, 1);
-	RenderTools()->QuadContainerAddSprite(m_ExtraParticleQuadContainerIndex, 1.f);
+	for(int i = 0; i <= (SPRITE_PART_SPARKLE - SPRITE_PART_SNOWFLAKE); ++i) {
+		Graphics()->QuadsSetSubset(0, 0, 1, 1);
+		RenderTools()->QuadContainerAddSprite(m_ExtraParticleQuadContainerIndex, 1.f);
+	}
+
 	Graphics()->QuadContainerUpload(m_ExtraParticleQuadContainerIndex);
 }
 
diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp
index 85ea937ba..d47c18066 100644
--- a/src/game/client/components/players.cpp
+++ b/src/game/client/components/players.cpp
@@ -742,6 +742,7 @@ void CPlayers::RenderPlayer(
 	{
 		GameClient()->m_Effects.FreezingFlakes(BodyPos, vec2(32, 32), Alpha);
 	}
+	GameClient()->m_Effects.InvincibleSparkle(BodyPos, 20.0f, Alpha);
 
 	if(ClientId < 0)
 		return;
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp
index e6a5d0fa5..4c8103d55 100644
--- a/src/game/client/gameclient.cpp
+++ b/src/game/client/gameclient.cpp
@@ -3701,6 +3701,7 @@ void CGameClient::LoadExtrasSkin(const char *pPath, bool AsDir)
 	if(m_ExtrasSkinLoaded)
 	{
 		Graphics()->UnloadTexture(&m_ExtrasSkin.m_SpriteParticleSnowflake);
+		Graphics()->UnloadTexture(&m_ExtrasSkin.m_SpriteParticleSparkle);
 
 		for(auto &SpriteParticle : m_ExtrasSkin.m_aSpriteParticles)
 			SpriteParticle = IGraphics::CTextureHandle();
@@ -3735,7 +3736,11 @@ void CGameClient::LoadExtrasSkin(const char *pPath, bool AsDir)
 	else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE].m_pSet->m_Gridy, true) && Graphics()->IsImageFormatRgba(aPath, ImgInfo))
 	{
 		m_ExtrasSkin.m_SpriteParticleSnowflake = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE]);
+		m_ExtrasSkin.m_SpriteParticleSparkle = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SPARKLE]);
+
 		m_ExtrasSkin.m_aSpriteParticles[0] = m_ExtrasSkin.m_SpriteParticleSnowflake;
+		m_ExtrasSkin.m_aSpriteParticles[1] = m_ExtrasSkin.m_SpriteParticleSparkle;
+
 		m_ExtrasSkinLoaded = true;
 	}
 	ImgInfo.Free();
diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h
index 5763dea59..aadee6992 100644
--- a/src/game/client/gameclient.h
+++ b/src/game/client/gameclient.h
@@ -770,7 +770,8 @@ public:
 	struct SClientExtrasSkin
 	{
 		IGraphics::CTextureHandle m_SpriteParticleSnowflake;
-		IGraphics::CTextureHandle m_aSpriteParticles[1];
+		IGraphics::CTextureHandle m_SpriteParticleSparkle;
+		IGraphics::CTextureHandle m_aSpriteParticles[2];
 	};
 
 	SClientExtrasSkin m_ExtrasSkin;
