#include "StarEffectEmitter.hpp" #include "StarJsonExtra.hpp" #include "StarRoot.hpp" #include "StarParticleDatabase.hpp" #include "StarEntityRendering.hpp" #include "StarDataStreamExtra.hpp" namespace Star { EffectEmitter::EffectEmitter() { m_renders = false; m_direction = Direction::Right; addNetElement(&m_activeSources); } void EffectEmitter::addEffectSources(String const& position, StringSet effectSources) { for (auto& e : effectSources) m_newSources.add({position, std::move(e)}); } void EffectEmitter::setSourcePosition(String name, Vec2F const& position) { m_positions[std::move(name)] = position; } void EffectEmitter::setDirection(Direction direction) { m_direction = direction; } void EffectEmitter::setBaseVelocity(Vec2F const& velocity) { m_baseVelocity = velocity; } void EffectEmitter::tick(float dt, EntityMode mode) { if (mode == EntityMode::Master) { m_activeSources.set(std::move(m_newSources)); m_newSources.clear(); } else { if (!m_newSources.empty()) throw StarException("EffectEmitters can only be added to the master entity."); } if (m_renders) { eraseWhere(m_sources, [](EffectSourcePtr const& source) { return source->expired(); }); for (auto& ps : m_sources) ps->tick(dt); Set> current; for (auto& ps : m_sources) { pair entry = {ps->suggestedSpawnLocation(), ps->kind()}; current.add(entry); if (!m_activeSources.get().contains(entry)) { ps->stop(); } } for (auto& c : m_activeSources.get()) { if (!current.contains(c)) { m_sources.append(Root::singleton().effectSourceDatabase()->effectSourceConfig(c.second)->instance(c.first)); } } } } void EffectEmitter::reset() { m_sources.clear(); m_newSources.clear(); m_activeSources.set({}); } void EffectEmitter::render(RenderCallback* renderCallback) { m_renders = true; if (m_sources.empty()) return; for (auto& ps : m_sources) { Vec2F position = m_positions.get(ps->effectSpawnLocation()); for (auto& p : ps->particles()) { Particle particle = Root::singleton().particleDatabase()->particle(p); if (m_direction == Direction::Left) { particle.flip = true; particle.position[0] = -particle.position[0]; particle.velocity[0] = -particle.velocity[0]; particle.finalVelocity[0] = -particle.finalVelocity[0]; } particle.velocity += m_baseVelocity; particle.finalVelocity += m_baseVelocity; particle.position += position; renderCallback->addParticle(particle); } for (auto& s : ps->sounds(position)) renderCallback->addAudio(s); } for (auto& ps : m_sources) ps->postRender(); } Json EffectEmitter::toJson() const { return JsonObject{{"activeSources", jsonFromSet>(m_activeSources.get(), [](pair const& entry) { return JsonObject{{"position", entry.first}, {"source", entry.second}}; })}}; } void EffectEmitter::fromJson(Json const& diskStore) { m_activeSources.set(jsonToSet>(diskStore.get("activeSources"), [](Json const& v) { return pair{v.getString("position"), v.getString("source")}; })); } }