#include "celebration_system.hpp" #include "entities/camera.hpp" #include "entities/world.hpp" #include "systems/particle_system.hpp" namespace Nimbin { void CelebrationSystem::start(const Camera& cam, double& glyph_yaw) { _active = true; _t = 0.0; _next_burst = 0.0; const double ws = World::get_BoxScale(); const double floor = World::get_FloorY(); const double margin = 1.0; Vec3 banner_pos { cam.pos.x + cam.fwd.x * 10.0, cam.pos.y + cam.fwd.y * 10.0, cam.pos.z + cam.fwd.z * 10.0, }; auto clamp = [](double v, double lo, double hi) { return v < lo ? lo : (v > hi ? hi : v); }; banner_pos.x = clamp(banner_pos.x, -ws + margin, ws - margin); banner_pos.z = clamp(banner_pos.z, -ws + margin, ws - margin); banner_pos.y = clamp(banner_pos.y, floor + 1.0, ws - margin); _banner = Text::make_Token("Success", Text::Token::depth_floor * 2.0f, 0.012f, banner_pos, Config::Color::white); _banner->yaw = static_cast(glyph_yaw); _banner->body.mode = PhysicsMode::Static; } void CelebrationSystem::tick(double dt, ParticleSystem& particle_sys) { if (!_active) return; _t += dt; if (_banner) _banner->yaw += static_cast(dt * 0.6); if (_t >= _next_burst && _t < _duration - 0.3) { const double ws = World::get_BoxScale(); const double margin = 3.0; auto rnd = []() { return Random::unit(); }; Vec3 center { (rnd() * 2.0 - 1.0) * (ws - margin), rnd() * (ws - margin), (rnd() * 2.0 - 1.0) * (ws - margin), }; double h = rnd() * 6.0; int i = static_cast(h); double f = h - i; float r=0, g=0, b=0; switch (i % 6) { case 0: r=1; g=(float)f; b=0; break; case 1: r=(float)(1-f); g=1; b=0; break; case 2: r=0; g=1; b=(float)f; break; case 3: r=0; g=(float)(1-f); b=1; break; case 4: r=(float)f; g=0; b=1; break; case 5: r=1; g=0; b=(float)(1-f); break; } particle_sys.emit_FireworkBurst(center, SDL_FColor{r, g, b, 1.0f}, 80); _next_burst = _t + 0.5 + rnd() * 0.5; } } void CelebrationSystem::finish(ParticleSystem& particle_sys) { _active = false; _banner. reset(); particle_sys.clear(); } bool CelebrationSystem::is_Active() const { return _active; } double CelebrationSystem::get_Progress() const { return (_duration > 0.0) ? (_t / _duration) : 1.0; } void CelebrationSystem::draw(GlRenderer& gl, const Camera& cam, const Light& light) const { if (!_active || !_banner) return; _banner->draw(gl, cam, light); } } // namespace Nimbin