#pragma once #include "config.hpp" #include "constants.hpp" #include "dinkyecs.hpp" #include "point.hpp" #include #include #include #include #include #include #include #include "easings.hpp" #include "json_mods.hpp" #include "goap.hpp" #include namespace combat { enum class BattleHostState; } namespace components { using std::string; using namespace nlohmann; struct CombatResult { DinkyECS::Entity attacker; combat::BattleHostState host_state; int player_did = 0; int enemy_did = 0; }; struct InventoryItem { int count; json data; }; struct SpriteEffect { int frames; std::shared_ptr effect; }; struct Temporary { bool is = true; }; struct Collision { bool has = true; }; struct Position { Point location{0,0}; Point aiming_at{0,0}; }; struct Motion { int dx; int dy; bool random=false; }; struct Tile { wchar_t display; std::string foreground; std::string background; }; struct GameConfig { settings::Config game; settings::Config enemies; settings::Config items; settings::Config tiles; settings::Config devices; settings::Config bosses; settings::Config rituals; settings::Config stories; }; struct Personality { int hearing_distance = 10; bool tough = true; }; struct EnemyConfig { std::string ai_script; std::string ai_start_name; std::string ai_goal_name; }; struct Curative { int hp = 10; }; struct Sprite { string name; float scale; }; struct AnimatedScene { std::string background; std::vector layout; json actors; json fixtures; }; struct Storyboard { std::string image; std::string audio; std::vector layout; std::vector> beats; }; struct Combat { int hp; int max_hp; int ap_delta; int max_ap; int damage; // everyone starts at 0 but ap_delta is added each round int ap = 0; /* 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; }; struct Sound { std::string attack; std::string death; }; struct Player { DinkyECS::Entity entity; }; template struct NameOf; using ReflFuncSignature = std::function; using ComponentMap = std::unordered_map; ENROLL_COMPONENT(Tile, display, foreground, background); ENROLL_COMPONENT(AnimatedScene, background, layout, actors, fixtures); ENROLL_COMPONENT(Sprite, name, scale); ENROLL_COMPONENT(Curative, hp); ENROLL_COMPONENT(LightSource, strength, radius); ENROLL_COMPONENT(Position, location.x, location.y); ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name); ENROLL_COMPONENT(Personality, hearing_distance, tough); ENROLL_COMPONENT(Motion, dx, dy, random); ENROLL_COMPONENT(Combat, hp, max_hp, ap_delta, max_ap, damage, dead); ENROLL_COMPONENT(Device, config, events); ENROLL_COMPONENT(Storyboard, image, audio, layout, beats); ENROLL_COMPONENT(Sound, attack, death); ENROLL_COMPONENT(Collision, has); 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 init(); void configure_entity(DinkyECS::World& world, DinkyECS::Entity ent, json& data); }