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

master
Zed A. Shaw 2 weeks ago
parent 63eaea3536
commit c894f6e094
  1. 114
      autowalker.cpp
  2. 6
      autowalker.hpp

@ -2,6 +2,7 @@
#include "ai_debug.hpp"
#include "gui/ritual_ui.hpp"
#include "game_level.hpp"
#define DEBUG
struct InventoryStats {
int healing = 0;
@ -102,20 +103,23 @@ void Autowalker::process_combat() {
if(fsm.in_state(gui::State::ATTACKING)) {
send_event(gui::Event::TICK);
} else {
send_event(gui::Event::ATTACK);;
send_event(gui::Event::ATTACK);
}
}
}
Point Autowalker::get_current_position() {
return GameDB::player_position().location;
}
void Autowalker::path_fail(Matrix& bad_paths, Point pos) {
void Autowalker::path_fail(const std::string& msg, Matrix& bad_paths, Point pos) {
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);
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);
#endif
}
bool Autowalker::path_player(Pathing& paths, Point& target_out) {
@ -125,77 +129,29 @@ bool Autowalker::path_player(Pathing& paths, Point& target_out) {
if(!found) {
// failed to find a linear path, try diagonal
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;
}
}
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 true;
}
void Autowalker::rotate_player(Point current, Point target) {
int delta_x = int(target.x) - int(current.x);
int delta_y = int(target.y) - int(current.y);
int facing = fsm.$main_ui.$compass_dir;
int target_facing = 0;
/* This is a massive pile of garbage. Need a way
* 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));
}
void Autowalker::rotate_player(Point target) {
auto rayview = fsm.$main_ui.$rayview;
auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
// auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
auto dir = gui::Event::ROTATE_LEFT;
while(facing != target_facing) {
while(rayview->aiming_at != target) {
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) {
@ -240,14 +196,11 @@ void Autowalker::handle_player_walk(ai::State& start, ai::State& goal) {
} else if(action.name == "kill_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)) {
rotate_player(current, {current.x - 1, current.y - 1});
dbc::log("TODO: you should find the enemy and face them instead of THIS GARBAGE!");
if(face_enemy()) {
process_combat();
}
}
process_combat();
} else if(action.name == "use_healing") {
status(L"USING HEALING");
player_use_healing();
@ -332,16 +285,17 @@ void Autowalker::autowalk() {
void Autowalker::process_move(Pathing& paths) {
auto world = GameDB::current_world();
Point current = get_current_position();
Point target = current;
// target has to start at the player location then...
auto target = GameDB::player_position().location;
// ... target gets modified as an out parameter to find the path
if(!path_player(paths, target)) {
close_status();
log(L"No paths found, aborting autowalk.");
return;
}
rotate_player(current, target);
rotate_player(target);
// what are we aiming at?
auto aimed_at = camera_aim();
@ -383,3 +337,19 @@ void Autowalker::player_use_healing() {
void Autowalker::start_autowalk() {
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;
}

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