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:
Zed A. Shaw 2025-12-16 11:40:29 -05:00
parent bf8ce7e16b
commit 0456c73e4f
6 changed files with 53 additions and 37 deletions

View file

@ -9,9 +9,11 @@ namespace boss {
$boss_id(boss_id),
$battle(System::create_battle($world, $boss_id)),
$ui(world, boss_id, player_id),
$host(player_id),
$host_combat($world->get<components::Combat>(player_id))
$host(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();
}
@ -66,7 +68,7 @@ namespace boss {
case ATTACK:
if($battle.player_request("kill_enemy")) {
fmt::println("player requests kill_enemy {} vs. {}",
$host_combat.ap, $battle.player_pending_ap());
$host_combat->ap, $battle.player_pending_ap());
} else {
fmt::println("NO MORE ACTION!");
}
@ -138,7 +140,7 @@ namespace boss {
$ui.update_stats();
$battle.set($host, "tough_personality", 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) {
@ -175,7 +177,7 @@ namespace boss {
}
bool Fight::player_dead() {
return $host_combat.hp <= 0;
return $host_combat->hp <= 0;
}
void Fight::init_fight() {

View file

@ -28,7 +28,7 @@ namespace boss {
boss::UI $ui;
sf::Vector2f mouse_pos{0,0};
Entity $host = NONE;
components::Combat& $host_combat;
components::Combat* $host_combat = nullptr;
Fight(shared_ptr<World> world, Entity boss_id, Entity player_id);

View file

@ -29,26 +29,31 @@ namespace boss {
}
shared_ptr<boss::Fight> System::create_bossfight() {
auto& level = GameDB::current_level();
auto prev_world = GameDB::current_world();
dbc::check(prev_world != nullptr, "Starter world for boss fights can't be null.");
auto world = GameDB::clone_load_world(prev_world);
auto& config = prev_world->get_the<GameConfig>();
// need to copy so we can clone it and keep things working, even
// if we don't use things like map and lighting
auto level = GameDB::current_level();
dbc::check(level.world != nullptr, "Starter world for boss fights can't be null.");
level.world = GameDB::clone_load_world(level.world);
auto& config = level.world->get_the<GameConfig>();
auto boss_names = config.bosses.keys();
auto& level_name = boss_names[level.index % boss_names.size()];
auto& boss_data = config.bosses[level_name];
auto boss_id = world->entity();
components::configure_entity(*world, boss_id, boss_data["components"]);
auto boss_id = level.world->entity();
components::configure_entity(*level.world, boss_id, boss_data["components"]);
initialize_actor_ai(*world, boss_id);
dbc::check(world->has<ai::EntityAI>(boss_id), "boss doesn't have an AI");
initialize_actor_ai(*level.world, boss_id);
dbc::check(level.world->has<ai::EntityAI>(boss_id), "boss doesn't have an AI");
initialize_actor_ai(*world, level.player);
dbc::check(world->has<ai::EntityAI>(level.player), "player/host doesn't have an AI");
initialize_actor_ai(*level.world, level.player);
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) {