Decompile 4 functions in Source/Contents/TerrainPathSearch.cpp, Source/Contents/TerrainPathSearch.h
Batch #1547 by ragnarok-clanker: 0 byte-identical, 4 confirmed by peer review. - fn_17868 CPathFinder::FindPath: logic confirmed by peer review - fn_17875 CPathFinder::FindOrCreateNode: logic confirmed by peer review - fn_17882 CPathFinder::AddNeighbor: logic confirmed by peer review - fn_17884 CPathFinder::Clear: logic confirmed by peer review Reviewed-by: ragnarok-clanker
This commit is contained in:
parent
943d22d0b8
commit
9541f2ff09
2 changed files with 210 additions and 2 deletions
|
|
@ -1,10 +1,211 @@
|
|||
#include "Contents/TerrainPathSearch.h"
|
||||
#include "Resource/World/TerrainResource.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
// OFFSET: 0x00AD7E70
|
||||
// FUNCTION: fn_17860
|
||||
CPathFinder::CPathFinder() : useNodePool(false) {
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD88F0
|
||||
// FUNCTION: fn_17868
|
||||
bool CPathFinder::FindPath(
|
||||
int startTick, int startX, int startY, int currentFractionX, int currentFractionY, int destX, int destY, int speed, MovementRouteInterpolation& route,
|
||||
char flag
|
||||
) {
|
||||
this->destinationX = destX;
|
||||
this->destinationY = destY;
|
||||
|
||||
if (startX == destX && startY == destY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
route.segment = 0;
|
||||
this->Reset();
|
||||
this->nodeCount = 0;
|
||||
|
||||
MovementPathNode* start = this->FindOrCreateNode(startX, startY);
|
||||
start->state = 1;
|
||||
start->parent = nullptr;
|
||||
start->cost = 0;
|
||||
start->estimatedCost = 10 * (std::abs(startX - this->destinationX) + std::abs(startY - this->destinationY));
|
||||
|
||||
std::vector<MovementPathNode*>& open = this->openList.Nodes();
|
||||
open.push_back(start);
|
||||
std::push_heap(open.begin(), open.end(), MovementPathNodeCompare());
|
||||
|
||||
while (!open.empty()) {
|
||||
MovementPathNode* current = open.front();
|
||||
std::pop_heap(open.begin(), open.end(), MovementPathNodeCompare());
|
||||
open.pop_back();
|
||||
|
||||
if (current->x == destX && current->y == destY) {
|
||||
float x = static_cast<float>(currentFractionX) * 0.0625f;
|
||||
if (startX > 0) {
|
||||
x = static_cast<float>(static_cast<double>(startX) - 0.5 + x);
|
||||
}
|
||||
route.startX = x;
|
||||
|
||||
float y = static_cast<float>(currentFractionY) * 0.0625f;
|
||||
if (startY > 0) {
|
||||
y = static_cast<float>(static_cast<double>(startY) - 0.5 + y);
|
||||
}
|
||||
route.startY = y;
|
||||
|
||||
BuildMovementRoute(startTick, current, speed, route);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->CanMove(current->x, current->y, current->x + 1, current->y - 1, flag) && !this->AddNeighbor(current, 14, current->x + 1, current->y - 1, 5)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x + 1, current->y, flag) && !this->AddNeighbor(current, 10, current->x + 1, current->y, 6)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x + 1, current->y + 1, flag) && !this->AddNeighbor(current, 14, current->x + 1, current->y + 1, 7)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x, current->y + 1, flag) && !this->AddNeighbor(current, 10, current->x, current->y + 1, 0)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x - 1, current->y + 1, flag) && !this->AddNeighbor(current, 14, current->x - 1, current->y + 1, 1)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x - 1, current->y, flag) && !this->AddNeighbor(current, 10, current->x - 1, current->y, 2)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x - 1, current->y - 1, flag) && !this->AddNeighbor(current, 14, current->x - 1, current->y - 1, 3)) {
|
||||
return false;
|
||||
}
|
||||
if (this->CanMove(current->x, current->y, current->x, current->y - 1, flag) && !this->AddNeighbor(current, 10, current->x, current->y - 1, 4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current->state = 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD9030
|
||||
// FUNCTION: fn_17875
|
||||
MovementPathNode* CPathFinder::FindOrCreateNode(int x, int y) {
|
||||
const int width = this->attr->width;
|
||||
const int key = y * width + x;
|
||||
auto found = this->nodeMap.find(key);
|
||||
if (found != this->nodeMap.end() && found->second) {
|
||||
return found->second;
|
||||
}
|
||||
|
||||
MovementPathNode* node;
|
||||
if (this->useNodePool) {
|
||||
const int count = static_cast<int>(this->nodePool.size());
|
||||
if (this->nodeCount >= count - 1) {
|
||||
this->nodePool.resize(this->attr->height * width + 1);
|
||||
}
|
||||
node = &this->nodePool[this->nodeCount++];
|
||||
} else {
|
||||
if (this->nodeCount >= 149) {
|
||||
return nullptr;
|
||||
}
|
||||
node = &this->nodes[this->nodeCount++];
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node->x = x;
|
||||
node->y = y;
|
||||
node->state = 0;
|
||||
this->nodeMap[key] = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD9550
|
||||
// FUNCTION: fn_17879
|
||||
bool CPathFinder::CanMove(int startX, int startY, int targetX, int targetY, char flag) const {
|
||||
if (targetX < 0 || targetY < 0 || targetX >= this->attr->width || targetY >= this->attr->height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const TerrainHeightCell* cell = this->attr->Grid().CellAt(targetX, targetY);
|
||||
if (!cell || cell->type == 1 || (flag != 12 && cell->type == 5)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (startX == targetX || startY == targetY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const TerrainHeightCell* side = this->attr->Grid().CellAt(startX, targetY);
|
||||
if (!side || side->type == 1 || side->type == 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
side = this->attr->Grid().CellAt(targetX, startY);
|
||||
if (!side || side->type == 1 || side->type == 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD9610
|
||||
// FUNCTION: fn_17882
|
||||
bool CPathFinder::AddNeighbor(MovementPathNode* current, int cost, int nextX, int nextY, int metadata) {
|
||||
const int totalCost = current->cost + cost;
|
||||
MovementPathNode* next = this->FindOrCreateNode(nextX, nextY);
|
||||
if (!next) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (next->state == 0) {
|
||||
next->parent = current;
|
||||
next->state = 1;
|
||||
next->cost = totalCost;
|
||||
next->estimatedCost = totalCost + 10 * (std::abs(nextX - this->destinationX) + std::abs(nextY - this->destinationY));
|
||||
next->metadata = metadata;
|
||||
std::vector<MovementPathNode*>& open = this->openList.Nodes();
|
||||
open.push_back(next);
|
||||
std::push_heap(open.begin(), open.end(), MovementPathNodeCompare());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (next->cost > totalCost) {
|
||||
next->parent = current;
|
||||
next->cost = totalCost;
|
||||
next->estimatedCost = totalCost + 10 * (std::abs(nextX - this->destinationX) + std::abs(nextY - this->destinationY));
|
||||
next->metadata = metadata;
|
||||
|
||||
if (next->state == 1) {
|
||||
std::vector<MovementPathNode*>& open = this->openList.Nodes();
|
||||
for (auto it = open.begin(); it != open.end(); ++it) {
|
||||
if ((*it)->x == next->x && (*it)->y == next->y) {
|
||||
std::push_heap(open.begin(), it + 1, MovementPathNodeCompare());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (next->state == 2) {
|
||||
next->state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD97C0
|
||||
// FUNCTION: fn_17884
|
||||
void CPathFinder::Clear() {
|
||||
for (auto& [name, cached] : this->attrCache) {
|
||||
delete cached;
|
||||
}
|
||||
|
||||
this->attrCache.clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AD9840
|
||||
// FUNCTION: fn_17885
|
||||
void CPathFinder::Reset() {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define RAGNAROK_SOURCE_CONTENTS_TERRAINPATHSEARCH_H
|
||||
|
||||
#include "Contents/MovementRouteInterpolation.h"
|
||||
#include "Resource/World/TerrainResource.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
|
@ -9,8 +10,6 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class C3dAttr;
|
||||
|
||||
struct MovementPathNodeCompare {
|
||||
bool operator()(const MovementPathNode* left, const MovementPathNode* right) const {
|
||||
return left->estimatedCost > right->estimatedCost;
|
||||
|
|
@ -42,7 +41,15 @@ public:
|
|||
/* 1090 */ std::map<int, MovementPathNode*> nodeMap;
|
||||
/* 1098 */ MovementOpenList openList;
|
||||
|
||||
void Clear();
|
||||
void Reset();
|
||||
bool CanMove(int startX, int startY, int targetX, int targetY, char flag) const;
|
||||
MovementPathNode* FindOrCreateNode(int x, int y);
|
||||
bool AddNeighbor(MovementPathNode* current, int cost, int nextX, int nextY, int metadata);
|
||||
bool FindPath(
|
||||
int startTick, int startX, int startY, int currentFractionX, int currentFractionY, int destX, int destY, int speed, MovementRouteInterpolation& route,
|
||||
char flag
|
||||
);
|
||||
int Height() const;
|
||||
int Width() const;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue