Initial part of the rewrite for the autowalker to fix the pathing and aiming issues.
This commit is contained in:
parent
63eaea3536
commit
c894f6e094
2 changed files with 45 additions and 75 deletions
114
autowalker.cpp
114
autowalker.cpp
|
@ -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);
|
||||
void Autowalker::rotate_player(Point target) {
|
||||
auto rayview = fsm.$main_ui.$rayview;
|
||||
|
||||
int facing = fsm.$main_ui.$compass_dir;
|
||||
int target_facing = 0;
|
||||
// auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
|
||||
auto dir = gui::Event::ROTATE_LEFT;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
auto dir = facing > target_facing ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
|
||||
|
||||
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();
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue