osb/source/game/StarEffectEmitter.cpp

111 lines
3.3 KiB
C++
Raw Normal View History

2023-06-20 04:33:09 +00:00
#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)});
2023-06-20 04:33:09 +00:00
}
void EffectEmitter::setSourcePosition(String name, Vec2F const& position) {
m_positions[std::move(name)] = position;
2023-06-20 04:33:09 +00:00
}
void EffectEmitter::setDirection(Direction direction) {
m_direction = direction;
}
void EffectEmitter::setBaseVelocity(Vec2F const& velocity) {
m_baseVelocity = velocity;
}
void EffectEmitter::tick(float dt, EntityMode mode) {
2023-06-20 04:33:09 +00:00
if (mode == EntityMode::Master) {
m_activeSources.set(std::move(m_newSources));
2023-06-20 04:33:09 +00:00
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);
2023-06-20 04:33:09 +00:00
Set<pair<String, String>> current;
for (auto& ps : m_sources) {
pair<String, String> 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<pair<String, String>>(m_activeSources.get(),
[](pair<String, String> const& entry) {
return JsonObject{{"position", entry.first}, {"source", entry.second}};
})}};
}
void EffectEmitter::fromJson(Json const& diskStore) {
m_activeSources.set(jsonToSet<pair<String, String>>(diskStore.get("activeSources"),
[](Json const& v) {
return pair<String, String>{v.getString("position"), v.getString("source")};
}));
}
}