diff --git a/datasrc/network.py b/datasrc/network.py index ca4914878..f028337d1 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -1,7 +1,7 @@ # pylint: skip-file # See https://github.com/ddnet/ddnet/issues/3507 -from datatypes import Enum, Flags, NetArray, NetBool, NetEvent, NetIntAny, NetIntRange, NetMessage, NetMessageEx, NetObject, NetObjectEx, NetString, NetStringHalfStrict, NetStringStrict, NetTick +from datatypes import Enum, Flags, NetArray, NetBool, NetEvent, NetEventEx, NetIntAny, NetIntRange, NetMessage, NetMessageEx, NetObject, NetObjectEx, NetString, NetStringHalfStrict, NetStringStrict, NetTick Emotes = ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"] PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"] @@ -328,6 +328,7 @@ Objects = [ NetEvent("Spawn:Common", []), NetEvent("HammerHit:Common", []), + NetEvent("Death:Common", [ NetIntRange("m_ClientId", 0, 'MAX_CLIENTS-1'), ]), @@ -344,6 +345,8 @@ Objects = [ NetIntAny("m_Angle"), ]), + NetEventEx("Finish:Common", "finish@netevent.ddnet.org", []), + NetObjectEx("MyOwnEvent", "my-own-event@heinrich5991.de", [ NetIntAny("m_Test"), ]), diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index f3b38db8c..f6389e924 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -231,6 +231,60 @@ void CEffects::PlayerDeath(vec2 Pos, int ClientId, float Alpha) } } +void CEffects::FinishConfetti(vec2 Pos, float Alpha) +{ + ColorRGBA Red(1.0f, 0.4f, 0.4f); + ColorRGBA Green(0.4f, 1.0f, 0.4f); + ColorRGBA Blue(0.4f, 0.4f, 1.0f); + ColorRGBA Yellow(1.0f, 1.0f, 0.4f); + ColorRGBA Cyan(0.4f, 1.0f, 1.0f); + ColorRGBA Magenta(1.0f, 0.4f, 1.0f); + + ColorRGBA aConfettiColors[] = {Red, Green, Blue, Yellow, Cyan, Magenta}; + + // powerful confettis + for(int i = 0; i < 32; i++) + { + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SPLAT01 + (rand() % 3); + p.m_Pos = Pos; + p.m_Vel = direction(-0.5f * pi + random_float(-0.2f, 0.2f)) * random_float(0.01f, 1.0f) * 2000.0f; + p.m_LifeSpan = random_float(1.0f, 1.2f); + p.m_StartSize = random_float(12.0f, 24.0f); + p.m_EndSize = 0; + p.m_Rot = random_angle(); + p.m_Rotspeed = random_float(-0.5f, 0.5f) * pi; + p.m_Gravity = -700.0f; + p.m_Friction = 0.6f; + ColorRGBA c = aConfettiColors[(rand() % std::size(aConfettiColors))]; + p.m_Color = c.WithMultipliedAlpha(0.75f * Alpha); + p.m_StartAlpha = Alpha; + m_pClient->m_Particles.Add(CParticles::GROUP_GENERAL, &p); + } + + // broader confettis + for(int i = 0; i < 32; i++) + { + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SPLAT01 + (rand() % 3); + p.m_Pos = Pos; + p.m_Vel = direction(-0.5f * pi + random_float(-0.8f, 0.8f)) * random_float(0.01f, 1.0f) * 1500.0f; + p.m_LifeSpan = random_float(0.8f, 1.0f); + p.m_StartSize = random_float(12.0f, 24.0f); + p.m_EndSize = 0; + p.m_Rot = random_angle(); + p.m_Rotspeed = random_float(-0.5f, 0.5f) * pi; + p.m_Gravity = -700.0f; + p.m_Friction = 0.6f; + ColorRGBA c = aConfettiColors[(rand() % std::size(aConfettiColors))]; + p.m_Color = c.WithMultipliedAlpha(0.75f * Alpha); + p.m_StartAlpha = Alpha; + m_pClient->m_Particles.Add(CParticles::GROUP_GENERAL, &p); + } +} + void CEffects::Explosion(vec2 Pos, float Alpha) { // add to flow diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h index adc0a374b..c88b691ef 100644 --- a/src/game/client/components/effects.h +++ b/src/game/client/components/effects.h @@ -31,6 +31,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 FinishConfetti(vec2 Pos, float Alpha = 1.0f); void Update(); }; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d41cd9607..944fe5398 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1140,6 +1140,11 @@ void CGameClient::ProcessEvents() CNetEvent_HammerHit *pEvent = (CNetEvent_HammerHit *)pData; m_Effects.HammerHit(vec2(pEvent->m_X, pEvent->m_Y), Alpha); } + else if(Item.m_Type == NETEVENTTYPE_FINISH) + { + CNetEvent_Finish *pEvent = (CNetEvent_Finish *)pData; + m_Effects.FinishConfetti(vec2(pEvent->m_X, pEvent->m_Y), Alpha); + } else if(Item.m_Type == NETEVENTTYPE_SPAWN) { CNetEvent_Spawn *pEvent = (CNetEvent_Spawn *)pData; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 70107c519..2ffcea829 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -347,6 +347,17 @@ void CGameContext::CreateDeath(vec2 Pos, int ClientId, CClientMask Mask) } } +void CGameContext::CreateFinishConfetti(vec2 Pos, CClientMask Mask) +{ + // create the event + CNetEvent_Finish *pEvent = m_Events.Create(Mask); + if(pEvent) + { + pEvent->m_X = (int)Pos.x; + pEvent->m_Y = (int)Pos.y; + } +} + void CGameContext::CreateSound(vec2 Pos, int Sound, CClientMask Mask) { if(Sound < 0) diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index d7ae91341..b8423e669 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -239,6 +239,7 @@ public: void CreateHammerHit(vec2 Pos, CClientMask Mask = CClientMask().set()); void CreatePlayerSpawn(vec2 Pos, CClientMask Mask = CClientMask().set()); void CreateDeath(vec2 Pos, int ClientId, CClientMask Mask = CClientMask().set()); + void CreateFinishConfetti(vec2 Pos, CClientMask Mask = CClientMask().set()); void CreateSound(vec2 Pos, int Sound, CClientMask Mask = CClientMask().set()); void CreateSoundGlobal(int Sound, int Target = -1) const; diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index e6f70a944..75a8e4d30 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -848,6 +848,10 @@ void CGameTeams::OnFinish(CPlayer *Player, int TimeTicks, const char *pTimestamp { Player->m_Score = TTime; } + + // Confetti + CCharacter *pChar = Player->GetCharacter(); + m_pGameContext->CreateFinishConfetti(pChar->m_Pos, pChar->TeamMask()); } void CGameTeams::RequestTeamSwap(CPlayer *pPlayer, CPlayer *pTargetPlayer, int Team)