#pragma once #include "components.hpp" #include "config.hpp" #include "constants.hpp" #include "dinkyecs.hpp" #include "point.hpp" #include #include #include #include #include #include "easings.hpp" #define ENROLL_COMPONENT(COMPONENT, ...) \ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \ template <> struct NameOf { \ static constexpr const char *name = #COMPONENT; \ }; namespace components { using namespace nlohmann; struct Position { Point location; }; struct Motion { int dx; int dy; bool random=false; }; struct Loot { int amount; }; struct Tile { std::string display; std::array foreground; std::array background; }; struct GameConfig { Config game; Config enemies; Config items; Config tiles; Config devices; Config bosses; }; struct EnemyConfig { int hearing_distance = 10; }; struct Debug { bool PATHS=false; bool LIGHT=false; bool FPS=false; }; struct Weapon { int damage = 0; }; struct Curative { int hp = 10; }; struct Combat { int hp; int max_hp; int damage; /* NOTE: This is used to _mark_ entities as dead, to detect ones that have just died. Don't make attack automatically set it.*/ bool dead = false; int attack(Combat &target); }; struct LightSource { int strength = 0; float radius = 1.0f; }; struct Device { json config; std::vector events; void configure_events(std::vector &event_names); }; struct Sprite { string name; int width; int height; }; struct Sound { std::string attack; std::string death; }; struct Animation { float scale = 0.0f; bool simple = true; int frames = 10; float speed = 0.3f; int current = 0; bool playing = false; float subframe = 0; ease::Style easing = ease::IN_OUT_BACK; float ease_rate = 0.5f; int texture_width = TEXTURE_WIDTH; void play(); float twitching(); void step(sf::Vector2f& scale_out, sf::IntRect& rect_out); }; template struct NameOf; ENROLL_COMPONENT(Tile, display, foreground, background); ENROLL_COMPONENT(Sprite, name, width, height); ENROLL_COMPONENT(Curative, hp); ENROLL_COMPONENT(LightSource, strength, radius); ENROLL_COMPONENT(Weapon, damage); ENROLL_COMPONENT(Loot, amount); ENROLL_COMPONENT(Position, location.x, location.y); ENROLL_COMPONENT(EnemyConfig, hearing_distance); ENROLL_COMPONENT(Motion, dx, dy, random); ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead); ENROLL_COMPONENT(Device, config, events); ENROLL_COMPONENT(Animation, scale, simple, frames, speed, easing, ease_rate); ENROLL_COMPONENT(Sound, attack, death); using ReflFuncSignature = std::function; using ComponentMap = std::unordered_map; struct Player { DinkyECS::Entity entity; }; template COMPONENT convert(nlohmann::json &data) { COMPONENT result; from_json(data, result); return result; } template COMPONENT get(nlohmann::json &data) { for (auto &i : data["components"]) { if(i["_type"] == NameOf::name) { return convert(i); } } return {}; } template void enroll(ComponentMap &m) { m[NameOf::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) { COMPONENT c; from_json(j, c); world.set(ent, c); }; } void configure(ComponentMap& component_map); void configure_entity(const ComponentMap& component_map, DinkyECS::World& world, DinkyECS::Entity ent, json& data); }