Initial part of the rewrite for the autowalker to fix the pathing and aiming issues.

This commit is contained in:
Zed A. Shaw 2025-08-26 00:55:27 -04:00
parent 63eaea3536
commit c894f6e094
2 changed files with 45 additions and 75 deletions

View file

@ -2,6 +2,7 @@
#include "ai_debug.hpp" #include "ai_debug.hpp"
#include "gui/ritual_ui.hpp" #include "gui/ritual_ui.hpp"
#include "game_level.hpp" #include "game_level.hpp"
#define DEBUG
struct InventoryStats { struct InventoryStats {
int healing = 0; int healing = 0;
@ -102,20 +103,23 @@ void Autowalker::process_combat() {
if(fsm.in_state(gui::State::ATTACKING)) { if(fsm.in_state(gui::State::ATTACKING)) {
send_event(gui::Event::TICK); send_event(gui::Event::TICK);
} else { } else {
send_event(gui::Event::ATTACK);; send_event(gui::Event::ATTACK);
} }
} }
} }
Point Autowalker::get_current_position() { void Autowalker::path_fail(const std::string& msg, Matrix& bad_paths, Point pos) {
return GameDB::player_position().location;
}
void Autowalker::path_fail(Matrix& bad_paths, Point pos) {
status(L"PATH FAIL"); status(L"PATH FAIL");
log(L"Autowalk failed to find a path."); #ifdef DEBUG
matrix::dump("MOVE FAIL PATHS", bad_paths, pos.x, pos.y); matrix::dump("MOVE FAIL PATHS", bad_paths, pos.x, pos.y);
dbc::sentinel(fmt::format("[{}]: Autowalk failed to find a path.", msg));
#else
log(L"Autowalk failed to find a path.");
(void)bad_paths; // shutup compiler errors
(void)pos;
(void)msg;
send_event(gui::Event::STAIRS_DOWN); send_event(gui::Event::STAIRS_DOWN);
#endif
} }
bool Autowalker::path_player(Pathing& paths, Point& target_out) { bool Autowalker::path_player(Pathing& paths, Point& target_out) {
@ -125,77 +129,29 @@ bool Autowalker::path_player(Pathing& paths, Point& target_out) {
if(!found) { if(!found) {
// failed to find a linear path, try diagonal // failed to find a linear path, try diagonal
if(!paths.random_walk(target_out, false, PATHING_TOWARD, 8, 8)) { if(!paths.random_walk(target_out, false, PATHING_TOWARD, 8, 8)) {
path_fail(paths.$paths, target_out); path_fail("random_walk", paths.$paths, target_out);
return false; return false;
} }
} }
if(!level.map->can_move(target_out)) { if(!level.map->can_move(target_out)) {
path_fail(paths.$paths, target_out); path_fail("level_map->can_move", paths.$paths, target_out);
return false; return false;
} }
return true; return true;
} }
void Autowalker::rotate_player(Point current, Point target) { void Autowalker::rotate_player(Point target) {
int delta_x = int(target.x) - int(current.x); auto rayview = fsm.$main_ui.$rayview;
int delta_y = int(target.y) - int(current.y);
int facing = fsm.$main_ui.$compass_dir; // auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
int target_facing = 0; auto dir = gui::Event::ROTATE_LEFT;
/* This is a massive pile of garbage. Need a way while(rayview->aiming_at != target) {
* to determine player facing direction without
* hacking into the compass, and also do accurate
* turns.
*/
if(delta_x == -1 && delta_y == 0) {
// west
target_facing = 4;
} else if(delta_x == 1 && delta_y == 0) {
// east
target_facing = 0;
} else if(delta_x == 0 && delta_y == 1) {
// south
target_facing = 2;
} else if(delta_x == 0 && delta_y == -1) {
// north
target_facing = 6;
} else if(delta_x == 1 && delta_y == -1) {
// north east
target_facing = 7;
} else if(delta_x == 1 && delta_y == 1) {
// south east
target_facing = 1;
} else if(delta_x == -1 && delta_y == 1) {
// south west
target_facing = 3;
} else if(delta_x == -1 && delta_y == -1) {
// north west
target_facing = 5;
} else {
dbc::sentinel(
fmt::format("got more than 8 direction result: "
"current={},{} "
"target={},{} "
"delta={},{} ",
current.x, current.y,
target.x, target.y,
delta_x, delta_y));
}
auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
while(facing != target_facing) {
send_event(dir); send_event(dir);
facing = fsm.$main_ui.$compass_dir;
}
while(fsm.in_state(gui::State::ROTATING)) send_event(gui::Event::TICK); while(fsm.in_state(gui::State::ROTATING)) send_event(gui::Event::TICK);
}
dbc::check(fsm.$main_ui.$compass_dir == target_facing,
"player isn't facing the correct direction");
} }
ai::State Autowalker::update_state(ai::State start) { ai::State Autowalker::update_state(ai::State start) {
@ -240,14 +196,11 @@ void Autowalker::handle_player_walk(ai::State& start, ai::State& goal) {
} else if(action.name == "kill_enemy") { } else if(action.name == "kill_enemy") {
status(L"KILLING ENEMY"); status(L"KILLING ENEMY");
// TODO: find the enemy and then rotate toward them
Point current = get_current_position();
if(fsm.in_state(gui::State::IN_COMBAT)) { if(fsm.in_state(gui::State::IN_COMBAT)) {
rotate_player(current, {current.x - 1, current.y - 1}); if(face_enemy()) {
dbc::log("TODO: you should find the enemy and face them instead of THIS GARBAGE!");
}
process_combat(); process_combat();
}
}
} else if(action.name == "use_healing") { } else if(action.name == "use_healing") {
status(L"USING HEALING"); status(L"USING HEALING");
player_use_healing(); player_use_healing();
@ -332,16 +285,17 @@ void Autowalker::autowalk() {
void Autowalker::process_move(Pathing& paths) { void Autowalker::process_move(Pathing& paths) {
auto world = GameDB::current_world(); auto world = GameDB::current_world();
Point current = get_current_position(); // target has to start at the player location then...
Point target = current; auto target = GameDB::player_position().location;
// ... target gets modified as an out parameter to find the path
if(!path_player(paths, target)) { if(!path_player(paths, target)) {
close_status(); close_status();
log(L"No paths found, aborting autowalk."); log(L"No paths found, aborting autowalk.");
return; return;
} }
rotate_player(current, target); rotate_player(target);
// what are we aiming at? // what are we aiming at?
auto aimed_at = camera_aim(); auto aimed_at = camera_aim();
@ -383,3 +337,19 @@ void Autowalker::player_use_healing() {
void Autowalker::start_autowalk() { void Autowalker::start_autowalk() {
fsm.autowalking = true; fsm.autowalking = true;
} }
bool Autowalker::face_enemy() {
auto& level = GameDB::current_level();
auto player_at = GameDB::player_position();
auto [found, neighbors] = level.collision->neighbors(player_at.location, true);
if(found) {
auto enemy_pos = level.world->get<components::Position>(neighbors[0]);
rotate_player(enemy_pos.location);
} else {
dbc::log("No enemies nearby, moving on.");
}
return found;
}

View file

@ -28,9 +28,8 @@ struct Autowalker {
void send_event(gui::Event ev); void send_event(gui::Event ev);
void process_combat(); void process_combat();
bool path_player(Pathing& paths, Point &target_out); bool path_player(Pathing& paths, Point &target_out);
void path_fail(Matrix& bad_paths, Point pos); void path_fail(const std::string& msg, Matrix& bad_paths, Point pos);
Point get_current_position(); void rotate_player(Point target);
void rotate_player(Point current, Point target);
void process_move(Pathing& paths); void process_move(Pathing& paths);
void log(std::wstring msg); void log(std::wstring msg);
void status(std::wstring msg); void status(std::wstring msg);
@ -43,4 +42,5 @@ struct Autowalker {
Pathing path_to_enemies(); Pathing path_to_enemies();
Pathing path_to_items(); Pathing path_to_items();
bool face_enemy();
}; };