diff --git a/data/extras.png b/data/extras.png index b2c6deea1..14d320e1e 100644 Binary files a/data/extras.png and b/data/extras.png differ diff --git a/datasrc/content.py b/datasrc/content.py index 52353c491..7cb5fbe1a 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -452,6 +452,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..ae2a1bdb4 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -103,6 +103,26 @@ void CEffects::FreezingFlakes(vec2 Pos, vec2 Size, float Alpha) m_pClient->m_Particles.Add(CParticles::GROUP_EXTRA, &p); } +void CEffects::SparkleTrail(vec2 Pos, float Alpha) +{ + if(!m_Add50hz) + return; + + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SPARKLE; + p.m_Pos = Pos + random_direction() * random_float(40.0f); + p.m_Vel = vec2(0, 0); + p.m_LifeSpan = 0.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 = std::min(0.2f, Alpha); + p.m_Collides = false; + m_pClient->m_Particles.Add(CParticles::GROUP_TRAIL_EXTRA, &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..703eff397 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 SparkleTrail(vec2 Pos, 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..21ef0ce35 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -14,6 +14,7 @@ CParticles::CParticles() { OnReset(); m_RenderTrail.m_pParts = this; + m_RenderTrailExtra.m_pParts = this; m_RenderExplosions.m_pParts = this; m_RenderExtra.m_pParts = this; m_RenderGeneral.m_pParts = this; @@ -181,9 +182,12 @@ 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); } @@ -207,7 +211,7 @@ void CParticles::RenderGroup(int Group) IGraphics::CTextureHandle *aParticles = GameClient()->m_ParticlesSkin.m_aSpriteParticles; int FirstParticleOffset = SPRITE_PART_SLICE; int ParticleQuadContainerIndex = m_ParticleQuadContainerIndex; - if(Group == GROUP_EXTRA) + if(Group == GROUP_EXTRA || Group == GROUP_TRAIL_EXTRA) { aParticles = GameClient()->m_ExtrasSkin.m_aSpriteParticles; FirstParticleOffset = SPRITE_PART_SNOWFLAKE; diff --git a/src/game/client/components/particles.h b/src/game/client/components/particles.h index 0d2f4937d..16c06b5d9 100644 --- a/src/game/client/components/particles.h +++ b/src/game/client/components/particles.h @@ -68,6 +68,7 @@ public: enum { GROUP_PROJECTILE_TRAIL = 0, + GROUP_TRAIL_EXTRA, GROUP_EXPLOSIONS, GROUP_EXTRA, GROUP_GENERAL, @@ -111,7 +112,10 @@ private: virtual void OnRender() override { m_pParts->RenderGroup(TGROUP); } }; + // behind players CRenderGroup m_RenderTrail; + CRenderGroup m_RenderTrailExtra; + // in front of players CRenderGroup m_RenderExplosions; CRenderGroup m_RenderExtra; CRenderGroup m_RenderGeneral; diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 85ea937ba..92609c65f 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -742,6 +742,10 @@ void CPlayers::RenderPlayer( { GameClient()->m_Effects.FreezingFlakes(BodyPos, vec2(32, 32), Alpha); } + if(RenderInfo.m_TeeRenderFlags & TEE_EFFECT_SPARKLE) + { + GameClient()->m_Effects.SparkleTrail(BodyPos, Alpha); + } if(ClientId < 0) return; @@ -833,6 +837,8 @@ void CPlayers::OnRender() aRenderInfo[i].m_TeeRenderFlags |= TEE_EFFECT_FROZEN | TEE_NO_WEAPON; if(m_pClient->m_aClients[i].m_LiveFrozen) aRenderInfo[i].m_TeeRenderFlags |= TEE_EFFECT_FROZEN; + if(m_pClient->m_aClients[i].m_Invincible) + aRenderInfo[i].m_TeeRenderFlags |= TEE_EFFECT_SPARKLE; const CGameClient::CSnapState::CCharacterInfo &CharacterInfo = m_pClient->m_Snap.m_aCharacters[i]; const bool Frozen = CharacterInfo.m_HasExtendedData && CharacterInfo.m_ExtendedData.m_FreezeEnd != 0; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 9aa732795..396ffcebd 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -128,6 +128,7 @@ void CGameClient::OnConsoleInit() &m_Background, // render instead of m_MapLayersBackground when g_Config.m_ClOverlayEntities == 100 &m_MapLayersBackground, // first to render &m_Particles.m_RenderTrail, + &m_Particles.m_RenderTrailExtra, &m_Items, &m_Ghost, &m_Players, @@ -1683,6 +1684,7 @@ void CGameClient::OnNewSnapshot() pClient->m_ShotgunHitDisabled = pCharacterData->m_Flags & CHARACTERFLAG_SHOTGUN_HIT_DISABLED; pClient->m_HookHitDisabled = pCharacterData->m_Flags & CHARACTERFLAG_HOOK_HIT_DISABLED; pClient->m_Super = pCharacterData->m_Flags & CHARACTERFLAG_SUPER; + pClient->m_Invincible = pCharacterData->m_Flags & CHARACTERFLAG_INVINCIBLE; // Endless pClient->m_EndlessHook = pCharacterData->m_Flags & CHARACTERFLAG_ENDLESS_HOOK; @@ -2457,6 +2459,7 @@ void CGameClient::CClientData::Reset() m_ShotgunHitDisabled = false; m_HookHitDisabled = false; m_Super = false; + m_Invincible = false; m_HasTelegunGun = false; m_HasTelegunGrenade = false; m_HasTelegunLaser = false; @@ -3697,6 +3700,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(); @@ -3731,7 +3735,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 bf0f9071d..ebaca0dd4 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -394,6 +394,7 @@ public: bool m_ShotgunHitDisabled; bool m_HookHitDisabled; bool m_Super; + bool m_Invincible; bool m_HasTelegunGun; bool m_HasTelegunGrenade; bool m_HasTelegunLaser; @@ -768,7 +769,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; diff --git a/src/game/client/render.h b/src/game/client/render.h index 17d8ccfa7..11b7255b9 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -123,6 +123,7 @@ enum { TEE_EFFECT_FROZEN = 1, TEE_NO_WEAPON = 2, + TEE_EFFECT_SPARKLE = 4, }; // sprite renderings