Had to refactor the GameDB to use a list of levels instead of a vector of levels. If you get a _reference_ to an element of a vector, and then resize the vector, you'll get a crash if the realoc moves the data buffer. Using a list is actually what we want.
This commit is contained in:
parent
bf8ce7e16b
commit
0456c73e4f
6 changed files with 53 additions and 37 deletions
|
|
@ -9,9 +9,11 @@ namespace boss {
|
||||||
$boss_id(boss_id),
|
$boss_id(boss_id),
|
||||||
$battle(System::create_battle($world, $boss_id)),
|
$battle(System::create_battle($world, $boss_id)),
|
||||||
$ui(world, boss_id, player_id),
|
$ui(world, boss_id, player_id),
|
||||||
$host(player_id),
|
$host(player_id)
|
||||||
$host_combat($world->get<components::Combat>(player_id))
|
|
||||||
{
|
{
|
||||||
|
$host_combat = $world->get_if<components::Combat>(player_id);
|
||||||
|
dbc::check($host_combat,
|
||||||
|
fmt::format("No combat for host with player_id={}", player_id));
|
||||||
$ui.init();
|
$ui.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +68,7 @@ namespace boss {
|
||||||
case ATTACK:
|
case ATTACK:
|
||||||
if($battle.player_request("kill_enemy")) {
|
if($battle.player_request("kill_enemy")) {
|
||||||
fmt::println("player requests kill_enemy {} vs. {}",
|
fmt::println("player requests kill_enemy {} vs. {}",
|
||||||
$host_combat.ap, $battle.player_pending_ap());
|
$host_combat->ap, $battle.player_pending_ap());
|
||||||
} else {
|
} else {
|
||||||
fmt::println("NO MORE ACTION!");
|
fmt::println("NO MORE ACTION!");
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +140,7 @@ namespace boss {
|
||||||
$ui.update_stats();
|
$ui.update_stats();
|
||||||
$battle.set($host, "tough_personality", false);
|
$battle.set($host, "tough_personality", false);
|
||||||
$battle.set($host, "have_healing", false);
|
$battle.set($host, "have_healing", false);
|
||||||
$battle.set($host, "health_good", $host_combat.hp > 100);
|
$battle.set($host, "health_good", $host_combat->hp > 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fight::render(sf::RenderWindow& window) {
|
void Fight::render(sf::RenderWindow& window) {
|
||||||
|
|
@ -175,7 +177,7 @@ namespace boss {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Fight::player_dead() {
|
bool Fight::player_dead() {
|
||||||
return $host_combat.hp <= 0;
|
return $host_combat->hp <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fight::init_fight() {
|
void Fight::init_fight() {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace boss {
|
||||||
boss::UI $ui;
|
boss::UI $ui;
|
||||||
sf::Vector2f mouse_pos{0,0};
|
sf::Vector2f mouse_pos{0,0};
|
||||||
Entity $host = NONE;
|
Entity $host = NONE;
|
||||||
components::Combat& $host_combat;
|
components::Combat* $host_combat = nullptr;
|
||||||
|
|
||||||
Fight(shared_ptr<World> world, Entity boss_id, Entity player_id);
|
Fight(shared_ptr<World> world, Entity boss_id, Entity player_id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,26 +29,31 @@ namespace boss {
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<boss::Fight> System::create_bossfight() {
|
shared_ptr<boss::Fight> System::create_bossfight() {
|
||||||
auto& level = GameDB::current_level();
|
// need to copy so we can clone it and keep things working, even
|
||||||
auto prev_world = GameDB::current_world();
|
// if we don't use things like map and lighting
|
||||||
dbc::check(prev_world != nullptr, "Starter world for boss fights can't be null.");
|
auto level = GameDB::current_level();
|
||||||
auto world = GameDB::clone_load_world(prev_world);
|
dbc::check(level.world != nullptr, "Starter world for boss fights can't be null.");
|
||||||
auto& config = prev_world->get_the<GameConfig>();
|
|
||||||
|
level.world = GameDB::clone_load_world(level.world);
|
||||||
|
|
||||||
|
auto& config = level.world->get_the<GameConfig>();
|
||||||
|
|
||||||
auto boss_names = config.bosses.keys();
|
auto boss_names = config.bosses.keys();
|
||||||
auto& level_name = boss_names[level.index % boss_names.size()];
|
auto& level_name = boss_names[level.index % boss_names.size()];
|
||||||
auto& boss_data = config.bosses[level_name];
|
auto& boss_data = config.bosses[level_name];
|
||||||
|
|
||||||
auto boss_id = world->entity();
|
auto boss_id = level.world->entity();
|
||||||
components::configure_entity(*world, boss_id, boss_data["components"]);
|
components::configure_entity(*level.world, boss_id, boss_data["components"]);
|
||||||
|
|
||||||
initialize_actor_ai(*world, boss_id);
|
initialize_actor_ai(*level.world, boss_id);
|
||||||
dbc::check(world->has<ai::EntityAI>(boss_id), "boss doesn't have an AI");
|
dbc::check(level.world->has<ai::EntityAI>(boss_id), "boss doesn't have an AI");
|
||||||
|
|
||||||
initialize_actor_ai(*world, level.player);
|
initialize_actor_ai(*level.world, level.player);
|
||||||
dbc::check(world->has<ai::EntityAI>(level.player), "player/host doesn't have an AI");
|
dbc::check(level.world->has<ai::EntityAI>(level.player), "player/host doesn't have an AI");
|
||||||
|
|
||||||
return make_shared<boss::Fight>(world, boss_id, level.player);
|
GameDB::register_level(level);
|
||||||
|
|
||||||
|
return make_shared<boss::Fight>(level.world, boss_id, level.player);
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleEngine System::create_battle(std::shared_ptr<DinkyECS::World> world, DinkyECS::Entity boss_id) {
|
BattleEngine System::create_battle(std::shared_ptr<DinkyECS::World> world, DinkyECS::Entity boss_id) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "components.hpp"
|
#include "components.hpp"
|
||||||
#include "rituals.hpp"
|
#include "rituals.hpp"
|
||||||
#include "textures.hpp"
|
#include "textures.hpp"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
using lighting::LightRender;
|
using lighting::LightRender;
|
||||||
using std::shared_ptr, std::make_shared;
|
using std::shared_ptr, std::make_shared;
|
||||||
|
|
@ -20,11 +21,11 @@ namespace GameDB {
|
||||||
using std::shared_ptr, std::string, std::make_shared;
|
using std::shared_ptr, std::string, std::make_shared;
|
||||||
|
|
||||||
struct LevelDB {
|
struct LevelDB {
|
||||||
std::vector<GameDB::Level> levels;
|
std::list<GameDB::Level> levels;
|
||||||
size_t current_level = 0;
|
size_t current_level = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_ptr<LevelDB> LDB;
|
shared_ptr<LevelDB> LDB = nullptr;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
LevelScaling scale_level() {
|
LevelScaling scale_level() {
|
||||||
|
|
@ -46,8 +47,18 @@ namespace GameDB {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void register_level(Level level) {
|
||||||
|
// size BEFORE push to get the correct index
|
||||||
|
level.index = LDB->levels.size();
|
||||||
|
|
||||||
size_t new_level(std::shared_ptr<DinkyECS::World> prev_world) {
|
LDB->levels.push_back(level);
|
||||||
|
|
||||||
|
dbc::check(level.index == LDB->levels.size() - 1, "Level index is not the same as LDB->levels.size() - 1, off by one error");
|
||||||
|
|
||||||
|
LDB->current_level = level.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_level(std::shared_ptr<DinkyECS::World> prev_world) {
|
||||||
dbc::check(initialized, "Forgot to call GameDB::init()");
|
dbc::check(initialized, "Forgot to call GameDB::init()");
|
||||||
auto world = clone_load_world(prev_world);
|
auto world = clone_load_world(prev_world);
|
||||||
|
|
||||||
|
|
@ -59,16 +70,16 @@ namespace GameDB {
|
||||||
WorldBuilder builder(*map, *collision);
|
WorldBuilder builder(*map, *collision);
|
||||||
builder.generate(*world);
|
builder.generate(*world);
|
||||||
|
|
||||||
size_t index = LDB->levels.size();
|
auto lights = make_shared<LightRender>(map->tiles());
|
||||||
|
|
||||||
auto player = world->get_the<Player>();
|
auto player = world->get_the<Player>();
|
||||||
|
|
||||||
LDB->levels.emplace_back(index, player.entity, map, world,
|
register_level({
|
||||||
make_shared<LightRender>(map->tiles()), collision);
|
.player=player.entity,
|
||||||
|
.map=map,
|
||||||
dbc::check(index == LDB->levels.size() - 1, "Level index is not the same as LDB->levels.size() - 1, off by one error");
|
.world=world,
|
||||||
|
.lights=lights,
|
||||||
return index;
|
.collision=collision});
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
|
@ -89,18 +100,15 @@ namespace GameDB {
|
||||||
|
|
||||||
Level& create_level() {
|
Level& create_level() {
|
||||||
dbc::check(initialized, "Forgot to call GameDB::init()");
|
dbc::check(initialized, "Forgot to call GameDB::init()");
|
||||||
dbc::check(LDB->current_level < LDB->levels.size(), "attempt to get next level when at end");
|
|
||||||
|
|
||||||
size_t level = new_level(current_world());
|
new_level(current_world());
|
||||||
dbc::check(level == LDB->current_level + 1, "new level index is wrong");
|
|
||||||
|
|
||||||
LDB->current_level++;
|
return LDB->levels.back();
|
||||||
return LDB->levels.at(LDB->current_level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Level ¤t_level() {
|
Level ¤t_level() {
|
||||||
dbc::check(initialized, "Forgot to call GameDB::init()");
|
dbc::check(initialized, "Forgot to call GameDB::init()");
|
||||||
return LDB->levels.at(LDB->current_level);
|
return LDB->levels.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
components::Position& player_position() {
|
components::Position& player_position() {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ namespace components {
|
||||||
|
|
||||||
namespace GameDB {
|
namespace GameDB {
|
||||||
struct Level {
|
struct Level {
|
||||||
size_t index;
|
size_t index = 0;
|
||||||
DinkyECS::Entity player;
|
DinkyECS::Entity player = DinkyECS::NONE;
|
||||||
std::shared_ptr<Map> map = nullptr;
|
std::shared_ptr<Map> map = nullptr;
|
||||||
std::shared_ptr<DinkyECS::World> world = nullptr;
|
std::shared_ptr<DinkyECS::World> world = nullptr;
|
||||||
std::shared_ptr<lighting::LightRender> lights = nullptr;
|
std::shared_ptr<lighting::LightRender> lights = nullptr;
|
||||||
|
|
@ -31,4 +31,5 @@ namespace GameDB {
|
||||||
|
|
||||||
std::shared_ptr<DinkyECS::World> clone_load_world(std::shared_ptr<DinkyECS::World> prev_world);
|
std::shared_ptr<DinkyECS::World> clone_load_world(std::shared_ptr<DinkyECS::World> prev_world);
|
||||||
void load_configs(DinkyECS::World &world);
|
void load_configs(DinkyECS::World &world);
|
||||||
|
void register_level(Level level);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ void System::combat(int attack_id) {
|
||||||
battle.plan();
|
battle.plan();
|
||||||
}
|
}
|
||||||
|
|
||||||
battle.dump();
|
// battle.dump();
|
||||||
|
|
||||||
while(auto act = battle.next()) {
|
while(auto act = battle.next()) {
|
||||||
auto [enemy, enemy_action, cost, host_state] = *act;
|
auto [enemy, enemy_action, cost, host_state] = *act;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue