Reverted the path node system
Code reviews were unfavorable so better nix it before it finds wider use.
This commit is contained in:
parent
c9e678b60e
commit
520b960ca5
21 changed files with 30 additions and 613 deletions
186
src/g_level.cpp
186
src/g_level.cpp
|
|
@ -98,7 +98,6 @@
|
|||
#include "s_music.h"
|
||||
#include "fragglescript/t_script.h"
|
||||
|
||||
|
||||
#include "texturemanager.h"
|
||||
|
||||
void STAT_StartNewGame(const char *lev);
|
||||
|
|
@ -2467,188 +2466,3 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetEpisodeName)
|
|||
ACTION_RETURN_STRING(GStrings.localize(STAT_EpisodeName().GetChars()));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Pathfinding
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Code by RicardoLuis0, modified by Major Cooke
|
||||
static TArray<TObjPtr<AActor*>>& GetPathNodeNeighbors(AActor * self)
|
||||
{
|
||||
static PClass * nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if(!nodeCls->IsAncestorOf(self->GetClass()))
|
||||
{
|
||||
ThrowAbortException(X_BAD_SELF, "Invalid class passed to GetNeighbors (must be PathNode)");
|
||||
}
|
||||
#endif
|
||||
|
||||
static PField *var = dyn_cast<PField>(nodeCls->FindSymbol("neighbors", true));
|
||||
|
||||
assert(var);
|
||||
assert(var->Type->isDynArray());
|
||||
assert(static_cast<PDynArray*>(var->Type)->ElementType == nodeCls->VMType);
|
||||
|
||||
return *reinterpret_cast<TArray<TObjPtr<AActor*>>*>(reinterpret_cast<uintptr_t>(self) + var->Offset);
|
||||
}
|
||||
|
||||
static void ReconstructPath(TMap<AActor*, AActor*> &cameFrom, AActor* current, TArray<TObjPtr<AActor*>> &path)
|
||||
{
|
||||
path.Clear();
|
||||
path.Push(current);
|
||||
AActor ** tmp = cameFrom.CheckKey(current);
|
||||
|
||||
if(tmp) do
|
||||
{
|
||||
path.Insert(0, *tmp);
|
||||
}
|
||||
while(tmp = cameFrom.CheckKey(*tmp));
|
||||
}
|
||||
|
||||
static AActor* FindClosestNode(AActor* from)
|
||||
{
|
||||
static const PClass * nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
|
||||
AActor * closest = nullptr;
|
||||
double closestDist = DBL_MAX;
|
||||
|
||||
for (int i = 0; i < from->Level->PathNodes.Size(); i++)
|
||||
{
|
||||
AActor* node = from->Level->PathNodes[i];
|
||||
if(node && !(node->flags & MF_AMBUSH) && nodeCls->IsAncestorOf(node->GetClass()))
|
||||
{
|
||||
double dst = node->Distance3DSquared(from);
|
||||
const bool mrange = (dst < closestDist &&
|
||||
(node->friendlyseeblocks <= 0 || dst < double(node->friendlyseeblocks * node->friendlyseeblocks)));
|
||||
|
||||
if (mrange && !from->CallExcludeNode(node) && P_CheckSight(node, from))
|
||||
{
|
||||
closestDist = dst;
|
||||
closest = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
static V GetOr(TMap<K, V> map, const K &key, V alt)
|
||||
{
|
||||
V *k = map.CheckKey(key);
|
||||
return k ? *k : alt;
|
||||
}
|
||||
|
||||
static bool FindPathAStar(AActor *chaser, AActor* startnode, AActor* goalnode, TArray<TObjPtr<AActor*>> &path)
|
||||
{
|
||||
TArray<AActor*> openSet;
|
||||
TMap<AActor*, AActor*> cameFrom;
|
||||
TMap<AActor*, double> gScore;
|
||||
TMap<AActor*, double> fScore;
|
||||
|
||||
openSet.Push(startnode);
|
||||
gScore.Insert(startnode, 0);
|
||||
fScore.Insert(startnode, startnode->Distance3DSquared(goalnode));
|
||||
|
||||
auto lt_fScore = [&fScore](AActor* lhs, AActor* rhs)
|
||||
{
|
||||
return GetOr(fScore, lhs, DBL_MAX) < GetOr(fScore, rhs, DBL_MAX);
|
||||
};
|
||||
|
||||
while(openSet.Size() > 0)
|
||||
{
|
||||
AActor * current = openSet[0];
|
||||
openSet.Delete(0);
|
||||
if(current == goalnode)
|
||||
{
|
||||
ReconstructPath(cameFrom, current, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
double current_gScore = GetOr(gScore, current, DBL_MAX);
|
||||
|
||||
for(AActor * neighbor : GetPathNodeNeighbors(current))
|
||||
{
|
||||
double tentative_gScore = current_gScore + current->Distance3DSquared(neighbor);
|
||||
|
||||
double neighbor_gScore = GetOr(gScore, neighbor, DBL_MAX);
|
||||
|
||||
if (tentative_gScore < neighbor_gScore && !chaser->CallExcludeNode(neighbor))
|
||||
{
|
||||
openSet.SortedDelete(neighbor, lt_fScore);
|
||||
cameFrom.Insert(neighbor, current);
|
||||
gScore.Insert(neighbor, tentative_gScore);
|
||||
fScore.Insert(neighbor, tentative_gScore + neighbor->Distance3DSquared(goalnode));
|
||||
openSet.SortedInsert(neighbor, lt_fScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FLevelLocals::FindPath(AActor* chaser, AActor* target, AActor* startNode, AActor* goalNode)
|
||||
{
|
||||
if (!chaser || !target || PathNodes.Size() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static PClass* nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
assert(startNode == nullptr || nodeCls->IsAncestorOf(startNode->GetClass()));
|
||||
assert(goalNode == nullptr || nodeCls->IsAncestorOf(goalNode->GetClass()));
|
||||
|
||||
if(startNode == nullptr) startNode = FindClosestNode(chaser);
|
||||
if(goalNode == nullptr) goalNode = FindClosestNode(target);
|
||||
|
||||
// Incomplete graph.
|
||||
if (!startNode || !goalNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (startNode == goalNode)
|
||||
{
|
||||
chaser->ClearPath();
|
||||
chaser->Path.Push(MakeObjPtr<AActor*>(startNode));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FindPathAStar(chaser, startNode, goalNode, chaser->Path))
|
||||
{
|
||||
if (chaser->goal && nodeCls->IsAncestorOf(chaser->goal->GetClass()))
|
||||
{
|
||||
chaser->goal = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FLevelLocals, FindPath)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
|
||||
PARAM_OBJECT(chaser, AActor);
|
||||
PARAM_OBJECT(target, AActor);
|
||||
PARAM_OBJECT(startnode, AActor);
|
||||
PARAM_OBJECT(goalnode, AActor);
|
||||
return self->FindPath(chaser, target, startnode, goalnode);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FLevelLocals, HandlePathNode)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
|
||||
PARAM_OBJECT(node, AActor);
|
||||
PARAM_BOOL(add);
|
||||
if (node)
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
if (self->PathNodes.Find(node) >= self->PathNodes.Size())
|
||||
self->PathNodes.Push(node);
|
||||
}
|
||||
else self->PathNodes.Delete(self->PathNodes.Find(node));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue