|
|
|
@ -40,6 +40,19 @@ Pathing compute_paths(gui::FSM& fsm) { |
|
|
|
|
return paths; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::log(std::string msg) { |
|
|
|
|
fmt::println(">>> AUTOWALK: {}", msg); |
|
|
|
|
fsm.$status_ui.log(msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::status(std::string msg) { |
|
|
|
|
fsm.$main_ui.$overlay_ui.show_text("bottom", msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::close_status() { |
|
|
|
|
fsm.$main_ui.$overlay_ui.close_text("bottom"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Pathing Autowalker::path_to_enemies() { |
|
|
|
|
return compute_paths<components::Combat>(fsm); |
|
|
|
|
} |
|
|
|
@ -57,11 +70,13 @@ void Autowalker::window_events() { |
|
|
|
|
fsm.$window.handleEvents( |
|
|
|
|
[&](const sf::Event::KeyPressed &) { |
|
|
|
|
fsm.autowalking = false; |
|
|
|
|
fmt::println("ABORT AUTOWALK"); |
|
|
|
|
close_status(); |
|
|
|
|
log("Aborting autowalk. You can move now."); |
|
|
|
|
}, |
|
|
|
|
[&](const sf::Event::MouseButtonPressed &) { |
|
|
|
|
fsm.autowalking = false; |
|
|
|
|
fmt::println("ABORT AUTOWALK"); |
|
|
|
|
close_status(); |
|
|
|
|
log("Aborting autowalk. You can move now."); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
@ -71,10 +86,8 @@ void Autowalker::process_combat() { |
|
|
|
|
|| fsm.in_state(gui::State::ATTACKING)) |
|
|
|
|
{ |
|
|
|
|
if(fsm.in_state(gui::State::ATTACKING)) { |
|
|
|
|
fmt::println("In attacking state, sending a TICK"); |
|
|
|
|
send_event(gui::Event::TICK); |
|
|
|
|
} else { |
|
|
|
|
fmt::println("Not in ATTACK, sending an ATTACK to continue combat."); |
|
|
|
|
send_event(gui::Event::ATTACK);; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -91,14 +104,16 @@ 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, MOVE_DIAGONAL)) { |
|
|
|
|
dbc::log("couldn't find a diagonal direction"); |
|
|
|
|
status("PATH FAIL"); |
|
|
|
|
log("Autowalk failed to find a path."); |
|
|
|
|
matrix::dump("MOVE FAIL PATHS", paths.$paths, target_out.x, target_out.y); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(!fsm.$level.map->can_move(target_out)) { |
|
|
|
|
dbc::log("neighbors is telling me to go to a bad spot."); |
|
|
|
|
status("PATH FAIL"); |
|
|
|
|
log("Autowalk major pathing failure. You can move now."); |
|
|
|
|
matrix::dump("BAD TARGET PATHS", paths.$paths, target_out.x, target_out.y); |
|
|
|
|
matrix::dump("BAD TARGET MAP", fsm.$level.map->walls(), target_out.x, target_out.y); |
|
|
|
|
return false; |
|
|
|
@ -133,7 +148,7 @@ void Autowalker::rotate_player(Point current, Point target) { |
|
|
|
|
target_facing = 6; |
|
|
|
|
} else if(delta_x == 1 && delta_y == -1) { |
|
|
|
|
// north east
|
|
|
|
|
target_facing = 5; |
|
|
|
|
target_facing = 7; |
|
|
|
|
} else if(delta_x == 1 && delta_y == 1) { |
|
|
|
|
// south east
|
|
|
|
|
target_facing = 1; |
|
|
|
@ -165,35 +180,12 @@ void Autowalker::rotate_player(Point current, Point target) { |
|
|
|
|
"player isn't facing the correct direction"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::show_map_overlay(matrix::Matrix& map, Point current) { |
|
|
|
|
auto debug = fsm.$level.world->get_the<components::Debug>(); |
|
|
|
|
if(!debug.FPS) { |
|
|
|
|
fsm.$main_ui.$overlay_ui.close_text("top_right"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string map_overlay; |
|
|
|
|
for(matrix::box it{map, current.x, current.y, 6}; it.next();) { |
|
|
|
|
if(it.x == it.left) map_overlay += "\n"; |
|
|
|
|
int cell = map[it.y][it.x]; |
|
|
|
|
|
|
|
|
|
if(it.x == current.x && it.y == current.y) { |
|
|
|
|
map_overlay += fmt::format("{:x}<", cell); |
|
|
|
|
} else if(cell == WALL_PATH_LIMIT) { |
|
|
|
|
map_overlay += fmt::format("# "); |
|
|
|
|
} else if(cell > 15) { |
|
|
|
|
map_overlay += fmt::format("* "); |
|
|
|
|
} else { |
|
|
|
|
map_overlay += fmt::format("{:x} ", cell); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fsm.$main_ui.$overlay_ui.show_text("top_right", map_overlay); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::autowalk() { |
|
|
|
|
window_events(); |
|
|
|
|
if(!fsm.autowalking) return; |
|
|
|
|
if(!fsm.autowalking) { |
|
|
|
|
close_status(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int move_attempts = 0; |
|
|
|
|
|
|
|
|
@ -204,14 +196,17 @@ void Autowalker::autowalk() { |
|
|
|
|
int enemy_count = number_left<components::Combat>(fsm); |
|
|
|
|
int item_count = number_left<components::InventoryItem>(fsm); |
|
|
|
|
|
|
|
|
|
fmt::println("ENEMY COUNT: {}, ITEM COUNT: {}", enemy_count, item_count); |
|
|
|
|
|
|
|
|
|
window_events(); |
|
|
|
|
ai::set(start, "no_more_enemies", enemy_count == 0); |
|
|
|
|
ai::set(start, "no_more_items", item_count == 0); |
|
|
|
|
ai::set(start, "enemy_found", |
|
|
|
|
fsm.in_state(gui::State::IN_COMBAT) || |
|
|
|
|
fsm.in_state(gui::State::ATTACKING)); |
|
|
|
|
ai::set(start, "health_good", player_health_good()); |
|
|
|
|
ai::set(start, "in_combat", |
|
|
|
|
fsm.in_state(gui::State::IN_COMBAT) || |
|
|
|
|
fsm.in_state(gui::State::ATTACKING)); |
|
|
|
|
ai::set(start, "have_item", player_item_count() > 0); |
|
|
|
|
|
|
|
|
|
auto a_plan = ai::plan("Walker::actions", start, goal); |
|
|
|
|
|
|
|
|
@ -219,27 +214,32 @@ void Autowalker::autowalk() { |
|
|
|
|
for(auto action : a_plan.script) { |
|
|
|
|
if(action.name == "find_enemy") { |
|
|
|
|
// this is where to test if enemy found and update state
|
|
|
|
|
fmt::println("FINDING AN ENEMY"); |
|
|
|
|
status("FINDING ENEMY"); |
|
|
|
|
auto paths = path_to_enemies(); |
|
|
|
|
process_move(paths); |
|
|
|
|
send_event(gui::Event::ATTACK); |
|
|
|
|
} else if(action.name == "use_item") { |
|
|
|
|
status("USE ITEMS"); |
|
|
|
|
} else if(action.name == "kill_enemy") { |
|
|
|
|
fmt::println("KILLING ENEMY"); |
|
|
|
|
status("KILLING ENEMY"); |
|
|
|
|
process_combat(); |
|
|
|
|
} else if(action.name == "find_healing") { |
|
|
|
|
fmt::println("FINDING HEALING"); |
|
|
|
|
status("FINDING HEALING"); |
|
|
|
|
auto paths = path_to_items(); |
|
|
|
|
process_move(paths); |
|
|
|
|
// do the path to healing thing
|
|
|
|
|
} else if(action.name == "collect_items") { |
|
|
|
|
fmt::println("COLLECTING ITEMS"); |
|
|
|
|
status("COLLECTING ITEMS"); |
|
|
|
|
auto paths = path_to_items(); |
|
|
|
|
process_move(paths); |
|
|
|
|
// path to the items and get them all
|
|
|
|
|
} else if(action == ai::FINAL_ACTION) { |
|
|
|
|
fmt::println("END STATE, complete? {}", a_plan.complete); |
|
|
|
|
close_status(); |
|
|
|
|
log("Autowalk done, nothing left to do."); |
|
|
|
|
fsm.autowalking = false; |
|
|
|
|
} else { |
|
|
|
|
close_status(); |
|
|
|
|
log("Autowalk has a bug. Unknown action."); |
|
|
|
|
fmt::println("Unknown action: {}", action.name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -253,7 +253,8 @@ void Autowalker::process_move(Pathing& paths) { |
|
|
|
|
Point target = current; |
|
|
|
|
|
|
|
|
|
if(!path_player(paths, target)) { |
|
|
|
|
dbc::log("no paths found, aborting autowalk"); |
|
|
|
|
close_status(); |
|
|
|
|
log("No paths found, aborting autowalk. You can move now."); |
|
|
|
|
fsm.autowalking = false; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -271,6 +272,16 @@ void Autowalker::send_event(gui::Event ev) { |
|
|
|
|
fsm.handle_world_events(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Autowalker::player_health_good() { |
|
|
|
|
auto combat = fsm.$level.world->get<components::Combat>(fsm.$level.player); |
|
|
|
|
return float(combat.hp) / float(combat.max_hp) > 0.5f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int Autowalker::player_item_count() { |
|
|
|
|
auto inventory = fsm.$level.world->get<components::Inventory>(fsm.$level.player); |
|
|
|
|
return inventory.count(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Autowalker::start_autowalk() { |
|
|
|
|
fsm.autowalking = true; |
|
|
|
|
} |
|
|
|
|