diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index c6b14220a7..a4006d4a6f 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -616,6 +616,8 @@ bool Game_Interpreter::ExecuteCommand() { auto& frame = GetFrame(); const auto& com = frame.commands[frame.current_command]; + // Output::Debug("Event code : {}", com.code); + switch (static_cast(com.code)) { case Cmd::ShowMessage: return CommandShowMessage(com); @@ -818,6 +820,10 @@ bool Game_Interpreter::ExecuteCommand() { return CommandManiacSetGameOption(com); case Cmd::Maniac_CallCommand: return CommandManiacCallCommand(com); + case Cmd::Mack_Pathfinder: + return CommandSearchPath(com); + case Cmd::Mack_ActivateEvent: + return CommandActivateEventAt(com); default: return true; } @@ -4680,3 +4686,211 @@ bool Game_Interpreter::ManiacCheckContinueLoop(int val, int val2, int type, int return false; } } + + +bool Game_Interpreter::CommandSearchPath(lcf::rpg::EventCommand const& com) { + + int eventID, destX, destY; + bool passableDestination = true; + + if (com.string == "false") + passableDestination = false; + + eventID = com.parameters[1]; + + destX = com.parameters[3]; + destY = com.parameters[5]; + + if (com.parameters[0] == 1) + eventID = Main_Data::game_variables->Get(eventID); + if (com.parameters[2] == 1) + destX = Main_Data::game_variables->Get(destX); + if (com.parameters[4] == 1) + destY = Main_Data::game_variables->Get(destY); + + + Game_Character* event; + if (eventID == 0) + event = Main_Data::game_player.get(); + else + event = GetCharacter(eventID); + + NoeudA start = NoeudA(event->GetX(), event->GetY(), 0, -1); + if (start.x == destX && start.y == destY) + return true; + + //Output::Debug("Pathfinding : {} {} {} {} {}", eventID, destX, destY, start.x, start.y); + + std::vector list; + std::vector closedList; + std::vector listMove; + + list.push_back(start); + int id = 0; + int idd = 0; + + while (!list.empty()) { + if (id >= list.size()) { + //Output::Debug("Give up"); + //return true; + } + + NoeudA n = pop_front(list);//list[id]; + closedList.push_back(n); + + if (n.x == destX && n.y == destY) { + + //Output::Debug("Chemin :"); + NoeudA* node = &n; + while (node != nullptr) { + //Output::Debug("N {} {} {}", node->x, node->y, node->parentID); + + NoeudA nodeF = NoeudA(node->x, node->y, 0, node->direction); + nodeF.parentX = n.x; + nodeF.parentY = n.y; + + listMove.push_back(nodeF); + int nid = node->parentID; + node = nullptr; + for (NoeudA na : closedList) { + if (na.id == nid) { + node = &na; + break; + } + } + } + + std::reverse(listMove.rbegin(), listMove.rend()); + + lcf::rpg::MoveRoute route; + // route.skippable = true; + route.repeat = false; + + if (!event->MakeWay(n.parentX, n.parentY, n.x, n.y)) { + listMove.pop_back(); + } + + if (listMove.size() <= 1 && n.direction <= 3) { + listMove.clear(); + n.direction += 12; + listMove.push_back(n); + } + + for (NoeudA node2 : listMove) { + if (node2.direction >= 0) { + lcf::rpg::MoveCommand cmd; + cmd.command_id = node2.direction; + route.move_commands.push_back(cmd); + + //Output::Debug("NF {} {} {}", node2.x, node2.y, cmd.command_id); + } + } + + lcf::rpg::MoveCommand cmd; + cmd.command_id = 23; + route.move_commands.push_back(cmd); + + event->ForceMoveRoute(route, 8); + + return true; + + } + else { + + std::vector neighbour; + NoeudA nn = NoeudA(n.x + 1, n.y, n.cout + 1, 1); // Right + neighbour.push_back(nn); + nn = NoeudA(n.x, n.y - 1, n.cout + 1, 0); // Up + neighbour.push_back(nn); + nn = NoeudA(n.x - 1, n.y, n.cout + 1, 3); // left + neighbour.push_back(nn); + nn = NoeudA(n.x, n.y + 1, n.cout + 1, 2); // Down + neighbour.push_back(nn); + + nn = NoeudA(n.x - 1, n.y + 1, n.cout + 1, 6); // Down Left + neighbour.push_back(nn); + nn = NoeudA(n.x + 1, n.y - 1, n.cout + 1, 4); // Up Right + neighbour.push_back(nn); + nn = NoeudA(n.x - 1, n.y - 1, n.cout + 1, 7); // Up Left + neighbour.push_back(nn); + nn = NoeudA(n.x + 1, n.y + 1, n.cout + 1, 5); // Down Right + neighbour.push_back(nn); + + + for (NoeudA a : neighbour) { + idd++; + a.parentX = n.x; + a.parentY = n.y; + a.id = idd; + a.parentID = n.id; + int i = vectorContains(list, a); + //if (!((vectorContains(closedList, a) != -1) || (i != -1 && i < list.size() && list[i].cout < a.cout))) { + //if (!((i != -1 && i < list.size() && list[i].cout < a.cout))) { + if (i < 0) { + if (event->MakeWay(n.x, n.y, a.x, a.y) || (passableDestination && a.x == destX && a.y == destY)) { + //Output::Debug(" {} {} {} {}", a.x, a.y, a.id, a.direction); + if (a.direction == 4) { + if (event->MakeWay(n.x, n.y, n.x + 1, n.y) || event->MakeWay(n.x, n.y, n.x, n.y - 1)) + list.push_back(a); + } + else if (a.direction == 5) { + if (event->MakeWay(n.x, n.y, n.x + 1, n.y) || event->MakeWay(n.x, n.y, n.x, n.y + 1)) + list.push_back(a); + } + else if (a.direction == 6) { + if (event->MakeWay(n.x, n.y, n.x - 1, n.y) || event->MakeWay(n.x, n.y, n.x, n.y + 1)) + list.push_back(a); + } + else if (a.direction == 7) { + if (event->MakeWay(n.x, n.y, n.x - 1, n.y) || event->MakeWay(n.x, n.y, n.x, n.y - 1)) + list.push_back(a); + } + else + list.push_back(a); + } + } + //closedList.push_back(a); + } + + } + id++; + } + + return true; +} + +int Game_Interpreter::vectorContains(std::vector v, NoeudA n) { + int id = -1; + for (NoeudA na : v) { + if (na.x == n.x && na.y == n.y) { + id = na.id; + break; + } + } + return id; +} + +Game_Interpreter::NoeudA Game_Interpreter::pop_front(std::vector& vec) +{ + assert(!vec.empty()); + NoeudA a = vec[0]; + vec.erase(vec.begin()); + return a; +} + +bool Game_Interpreter::CommandActivateEventAt(lcf::rpg::EventCommand const& com) { + + int x = com.parameters[1]; + int y = com.parameters[3]; + + if (com.parameters[0] == 1) + x = Main_Data::game_variables->Get(x); + if (com.parameters[2] == 1) + y = Main_Data::game_variables->Get(y); + + // Output::Debug("ActiveEvent : {} {}", x, y); + + bool b = Main_Data::game_player->ActivateEventAt(x, y); + + return true; +} diff --git a/src/game_interpreter.h b/src/game_interpreter.h index 715fdb5553..48695dc52e 100644 --- a/src/game_interpreter.h +++ b/src/game_interpreter.h @@ -284,6 +284,42 @@ class Game_Interpreter bool CommandManiacSetGameOption(lcf::rpg::EventCommand const& com); bool CommandManiacCallCommand(lcf::rpg::EventCommand const& com); + // Custom Commands + bool CommandSearchPath(lcf::rpg::EventCommand const& com); + bool CommandActivateEventAt(lcf::rpg::EventCommand const& com); + + + struct NoeudA { + NoeudA(int a, int b, int c, int d) { + x = a; + y = b; + cout = c; + direction = d; + } + int x; + int y; + int cout; + int id = 0; + + int parentID = -1; + int parentX = -1; + int parentY = -1; + int direction; + + friend bool operator==(const NoeudA& n1, const NoeudA& n2) + { + return n1.x == n2.x && n1.y == n2.y; + } + + bool operator()(NoeudA const& a, NoeudA const& b) + { + return a.id > b.id; + } + + }; + int vectorContains(std::vector v, NoeudA x); + NoeudA pop_front(std::vector& vec); + int DecodeInt(lcf::DBArray::const_iterator& it); const std::string DecodeString(lcf::DBArray::const_iterator& it); lcf::rpg::MoveCommand DecodeMove(lcf::DBArray::const_iterator& it); diff --git a/src/game_player.cpp b/src/game_player.cpp index 7f097daaf0..1915a0a59d 100644 --- a/src/game_player.cpp +++ b/src/game_player.cpp @@ -835,3 +835,6 @@ void Game_Player::UpdatePan() { data()->pan_current_y -= dy; } +bool Game_Player::ActivateEventAt(int x, int y) { + return CheckEventTriggerThere({ lcf::rpg::EventPage::Trigger_action }, x, y, true); +} diff --git a/src/game_player.h b/src/game_player.h index f107866b0d..62c9139f69 100644 --- a/src/game_player.h +++ b/src/game_player.h @@ -149,6 +149,8 @@ class Game_Player : public Game_PlayerBase { bool IsDatabaseCompatibleWithSave(int database_save_count) const; void UpdateSaveCounts(int db_save_count, int map_save_count); + + bool ActivateEventAt(int x, int y); private: using TriggerSet = lcf::FlagSet;