Skip to content

Commit

Permalink
particle stuff, move the particle functions from rpc, expose some mor…
Browse files Browse the repository at this point in the history
…e particle stuff, allow for making custom `ParticleDB`
  • Loading branch information
Mr-Auto committed Nov 1, 2023
1 parent 5b317b8 commit c99216a
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 92 deletions.
79 changes: 78 additions & 1 deletion src/game_api/particles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <unordered_map> // for unordered_map, _Umap_traits<>::allocator_type
#include <utility> // for min, max

#include "entity.hpp" //
#include "search.hpp" // for get_address
#include "state.hpp" //
#include "texture.hpp" // for get_texture, Texture

ParticleDB* particle_db_ptr()
Expand Down Expand Up @@ -103,7 +105,7 @@ const Particle EmittedParticlesInfo::operator[](const size_type idx) const
};
}

ParticleDB* get_particle_type(uint32_t id)
ParticleDB* get_particle_type(PARTICLEEMITTER id)
{
static std::unordered_map<uint32_t, ParticleDB*> mapping = {};
if (mapping.size() == 0)
Expand Down Expand Up @@ -150,3 +152,78 @@ const std::vector<ParticleEmitter>& list_particles()
}
return particles;
}

ParticleDB::ParticleDB(PARTICLEEMITTER particle_id)
: ParticleDB(*get_particle_type(particle_id)){};

ParticleEmitterInfo* generate_world_particles(PARTICLEEMITTER particle_emitter_id, uint32_t uid)
{
static size_t offset = get_address("generate_world_particles");

if (offset != 0)
{
auto entity = get_entity_ptr(uid);
if (entity != nullptr)
{
auto state = get_state_ptr();
typedef ParticleEmitterInfo* generate_particles_func(custom_vector<ParticleEmitterInfo*>*, uint32_t, Entity*);
static generate_particles_func* gpf = (generate_particles_func*)(offset);
return gpf(state->particle_emitters, particle_emitter_id, entity);
}
}
return nullptr;
}

ParticleEmitterInfo* generate_screen_particles(PARTICLEEMITTER particle_emitter_id, float x, float y)
{
static size_t offset = get_address("generate_screen_particles");

if (offset != 0)
{
typedef ParticleEmitterInfo* generate_particles_func(uint32_t, float, float, size_t);
static generate_particles_func* gpf = (generate_particles_func*)(offset);
return gpf(particle_emitter_id, x, y, 0);
}
return nullptr;
}

void advance_screen_particles(ParticleEmitterInfo* particle_emitter)
{
static size_t offset = get_address("advance_screen_particles");

if (offset != 0)
{
typedef void advance_particles_func(ParticleEmitterInfo*);
static advance_particles_func* apf = (advance_particles_func*)(offset);
apf(particle_emitter);
}
}

void render_screen_particles(ParticleEmitterInfo* particle_emitter)
{
static size_t offset = get_address("render_screen_particles");

if (offset != 0)
{
typedef void render_particles_func(ParticleEmitterInfo*, size_t, size_t, size_t);
static render_particles_func* rpf = (render_particles_func*)(offset);
rpf(particle_emitter, 0, 0, 0);
}
}

void extinguish_particles(ParticleEmitterInfo* particle_emitter)
{
// removing from state only applies to world emitters, but it just won't find the screen one in the vector, so no big deal
auto state = get_state_ptr();
std::erase(*state->particle_emitters, particle_emitter);

using generic_free_func = void(void*);
static generic_free_func* generic_free = (generic_free_func*)get_address("generic_free");

if (particle_emitter != nullptr)
{
generic_free(particle_emitter->emitted_particles.memory);
generic_free(particle_emitter->emitted_particles_back_layer.memory);
generic_free(particle_emitter);
}
}
37 changes: 23 additions & 14 deletions src/game_api/particles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

struct Texture;

using PARTICLEEMITTER = uint32_t;

struct ParticleDB
{
uint32_t id;
PARTICLEEMITTER id;
int32_t spawn_count_min; // minimum amount of particles to spawn in an iteration, actual value is random between this value and spawn_count (-1 = no lower bound, uses spawn_count)
uint32_t spawn_count; // total amount of particles to spawn for 1 iteration (check with PETTING_PET or MOUNT_TAMED, amount of hearts shown)
int32_t lifespan_min; // minimum lifespan of a particle, actual value is random between this value and lifespan (-1 = no lower bound, uses lifespan)
Expand Down Expand Up @@ -66,6 +68,9 @@ struct ParticleDB
uint8_t unknown41;
uint32_t unknown42;

ParticleDB(const ParticleDB& other) = default;
ParticleDB(const PARTICLEEMITTER particle_id);

std::uint64_t get_texture();
bool set_texture(std::uint32_t texture_id);
};
Expand Down Expand Up @@ -104,8 +109,8 @@ struct EmittedParticlesInfo
void* memory;
uint16_t* max_lifetimes;
uint16_t* lifetimes;
size_t unknown7;
size_t unknown8;
float* unknown7;
float* unknown8;
float* x_positions;
float* y_positions;
float* unknown_x_positions;
Expand All @@ -115,12 +120,12 @@ struct EmittedParticlesInfo
float* heights;
float* x_velocities;
float* y_velocities;
size_t unknown18;
size_t unknown19;
size_t unknown20;
size_t unknown21;
size_t unknown22;
size_t unknown23;
uint8_t* unknown18;
uint8_t* unknown19;
uint8_t* unknown20;
uint8_t* unknown21;
uint8_t* unknown22;
uint8_t* unknown23;

template <class T>
class IteratorImpl : public neo::iterator_facade<IteratorImpl<T>>
Expand Down Expand Up @@ -200,10 +205,9 @@ struct ParticleEmitterInfo
float offset_x;
float offset_y;

uint8_t unknown54a; // layer?
uint8_t unknown54b;
uint8_t unknown54c;
uint8_t unknown54d;
uint8_t layer;
uint8_t draw_depth;
uint8_t padding_probably[2];
float unknown55;
uint32_t unknown56;
uint32_t total_particles;
Expand All @@ -212,5 +216,10 @@ struct ParticleEmitterInfo
uint32_t unknown60;
};

ParticleDB* get_particle_type(uint32_t id);
ParticleDB* get_particle_type(PARTICLEEMITTER id);
const std::vector<ParticleEmitter>& list_particles();
ParticleEmitterInfo* generate_world_particles(PARTICLEEMITTER particle_emitter_id, uint32_t uid);
ParticleEmitterInfo* generate_screen_particles(PARTICLEEMITTER particle_emitter_id, float x, float y);
void advance_screen_particles(ParticleEmitterInfo* particle_emitter);
void render_screen_particles(ParticleEmitterInfo* particle_emitter);
void extinguish_particles(ParticleEmitterInfo* particle_emitter);
72 changes: 0 additions & 72 deletions src/game_api/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,78 +792,6 @@ bool is_inside_shop_zone(float x, float y, LAYER layer)
return false;
}

ParticleEmitterInfo* generate_world_particles(uint32_t particle_emitter_id, uint32_t uid)
{
static size_t offset = get_address("generate_world_particles");

if (offset != 0)
{
auto entity = get_entity_ptr(uid);
if (entity != nullptr)
{
auto state = get_state_ptr();
typedef ParticleEmitterInfo* generate_particles_func(custom_vector<ParticleEmitterInfo*>*, uint32_t, Entity*);
static generate_particles_func* gpf = (generate_particles_func*)(offset);
return gpf(state->particle_emitters, particle_emitter_id, entity);
}
}
return nullptr;
}

ParticleEmitterInfo* generate_screen_particles(uint32_t particle_emitter_id, float x, float y)
{
static size_t offset = get_address("generate_screen_particles");

if (offset != 0)
{
typedef ParticleEmitterInfo* generate_particles_func(uint32_t, float, float, size_t);
static generate_particles_func* gpf = (generate_particles_func*)(offset);
return gpf(particle_emitter_id, x, y, 0);
}
return nullptr;
}

void advance_screen_particles(ParticleEmitterInfo* particle_emitter)
{
static size_t offset = get_address("advance_screen_particles");

if (offset != 0)
{
typedef void advance_particles_func(ParticleEmitterInfo*);
static advance_particles_func* apf = (advance_particles_func*)(offset);
apf(particle_emitter);
}
}

void render_screen_particles(ParticleEmitterInfo* particle_emitter)
{
static size_t offset = get_address("render_screen_particles");

if (offset != 0)
{
typedef void render_particles_func(ParticleEmitterInfo*, size_t, size_t, size_t);
static render_particles_func* rpf = (render_particles_func*)(offset);
rpf(particle_emitter, 0, 0, 0);
}
}

void extinguish_particles(ParticleEmitterInfo* particle_emitter)
{
// removing from state only applies to world emitters, but it just won't find the screen one in the vector, so no big deal
auto state = get_state_ptr();
std::erase(*state->particle_emitters, particle_emitter);

using generic_free_func = void(void*);
static generic_free_func* generic_free = (generic_free_func*)get_address("generic_free");

if (particle_emitter != nullptr)
{
generic_free(particle_emitter->emitted_particles.memory);
generic_free(particle_emitter->emitted_particles_back_layer.memory);
generic_free(particle_emitter);
}
}

void set_journal_enabled(bool b)
{
get_journal_enabled() = b;
Expand Down
5 changes: 0 additions & 5 deletions src/game_api/rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ void force_olmec_phase_0(bool b);
void set_ghost_spawn_times(uint32_t normal = 10800, uint32_t cursed = 9000);
void set_time_ghost_enabled(bool b);
void set_time_jelly_enabled(bool b);
ParticleEmitterInfo* generate_world_particles(uint32_t particle_emitter_id, uint32_t uid);
ParticleEmitterInfo* generate_screen_particles(uint32_t particle_emitter_id, float x, float y);
void advance_screen_particles(ParticleEmitterInfo* particle_emitter);
void render_screen_particles(ParticleEmitterInfo* particle_emitter);
void extinguish_particles(ParticleEmitterInfo* particle_emitter);
void set_journal_enabled(bool b);
void set_camp_camera_bounds_enabled(bool b);
void set_explosion_mask(int32_t mask);
Expand Down
7 changes: 7 additions & 0 deletions src/game_api/script/usertypes/particles_lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void register_usertypes(sol::state& lua)

/// Used in ParticleDB, [get_particle_type](#get_particle_type)
auto particledb_type = lua.new_usertype<ParticleDB>("ParticleDB");
particledb_type["new"] = sol::constructors<ParticleDB(ParticleDB&), ParticleDB(PARTICLEEMITTER)>();
particledb_type["id"] = &ParticleDB::id;
particledb_type["spawn_count_min"] = &ParticleDB::spawn_count_min;
particledb_type["spawn_count"] = &ParticleDB::spawn_count;
Expand Down Expand Up @@ -82,6 +83,8 @@ void register_usertypes(sol::state& lua)
"ParticleEmitterInfo",
"particle_type",
&ParticleEmitterInfo::particle_type,
"particle_type2",
&ParticleEmitterInfo::particle_type2,
"particle_count",
sol::property([](ParticleEmitterInfo& e) -> uint32_t
{ return e.emitted_particles.particle_count; }),
Expand All @@ -98,6 +101,10 @@ void register_usertypes(sol::state& lua)
&ParticleEmitterInfo::offset_x,
"offset_y",
&ParticleEmitterInfo::offset_y,
"layer",
&ParticleEmitterInfo::layer,
"draw_depth",
&ParticleEmitterInfo::draw_depth,
"emitted_particles",
&ParticleEmitterInfo::emitted_particles,
"emitted_particles_back_layer",
Expand Down

0 comments on commit c99216a

Please sign in to comment.