#include "game_level.hpp" #include "components.hpp" #include "worldbuilder.hpp" #include "constants.hpp" #include "save.hpp" #include "systems.hpp" #include "components.hpp" #include "rituals.hpp" using lighting::LightRender; using std::shared_ptr, std::make_shared; using namespace components; struct LevelScaling { int map_width=20; int map_height=20; }; class LevelManager { public: std::vector $levels; size_t $current_level = 0; LevelManager(); shared_ptr create_bossfight(shared_ptr prev_world); size_t create_level(shared_ptr prev_world = nullptr); GameLevel &next(); GameLevel &previous(); GameLevel ¤t(); size_t current_index() { return $current_level; } GameLevel &get(size_t index); LevelScaling scale_level(); DinkyECS::Entity spawn_enemy(const std::string& named); }; LevelManager::LevelManager() { create_level(); } LevelScaling LevelManager::scale_level() { return { INITIAL_MAP_W + int($current_level * 2), INITIAL_MAP_H + int($current_level * 2) }; } inline shared_ptr clone_load_world(shared_ptr prev_world) { auto world = make_shared(); if(prev_world != nullptr) { prev_world->clone_into(*world); } else { save::load_configs(*world); } return world; } shared_ptr LevelManager::create_bossfight(shared_ptr prev_world) { dbc::check(prev_world != nullptr, "Starter world for boss fights can't be null."); auto world = clone_load_world(prev_world); auto& config = prev_world->get_the(); // BUG: the jank is too strong here auto boss_names = config.bosses.keys(); auto& level_name = boss_names[$current_level % boss_names.size()]; auto& boss_data = config.bosses[level_name]; auto boss_id = world->entity(); components::configure_entity(*world, boss_id, boss_data["components"]); return make_shared(world, boss_id); } DinkyECS::Entity LevelManager::spawn_enemy(const std::string& named) { (void)named; dbc::log("THIS FUNCTION NEEDS A REWRITE"); return 0; } size_t LevelManager::create_level(shared_ptr prev_world) { auto world = clone_load_world(prev_world); auto scaling = scale_level(); auto map = make_shared(scaling.map_width, scaling.map_height); auto collision = std::make_shared(); WorldBuilder builder(*map, *collision); builder.generate(*world); size_t index = $levels.size(); auto player = world->get_the(); $levels.emplace_back(index, player.entity, map, world, make_shared(map->tiles()), collision); dbc::check(index == $levels.size() - 1, "Level index is not the same as $levels.size() - 1, off by one error"); return index; } GameLevel &LevelManager::next() { dbc::check($current_level < $levels.size(), "attempt to get next level when at end"); $current_level++; return $levels.at($current_level); } GameLevel &LevelManager::previous() { dbc::check($current_level > 0, "attempt to go to previous level when at 0"); $current_level--; return $levels.at($current_level); } GameLevel &LevelManager::current() { return $levels.at($current_level); } GameLevel &LevelManager::get(size_t index) { return $levels.at(index); } namespace Game { using std::shared_ptr, std::string, std::make_shared; shared_ptr LEVELS; bool initialized = false; void init() { if(!initialized) { LEVELS = make_shared(); initialized = true; } } shared_ptr current_world() { dbc::check(initialized, "Forgot to call Game::init()"); return current().world; } shared_ptr create_bossfight() { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->create_bossfight(current_world()); } GameLevel& create_level() { dbc::check(initialized, "Forgot to call Game::init()"); LEVELS->create_level(current_world()); return next(); } GameLevel &next() { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->next(); } GameLevel &previous() { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->previous(); } GameLevel ¤t() { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->current(); } size_t current_index() { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->current_index(); } GameLevel &get(size_t index) { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->get(index); } DinkyECS::Entity spawn_enemy(const std::string& named) { dbc::check(initialized, "Forgot to call Game::init()"); return LEVELS->spawn_enemy(named); } components::Position& player_position() { dbc::check(initialized, "Forgot to call Game::init()"); auto world = current_world(); auto& player = world->get_the(); return world->get(player.entity); } DinkyECS::Entity the_player() { dbc::check(initialized, "Forgot to call Game::init()"); return current().player; } }