Cleanup pathfinding chicanery

This commit is contained in:
Drought-Ender 2024-07-30 15:02:30 -05:00 committed by Hunter Shelton
parent 79d53e7a5e
commit a12750be55
7 changed files with 164 additions and 131 deletions

View File

@ -17,13 +17,14 @@ enum PathFindState {
};
enum PathFindFlags {
PATHFLAG_Unk1 = 0x1,
PATHFLAG_PathThroughWater = 0x2,
PATHFLAG_Unk3 = 0x4,
PATHFLAG_Unk4 = 0x8,
PATHFLAG_VsRed = 0x10,
PATHFLAG_VsBlue = 0x20,
PATHFLAG_InVersusMode = 0x40,
PATHFLAG_RequireOpen = 0x1,
PATHFLAG_PathThroughWater = 0x2,
PATHFLAG_DisallowUnfinishedBridges = 0x4,
PATHFLAG_Unk4 = 0x8,
PATHFLAG_DisallowVsRed = 0x10,
PATHFLAG_DisallowVsBlue = 0x20,
PATHFLAG_AllowUnvisited = 0x40,
PATHFLAG_TwoWayPathing = 0x80 // used for Panmodoki and BlackMan
};
namespace PathfindContext {

View File

@ -44,15 +44,15 @@ struct WayPointLinks {
namespace Game {
enum WayPointFlags {
WPF_Unset = 0x00,
WPF_Closed = 0x01,
WPF_Water = 0x02,
WPF_Bridge = 0x04,
WPF_Unknown4 = 0x08,
WPF_Unknown5 = 0x10,
WPF_Unknown6 = 0x20,
WPF_Unknown7 = 0x40,
WPF_Unknown8 = 0x80
WPF_Unset = 0x00,
WPF_Closed = 0x01,
WPF_Water = 0x02,
WPF_Bridge = 0x04,
WPF_Unknown4 = 0x08,
WPF_VersusBlue = 0x10, // unused
WPF_VersusRed = 0x20, // unused
WPF_Unknown7 = 0x40,
WPF_Unvisited = 0x80
// There is an additional value for "visited", and probably values for vs
// color
};
@ -170,7 +170,7 @@ struct WPEdgeSearchArg {
inline bool isLinkedTo(s16 idx) { return mLinks ? mLinks->isLinkedTo(idx) : false; }
Vector3f mStartPosition; // _00
bool mInWater; // _0C
u8 mInWater; // _0C
WayPointLinks* mLinks; // _10
s16 mRoomID; // _14
WayPoint* mWp1; // _18

View File

@ -1737,17 +1737,17 @@ void ActPathMove::initPathfinding(bool resetLinkCount)
}
mState = PATHMOVE_Pathfinding;
u8 flag = Game::PATHFLAG_Unk1;
u8 flag = Game::PATHFLAG_RequireOpen;
if (isAllBlue()) {
flag |= Game::PATHFLAG_PathThroughWater;
}
flag |= Game::PATHFLAG_Unk3;
flag |= Game::PATHFLAG_DisallowUnfinishedBridges;
if (Game::gameSystem && Game::gameSystem->isVersusMode()) {
if (mOnyon->mOnyonType == ONYON_TYPE_BLUE) {
flag |= (Game::PATHFLAG_VsBlue | Game::PATHFLAG_InVersusMode);
flag |= (Game::PATHFLAG_DisallowVsRed | Game::PATHFLAG_AllowUnvisited);
} else {
flag |= (Game::PATHFLAG_VsRed | Game::PATHFLAG_InVersusMode);
flag |= (Game::PATHFLAG_DisallowVsBlue | Game::PATHFLAG_AllowUnvisited);
}
}
@ -1875,14 +1875,14 @@ int ActPathMove::execPathfinding()
Game::testPathfinder->release(mContextHandle);
}
u8 flag = (Game::PATHFLAG_PathThroughWater | Game::PATHFLAG_Unk3);
u8 flag = (Game::PATHFLAG_PathThroughWater | Game::PATHFLAG_DisallowUnfinishedBridges);
mStartPathFindCounter++;
mState = PATHMOVE_Pathfinding;
if (Game::gameSystem && Game::gameSystem->isVersusMode()) {
flag |= Game::PATHFLAG_InVersusMode;
flag |= Game::PATHFLAG_AllowUnvisited;
}
if (mStartPathFindCounter >= 2) {
flag |= Game::PATHFLAG_InVersusMode; // hm
flag |= Game::PATHFLAG_AllowUnvisited; // hm
if (mStartPathFindCounter >= 3) {
mStartPathFindCounter = 3;
}
@ -3098,7 +3098,7 @@ bool ActPathMove::contextCheck(int idx)
Game::WayPoint* wp = getWayPoint(nextIdx);
if (mOnyon->mOnyonType == ONYON_TYPE_BLUE) {
if (wp->isFlag(Game::WPF_Unknown6)) {
if (wp->isFlag(Game::PATHFLAG_DisallowVsBlue)) {
mVsWayPointCounter++;
if (mVsWayPointCounter < 2) {
return false;
@ -3106,7 +3106,7 @@ bool ActPathMove::contextCheck(int idx)
} else {
mVsWayPointCounter = 0;
}
} else if (wp->isFlag(Game::WPF_Unknown5)) {
} else if (wp->isFlag(Game::PATHFLAG_DisallowVsRed)) {
mVsWayPointCounter++;
if (mVsWayPointCounter < 2) {
return false;

View File

@ -494,118 +494,124 @@ int AStarPathfinder::search(Game::AStarContext* context, int maxIterations, Game
}
}
if (targetNode) {
PathNode* child = targetNode->mParent;
if (child) {
PathNode* node = child->mRootNode;
PathNode* prevNode = nullptr;
while (node) {
if (node == targetNode) {
if (prevNode) {
prevNode->mSibling = node->mSibling;
if (node->mSibling) {
node->mSibling->mPrevious = prevNode;
}
if (!targetNode) {
continue;
}
targetNode->mPrevious = nullptr;
targetNode->mSibling = nullptr;
targetNode->mParent = nullptr;
} else {
child->mRootNode = node->mSibling;
if (node->mSibling) {
node->mSibling->mPrevious = nullptr;
}
targetNode->mPrevious = nullptr;
targetNode->mSibling = nullptr;
targetNode->mParent = nullptr;
}
break;
PathNode* child = targetNode->mParent;
if (!child) {
continue;
}
PathNode* node = child->mRootNode;
PathNode* prevNode = nullptr;
while (node) {
if (node == targetNode) {
if (prevNode) {
prevNode->mSibling = node->mSibling;
if (node->mSibling) {
node->mSibling->mPrevious = prevNode;
}
prevNode = node;
node = node->mSibling;
targetNode->mPrevious = nullptr;
targetNode->mSibling = nullptr;
targetNode->mParent = nullptr;
} else {
child->mRootNode = node->mSibling;
if (node->mSibling) {
node->mSibling->mPrevious = nullptr;
}
targetNode->mPrevious = nullptr;
targetNode->mSibling = nullptr;
targetNode->mParent = nullptr;
}
break;
}
if (targetNode->mWpIndex == endIdx) {
path[0] = targetNode;
return 0;
}
prevNode = node;
node = node->mSibling;
}
WayPoint* wp = PathfindContext::routeMgr->getWayPoint(targetNode->mWpIndex);
if (targetNode->mWpIndex == endIdx) {
path[0] = targetNode;
return 0;
}
WayPointIterator iter(wp, mContext->mRequestFlag & 0x80);
WayPoint* wp = PathfindContext::routeMgr->getWayPoint(targetNode->mWpIndex);
CI_LOOP(iter) { s16 idx = *iter; }
WayPointIterator iter(wp, mContext->mRequestFlag & PATHFLAG_TwoWayPathing);
CI_LOOP(iter)
{
s16 idx = *iter;
WayPoint* cWP = PathfindContext::routeMgr->getWayPoint(idx);
CI_LOOP(iter) { s16 idx = *iter; }
PathNode* node = mContext->getNode(idx);
if ((!(mContext->mRequestFlag & 1) || !(cWP->mFlags & 1)) && ((mContext->mRequestFlag & 2) || !(cWP->mFlags & 2))
&& ((mContext->mRequestFlag & 0x40) || !(cWP->mFlags & 0x80))
&& (!(cWP->mFlags & 2) || !(mContext->mRequestFlag & 4) || !(wp->mFlags & 4))
&& (!(mContext->mRequestFlag & 0x20) || !(wp->mFlags & 0x20))
&& (!(mContext->mRequestFlag & 0x10) || !(wp->mFlags & 0x10))) {
f32 test = estimate(targetNode->mWpIndex, node->mWpIndex);
test += node->_00;
if (node->_22 == 2 || test <= node->_00) {
node->mChild = targetNode;
node->_00 = test;
node->mDistanceToEnd = estimate(node->mWpIndex, endIdx);
if (node->_22 == 1) {
PathNode* parent = node->mParent;
if (parent) {
PathNode* out = nullptr;
for (PathNode* child = parent->mRootNode; child->mSibling != nullptr;) {
if (child == node) {
if (out) {
out->mSibling = child->mSibling;
if (child->mSibling) {
child->mSibling->mPrevious = out;
}
node->mPrevious = nullptr;
node->mSibling = nullptr;
node->mParent = nullptr;
} else {
parent->mSibling = child->mSibling;
if (child->mSibling) {
child->mSibling->mPrevious = nullptr;
}
node->mPrevious = nullptr;
node->mSibling = nullptr;
node->mParent = nullptr;
}
break;
}
CI_LOOP(iter)
{
s16 idx = *iter;
WayPoint* cWP = PathfindContext::routeMgr->getWayPoint(idx);
PathNode* node = mContext->getNode(idx);
if ((((mContext->mRequestFlag & PATHFLAG_RequireOpen) && (cWP->mFlags & WPF_Closed))
|| (!(mContext->mRequestFlag & PATHFLAG_PathThroughWater) && (cWP->mFlags & WPF_Water))
|| (!(mContext->mRequestFlag & PATHFLAG_AllowUnvisited) && (cWP->mFlags & WPF_Unvisited))
|| ((cWP->mFlags & WPF_Water) && (mContext->mRequestFlag & PATHFLAG_DisallowUnfinishedBridges) && (wp->mFlags & WPF_Bridge))
|| ((mContext->mRequestFlag & PATHFLAG_DisallowVsRed) && (wp->mFlags & WPF_VersusRed))
|| ((mContext->mRequestFlag & PATHFLAG_DisallowVsBlue) && (wp->mFlags & WPF_VersusBlue)))) {
continue;
}
f32 test = estimate(targetNode->mWpIndex, node->mWpIndex);
test += node->_00;
if (node->_22 == 2 || test <= node->_00) {
node->mChild = targetNode;
node->_00 = test;
node->mDistanceToEnd = estimate(node->mWpIndex, endIdx);
if (node->_22 == 1) {
PathNode* parent = node->mParent;
if (parent) {
PathNode* out = nullptr;
for (PathNode* child = parent->mRootNode; child->mSibling != nullptr;) {
if (child == node) {
if (out) {
out->mSibling = child->mSibling;
if (child->mSibling) {
child->mSibling->mPrevious = out;
}
}
node->_22 = 2;
}
if (node->_22) {
node->_22 = 0;
AStarContext* context = mContext;
PathNode* newnode = context->mNodeLists[0].mRootNode;
if (newnode) {
while (newnode->mSibling) {
newnode = newnode->mSibling;
}
newnode->mSibling = node;
node->mPrevious = newnode;
node->mPrevious = nullptr;
node->mSibling = nullptr;
node->mParent = nullptr;
} else {
context->mNodeLists[0].mRootNode = node;
parent->mSibling = child->mSibling;
if (child->mSibling) {
child->mSibling->mPrevious = nullptr;
}
node->mPrevious = nullptr;
node->mSibling = nullptr;
node->mParent = nullptr;
}
node->mParent = &context->mNodeLists[0];
break;
}
}
}
node->_22 = 2;
}
if (node->_22) {
node->_22 = 0;
AStarContext* context = mContext;
PathNode* newnode = context->mNodeLists[0].mRootNode;
if (newnode) {
while (newnode->mSibling) {
newnode = newnode->mSibling;
}
newnode->mSibling = node;
node->mPrevious = newnode;
} else {
context->mNodeLists[0].mRootNode = node;
}
node->mParent = &context->mNodeLists[0];
}
targetNode->_22 = 1;
}
}
targetNode->_22 = 1;
}
if (!mContext->mNodeLists[0].mRootNode) {

View File

@ -227,18 +227,32 @@ void WayPoint::setBridge(bool bridge)
* @note Address: N/A
* @note Size: 0x28
*/
void WayPoint::setVisit(bool)
void WayPoint::setVisit(bool visit)
{
// UNUSED FUNCTION
if (visit) {
resetFlag(WPF_Unvisited);
}
else {
setFlag(WPF_Unvisited);
}
}
/**
* @note Address: N/A
* @note Size: 0x48
* @note Assumed code but size matches. Function is unused
*/
void WayPoint::setVsColor(int)
void WayPoint::setVsColor(int color)
{
// UNUSED FUNCTION
resetFlag(WPF_VersusBlue);
resetFlag(WPF_VersusRed);
if (color == Blue) {
setFlag(WPF_VersusBlue);
}
else if (color == Red) {
setFlag(WPF_VersusRed);
}
}
/**
@ -247,17 +261,26 @@ void WayPoint::setVsColor(int)
*/
bool WayPoint::hasLinkTo(s16 idx)
{
// UNUSED FUNCTION
for (s16 i = 0; i < mNumToLinks; i++) {
if (mToLinks[i] == idx) {
return true;
}
}
return false;
}
/**
* @note Address: N/A
* @note Size: 0xB4
*/
void WayPoint::addLink(s16)
void WayPoint::addLink(s16 idx)
{
P2ASSERTLINE(300, false);
// UNUSED FUNCTION
// currently this is 0x4 larger than the given size
if (!hasLinkTo(idx)) {
P2ASSERTLINE(300, mNumToLinks < ARRAY_SIZE(mToLinks));
mToLinks[mNumToLinks++] = idx;
}
}
/**
@ -1280,7 +1303,7 @@ void RouteMgr::setCloseAll()
CI_LOOP(iter)
{
WayPoint* wp = (*iter);
wp->setFlag(WPF_Unknown8);
wp->setVisit(false);
}
}
@ -1297,7 +1320,7 @@ void RouteMgr::openRoom(s16 roomIdx)
FOREACH_NODE(WayPoint::RoomList, wp->mRoomList.mChild, node)
{
if (node->mRoomIdx == roomIdx) {
wp->resetFlag(WPF_Unknown8);
wp->setVisit(true);
}
}
}

View File

@ -3798,7 +3798,9 @@ bool BlackMan::Obj::setPathFinder(bool check)
mPreviousWaypointIndex = mCurrentWaypointIndex;
mCurrentWaypointIndex = idx1;
u32 flag = (check > 0) + 0xC3;
int flag = (check) ? (PATHFLAG_PathThroughWater | PATHFLAG_AllowUnvisited | PATHFLAG_TwoWayPathing)
: (PATHFLAG_RequireOpen | PATHFLAG_PathThroughWater | PATHFLAG_AllowUnvisited | PATHFLAG_TwoWayPathing);
if (mPathFindingHandle) {
testPathfinder->release(mPathFindingHandle);
}

View File

@ -1568,7 +1568,8 @@ bool Obj::setPathFinder(bool cond)
mWpIndex3 = mWpIndex2;
mWpIndex2 = nearIdx;
int flag = cond != 0 ? 0xC2 : 0xC3;
int flag = cond != 0 ? (PATHFLAG_PathThroughWater | PATHFLAG_AllowUnvisited | PATHFLAG_TwoWayPathing)
: (PATHFLAG_RequireOpen | PATHFLAG_PathThroughWater | PATHFLAG_AllowUnvisited | PATHFLAG_TwoWayPathing);
if (mPathID) {
testPathfinder->release(mPathID);