This commit is contained in:
Gaël committed 2026-10-19 20:59:15 +02:00
commit 87bff164f1
416 files changed
+279512

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
#pragma once
// The entity/component part of Noita's Lua API, expressed as an interface the game world implements.
// LuaHost forwards EntityGetFirstComponent, ComponentGetValue2, EntityLoad, EntityKill, ... to it.
#include <map>
#include <string>
#include <vector>
#include "entity/spawn_comp.h"
namespace ng {
// A Lua value crossing the boundary.
struct LVal {
enum class T { Nil, Bool, Num, Str } t = T::Nil;
bool b = false;
double n = 0;
std::string s;
static LVal nil() { return {}; }
static LVal boolean(bool v) { LVal r; r.t = T::Bool; r.b = v; return r; }
static LVal number(double v) { LVal r; r.t = T::Num; r.n = v; return r; }
static LVal string(std::string v) { LVal r; r.t = T::Str; r.s = std::move(v); return r; }
};
class IEntityWorld {
public:
virtual ~IEntityWorld() = default;
// ---- entities ----
virtual int load(const std::string& path, double x, double y) = 0; // 0 on failure
virtual int load_with(const std::string& path, double x, double y, const std::vector<SpawnComp>& extra) { (void)extra; return load(path, x, y); } // the same with components merged in at the spawn ("=Type" merges into the first of that type)
virtual void load_to_entity(const std::string& path, int entity) = 0; // EntityLoadToEntity: the file's components are added to the entity (not its tags, not its children)
virtual void kill(int id) = 0;
virtual void physics_init(int /*id*/) {} // PhysicsBody2InitFromComponents
virtual bool alive(int id) = 0;
virtual bool get_transform(int id, double& x, double& y, double& rot, double& sx, double& sy) = 0;
virtual void set_transform(int id, double x, double y, double rot, double sx, double sy) = 0;
virtual std::string get_name(int id) = 0;
virtual void set_name(int id, const std::string& name) = 0;
virtual std::string get_filename(int id) = 0;
virtual bool has_tag(int id, const std::string& tag) = 0;
virtual void add_tag(int id, const std::string& tag) = 0;
virtual void remove_tag(int id, const std::string& tag) = 0;
virtual std::string get_tags(int id) = 0; // comma separated
virtual std::vector<int> with_tag(const std::string& tag) = 0; // empty tag = all
virtual std::vector<int> in_radius(double x, double y, double r, const std::string& tag) = 0;
virtual void script_query(bool on) { (void)on; } // a Lua query follows (with_tag / in_radius): the GPU-only projectiles get their twins first
virtual int parent(int id) = 0;
virtual std::vector<int> children(int id) = 0;
virtual void add_child(int parent, int child) = 0;
// A spell card inside a wand (AddGunAction / AddGunActionPermanent): a hidden child entity carrying the action id.
virtual int add_gun_action(int wand, const std::string& action_id, bool permanent) = 0;
// ---- components ----
virtual std::vector<int> components(int entity, const std::string& type, const std::string& tag, bool include_disabled) = 0;
virtual int add_component(int entity, const std::string& type, const std::map<std::string, std::string>& attrs) = 0;
virtual void remove_component(int comp) = 0;
virtual void set_component_enabled(int comp, bool enabled) = 0;
virtual bool component_enabled(int comp) = 0;
virtual std::string component_type(int comp) = 0;
virtual int component_entity(int comp) = 0;
virtual bool comp_has_tag(int comp, const std::string& tag) = 0;
virtual LVal get_value(int comp, const std::string& key, bool typed) = 0; // nil if the key is unknown
virtual void set_value(int comp, const std::string& key, const LVal& v) = 0;
// ---- context of the running script ----
virtual int updated_entity() = 0;
virtual int updated_component() = 0;
virtual int frame() = 0;
virtual std::vector<int> game_effect_components(int entity, const std::string& effect) { (void)entity; (void)effect; return {}; } // GameEffectComponents of the entity and its children (empty name = all)
virtual int load_game_effect(int entity, const std::string& effect, bool always_new, int& effect_entity) { (void)entity; (void)effect; (void)always_new; effect_entity = 0; return 0; } // GetGameEffectLoadTo: the component (and entity) of the effect on the entity, loaded when missing
virtual int load_game_effect_file(int entity, const std::string& file) { (void)entity; (void)file; return 0; } // LoadGameEffectEntityTo
virtual void shoot_projectile(int shooter, double x, double y, double tx, double ty, int entity, bool send_message = true) { (void)shooter; (void)x; (void)y; (void)tx; (void)ty; (void)entity; (void)send_message; } // GameShootProjectile
virtual void play_sound(const std::string& bank, const std::string& event, double x, double y) { (void)bank; (void)event; (void)x; (void)y; } // GamePlaySound
virtual void physics_remove_joints(double x0, double y0, double x1, double y1) { (void)x0; (void)y0; (void)x1; (void)y1; } // PhysicsRemoveJoints
virtual void screenshake(double amount, double x, double y) { (void)amount; (void)x; (void)y; } // GameScreenshake
virtual void convert_material_everywhere(int from, int to) { (void)from; (void)to; } // ConvertMaterialEverywhere (fungal shifts)
virtual void entity_play_sound(int entity, const std::string& name) { (void)entity; (void)name; } // GameEntityPlaySound: through every AudioComponent of the entity
virtual void entity_play_sound_loop(int entity, const std::string& tag, double intensity, double intensity2) { (void)entity; (void)tag; (void)intensity; (void)intensity2; } // GameEntityPlaySoundLoop
// EntityInflictDamage (007b4030 -> 00ab9740 -> TakeDamage_Impl 00ab9a90): damage of a type (a DAMAGE_* name) through the entity's enabled DamageModelComponent; the world position defaults to the entity's
virtual void inflict_damage(int entity, double amount, const std::string& type, const std::string& description, const std::string& ragdoll_fx, double impulse_x, double impulse_y, int responsible, double world_x, double world_y, double knockback) { (void)entity; (void)amount; (void)type; (void)description; (void)ragdoll_fx; (void)impulse_x; (void)impulse_y; (void)responsible; (void)world_x; (void)world_y; (void)knockback; }
virtual std::string biome_name(double x, double y) { (void)x; (void)y; return "_EMPTY_"; } // BiomeMapGetName: "$biome_coalmine"...
virtual int world_state_entity() = 0;
virtual void remove_from_parent(int id) { (void)id; } // EntityRemoveFromParent
virtual bool camera_bounds(double& x, double& y, double& w, double& h) { (void)x; (void)y; (void)w; (void)h; return false; } // GameGetCameraBounds / GameGetCameraPos
virtual void regen_item_actions(int player) { (void)player; } // GameRegenItemActionsInPlayer: every spell the player carries has its uses back
virtual int create_entity(const std::string& name) { (void)name; return 0; } // EntityCreateNew: an entity without components
virtual void comp_add_tag(int comp, const std::string& tag) { (void)comp; (void)tag; } // ComponentAddTag
virtual int herd_relation(int a, int b) { (void)a; (void)b; return 0; } // EntityGetHerdRelation
virtual int wand_capacity(int wand) { (void)wand; return 0; } // EntityGetWandCapacity: the slots without the always-cast spells
virtual void print(const std::string& title, const std::string& text, bool important) = 0;
virtual void physics_force(int entity, double fx, double fy) { (void)entity; (void)fx; (void)fy; } // PhysicsApplyForce
struct BodyInfo { int entity = 0; double mass = 1, x = 0, y = 0, vx = 0, vy = 0, angular = 0; }; // a rigid body: mass (kg), position (pixels), velocity (pixels per second)
virtual std::vector<BodyInfo> bodies_in_area(double x0, double y0, double x1, double y1) { (void)x0; (void)y0; (void)x1; (void)y1; return {}; } // PhysicsApplyForceOnArea
virtual void physics_area_force(int entity, double fx, double fy) { (void)entity; (void)fx; (void)fy; } // the force of PhysicsApplyForceOnArea's callback (newtons on the body)
};
} // namespace ng