diff --git a/assets/attacks.json b/assets/attacks.json new file mode 100644 index 0000000..8fee190 --- /dev/null +++ b/assets/attacks.json @@ -0,0 +1,28 @@ +{ + "MAGICK_FIRE": { + "animation": "burning_animation", + "shader": "flame", + "components": [ + {"_type": "Sprite", "name": "burning_animation", "scale": 1.0}, + {"_type": "LightSource", "strength": 25, "radius": 2.0}, + {"_type": "Temporary", "is": true} + ] + }, + "MAGICK_LIGHTNING": { + "animation": "lightning_animation", + "shader": "lightning", + "components": [ + {"_type": "Sprite", "name": "lightning_animation", "scale": 1.0}, + {"_type": "LightSource", "strength": 35, "radius": 2.5}, + {"_type": "Temporary", "is": true} + ] + }, + "PHYSICAL_NONE": { + "animation": "lightning_animation", + "shader": "flame", + "components": [ + {"_type": "Sprite", "name": "lightning_animation", "scale": 1.0}, + {"_type": "Temporary", "is": true} + ] + } +} diff --git a/assets/enemies.json b/assets/enemies.json index b241fdd..38c80cf 100644 --- a/assets/enemies.json +++ b/assets/enemies.json @@ -6,12 +6,12 @@ "foreground": "enemies/fg:player", "background": "color:transparent" }, - {"_type": "Combat", "hp": 200, "max_hp": 200, "ap": 0, "max_ap": 12, "ap_delta": 6, "damage": 50, "dead": false, "attack_rating": 0.60, "toughness_rating": 0.0}, + {"_type": "Combat", "hp": 200, "max_hp": 200, "ap": 0, "max_ap": 12, "ap_delta": 6, "damage": 500, "dead": false, "attack_rating": 1.0, "toughness_rating": 0.0}, {"_type": "Motion", "dx": 0, "dy": 0, "random": false}, {"_type": "Collision", "has": true}, {"_type": "EnemyConfig", "ai_script": "Host::actions", "ai_start_name": "Host::initial_state", "ai_goal_name": "Host::final_state"}, {"_type": "Personality", "hearing_distance": 5, "tough": false}, - {"_type": "LightSource", "strength": 35, "radius": 2.0} + {"_type": "LightSource", "strength": 20, "radius": 1.0} ] }, "GOLD_SAVIOR": { diff --git a/src/game/components.cpp b/src/game/components.cpp index 42304fe..5582624 100644 --- a/src/game/components.cpp +++ b/src/game/components.cpp @@ -30,6 +30,7 @@ namespace components { components::enroll(MAP); components::enroll(MAP); components::enroll(MAP); + components::enroll(MAP); MAP_configured = true; } } diff --git a/src/game/components.hpp b/src/game/components.hpp index d4c8329..7f57067 100644 --- a/src/game/components.hpp +++ b/src/game/components.hpp @@ -74,6 +74,7 @@ namespace components { settings::Config rituals; settings::Config stories; settings::Config scenes; + settings::Config attacks; }; struct Personality { @@ -174,6 +175,7 @@ namespace components { ENROLL_COMPONENT(Storyboard, image, audio, layout, beats); ENROLL_COMPONENT(Sound, attack, death); ENROLL_COMPONENT(Collision, has); + ENROLL_COMPONENT(Temporary, is); template COMPONENT convert(nlohmann::json &data) { COMPONENT result; diff --git a/src/game/level.cpp b/src/game/level.cpp index 8c0a9b5..f6ee8ae 100644 --- a/src/game/level.cpp +++ b/src/game/level.cpp @@ -130,6 +130,7 @@ namespace GameDB { } void load_configs(DinkyECS::World &world) { + // TODO: Could have a simple meta-config file that loads these.... world.set_the({ settings::get("config"), settings::get("enemies"), @@ -139,7 +140,8 @@ namespace GameDB { settings::get("bosses"), settings::get("rituals"), settings::get("stories"), - settings::get("scenes") + settings::get("scenes"), + settings::get("attacks") }); } } diff --git a/src/game/rituals.cpp b/src/game/rituals.cpp index 7833923..000e923 100644 --- a/src/game/rituals.cpp +++ b/src/game/rituals.cpp @@ -1,6 +1,7 @@ #include "game/rituals.hpp" #include "ai/ai_debug.hpp" #include "ai/ai.hpp" +#include namespace ritual { Engine::Engine(std::string config_path) : @@ -129,6 +130,12 @@ namespace ritual { fmt::println("\n"); } + std::string Action::name() { + return fmt::format("{}_{}", + magic_enum::enum_name(kind), + magic_enum::enum_name(element)); + } + Action& Belt::get(int index) { return equipped.at(index); } diff --git a/src/game/rituals.hpp b/src/game/rituals.hpp index cbbbf26..a54680a 100644 --- a/src/game/rituals.hpp +++ b/src/game/rituals.hpp @@ -49,6 +49,7 @@ namespace ritual { std::vector names; void dump(); + std::string name(); }; struct Engine { diff --git a/src/game/systems.cpp b/src/game/systems.cpp index 2d35fc7..93c152d 100644 --- a/src/game/systems.cpp +++ b/src/game/systems.cpp @@ -241,7 +241,7 @@ void System::death() { } } -void System::combat(int attack_id) { +void System::combat(int belt_id) { auto& level = GameDB::current_level(); auto& collider = *level.collision; auto& world = *level.world; @@ -285,8 +285,9 @@ void System::combat(int attack_id) { .enemy_did=0 }; + // TODO: Need a "miss" animation/sound if(result.player_did > 0) { - spawn_attack(world, attack_id, enemy.entity); + spawn_attack(world, belt_id, enemy.entity); } if(enemy_action == "kill_enemy") { @@ -666,31 +667,34 @@ void System::clear_attack() { } } -void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) { +void System::spawn_attack(World& world, int belt_id, DinkyECS::Entity enemy) { + auto& config = world.get_the().attacks; + using enum ritual::Element; // for FIRE vs LIGHTNING auto& the_belt = world.get_the(); - dbc::check(the_belt.has(attack_id), "STOP passing invalid attack IDs to the system."); + dbc::check(the_belt.has(belt_id), "STOP passing invalid attack IDs to the system."); - auto& ritual = the_belt.get(attack_id); + auto& ritual = the_belt.get(belt_id); + fmt::println("RITUAL NAME: {}", ritual.name()); - auto effect = ritual.element == FIRE ? "burning_animation" : "lightning_animation"; + auto attack_id = world.entity(); + auto& attack_config = config[ritual.name()]; - auto effect_id = world.entity(); - world.set(effect_id, {effect, 1.0f}); - world.set(effect_id, {true}); + components::configure_entity(world, attack_id, attack_config["components"]); - auto shader = shaders::get(ritual.element == FIRE ? "flame" : "lightning"); - world.set(effect_id, {100, shader}); + auto shader = shaders::get(attack_config["shader"]); + world.set(attack_id, {100, shader}); // also add the same effect to the enemy world.set(enemy, {50, shader}); - auto anim = animation::load("assets/animation.json", effect); + auto anim = animation::load("assets/animation.json", attack_config["animation"]); anim.play(); - world.set(effect_id, anim); + world.set(attack_id, anim); - drop_item(effect_id); + //BUG: THIS IS BULLSHIT! Should have a generic place item thing. + drop_item(attack_id); } void System::init(Registry& reg) { diff --git a/src/game/systems.hpp b/src/game/systems.hpp index af15f06..f9a8bcd 100644 --- a/src/game/systems.hpp +++ b/src/game/systems.hpp @@ -25,7 +25,7 @@ namespace System { void drop_item(Entity item); void enemy_ai(); - void combat(int attack_id); + void combat(int belt_id); std::shared_ptr sprite_effect(Entity entity); void player_status(); @@ -70,7 +70,7 @@ namespace System { } void clear_attack(); - void spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy); + void spawn_attack(World& world, int belt_id, DinkyECS::Entity enemy); void init(Registry& reg); void restart(); } diff --git a/src/gui/fsm.cpp b/src/gui/fsm.cpp index 058b7a9..6904087 100644 --- a/src/gui/fsm.cpp +++ b/src/gui/fsm.cpp @@ -1,4 +1,3 @@ -#define FSM_DEBUG 1 #include "gui/fsm.hpp" #include #include @@ -14,6 +13,7 @@ #include "gui/guecstra.hpp" #include "game/level.hpp" #include "boss/system.hpp" +#include namespace gui { using namespace components; @@ -60,8 +60,6 @@ namespace gui { $map_ui.init(); $map_ui.log(L"Welcome to the game!"); - run_systems(); - state(State::IDLE); } @@ -69,7 +67,6 @@ namespace gui { // this should be an optional that returns a point if(auto move_to = $main_ui.play_move()) { $systems.runMoving(*move_to); - run_systems(); $main_ui.dirty(); state(State::IDLE); } @@ -90,8 +87,6 @@ namespace gui { something_died(std::any_cast(data)); break; case TICK: - run_systems(); - if(!$main_ui.hands_playing()) { // run combat one more time state(State::IDLE); @@ -159,11 +154,7 @@ namespace gui { $map_open = !$map_open; break; case ATTACK: - $main_ui.play_hands(); - $main_ui.dirty(); - $systems.runCombat(0); - run_systems(); - $status_ui.update(); + play_attack(std::any_cast(data)); state(State::ATTACKING); break; case CLOSE: @@ -238,7 +229,6 @@ namespace gui { auto& sprite = world->get(entity); $main_ui.$rayview->update_sprite(entity, sprite); $main_ui.dirty(); - run_systems(); } void FSM::something_died(DinkyECS::Entity entity) { @@ -254,6 +244,13 @@ namespace gui { } } + void FSM::play_attack(int attack_id) { + $main_ui.play_hands(); + $main_ui.dirty(); + $systems.runCombat(attack_id); + $status_ui.update(); + } + void FSM::CUT_SCENE_PLAYING(Event ev, std::any data) { if($boss_scene->playing()) { if(ev == game::Event::MOUSE_CLICK) { @@ -404,22 +401,18 @@ namespace gui { } void FSM::update() { - if(in_state(State::BOSS_FIGHT)) { - $boss_fight->update(); - } else if(in_state(State::CUT_SCENE_PLAYING)) { - $boss_scene->update(); - } else { - // BUG: look at draw_gui for the update for here - } + $systems.runUpdate(); } void FSM::render() { $window.clear(); if(in_state(State::BOSS_FIGHT)) { + $boss_fight->update(); $boss_fight->render($window); // this clears any attack animations, like fire } else if(in_state(State::CUT_SCENE_PLAYING)) { + $boss_scene->update(); $boss_scene->render($window); } else { // this clears any attack animations, like fire @@ -431,10 +424,6 @@ namespace gui { $window.display(); } - void FSM::run_systems() { - $systems.runUpdate(); - } - bool FSM::active() { return !in_state(State::END); } @@ -487,7 +476,5 @@ namespace gui { $main_ui.update_level(); $loot_ui.update_level(); } - - run_systems(); } } diff --git a/src/gui/fsm.hpp b/src/gui/fsm.hpp index d8a208c..355f74d 100644 --- a/src/gui/fsm.hpp +++ b/src/gui/fsm.hpp @@ -74,7 +74,6 @@ namespace gui { void update(); void render(); bool active(); - void run_systems(); void handle_events(); void handle_boss_fight_events(); void next_level(bool bossfight); @@ -82,5 +81,6 @@ namespace gui { void take_screenshot(); void something_died(DinkyECS::Entity entity); void entity_spawned(DinkyECS::Entity entity); + void play_attack(int attack_id); }; }