mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-16 17:21:10 +00:00
Added ExcludeNode virtual for actors to reject certain nodes of choice.
- Changed MeleeRange to FriendlySeeBlocks so it's supported by Doom Builder.
This commit is contained in:
parent
81ebd8c8c4
commit
69001ad4f7
5 changed files with 52 additions and 10 deletions
|
@ -2472,7 +2472,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetEpisodeName)
|
|||
// Pathfinding
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Code by RicardoLuis0
|
||||
// Code by RicardoLuis0, modified by Major Cooke
|
||||
static TArray<TObjPtr<AActor*>>& GetPathNodeNeighbors(AActor * self)
|
||||
{
|
||||
static PClass * nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
|
@ -2508,7 +2508,7 @@ static void ReconstructPath(TMap<AActor*, AActor*> &cameFrom, AActor* current, T
|
|||
|
||||
static AActor* FindClosestNode(AActor* from)
|
||||
{
|
||||
static PClass * nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
static const PClass * nodeCls = PClass::FindClass(NAME_PathNode);
|
||||
|
||||
AActor * closest = nullptr;
|
||||
double closestDist = DBL_MAX;
|
||||
|
@ -2519,9 +2519,10 @@ static AActor* FindClosestNode(AActor* from)
|
|||
if(node && !(node->flags & MF_AMBUSH) && nodeCls->IsAncestorOf(node->GetClass()))
|
||||
{
|
||||
double dst = node->Distance3DSquared(from);
|
||||
bool mrange = (dst < closestDist && (node->meleerange <= 0.0 || dst < (node->meleerange * node->meleerange)));
|
||||
const bool mrange = (dst < closestDist &&
|
||||
(node->friendlyseeblocks <= 0 || dst < double(node->friendlyseeblocks * node->friendlyseeblocks)));
|
||||
|
||||
if(mrange && P_CheckSight(node, from))
|
||||
if (mrange && !from->CallExcludeNode(node) && P_CheckSight(node, from))
|
||||
{
|
||||
closestDist = dst;
|
||||
closest = node;
|
||||
|
@ -2539,9 +2540,8 @@ static V GetOr(TMap<K, V> map, const K &key, V alt)
|
|||
return k ? *k : alt;
|
||||
}
|
||||
|
||||
static bool FindPathAStar(AActor* startnode, AActor* goalnode, TArray<TObjPtr<AActor*>> &path)
|
||||
static bool FindPathAStar(AActor *chaser, AActor* startnode, AActor* goalnode, TArray<TObjPtr<AActor*>> &path)
|
||||
{
|
||||
|
||||
TArray<AActor*> openSet;
|
||||
TMap<AActor*, AActor*> cameFrom;
|
||||
TMap<AActor*, double> gScore;
|
||||
|
@ -2570,12 +2570,11 @@ static bool FindPathAStar(AActor* startnode, AActor* goalnode, TArray<TObjPtr<AA
|
|||
|
||||
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)
|
||||
if (tentative_gScore < neighbor_gScore && !chaser->CallExcludeNode(neighbor))
|
||||
{
|
||||
openSet.SortedDelete(neighbor, lt_fScore);
|
||||
cameFrom.Insert(neighbor, current);
|
||||
|
@ -2615,7 +2614,7 @@ bool FLevelLocals::FindPath(AActor* chaser, AActor* target, AActor* startNode, A
|
|||
return true;
|
||||
}
|
||||
|
||||
if (FindPathAStar(startNode, goalNode, chaser->Path))
|
||||
if (FindPathAStar(chaser, startNode, goalNode, chaser->Path))
|
||||
{
|
||||
if (chaser->goal && nodeCls->IsAncestorOf(chaser->goal->GetClass()))
|
||||
{
|
||||
|
|
|
@ -1106,6 +1106,7 @@ public:
|
|||
|
||||
void ClearPath();
|
||||
bool CanPathfind();
|
||||
bool CallExcludeNode(AActor *node);
|
||||
void CallReachedNode(AActor *node);
|
||||
|
||||
// info for drawing
|
||||
|
|
|
@ -2259,6 +2259,20 @@ void AActor::CallReachedNode(AActor *node)
|
|||
}
|
||||
}
|
||||
|
||||
// Called while scoring the path.
|
||||
bool AActor::CallExcludeNode(AActor* node)
|
||||
{
|
||||
IFVIRTUAL(AActor, ExcludeNode)
|
||||
{
|
||||
VMValue params[2] = { (DObject*)this, node };
|
||||
int retval = 0;
|
||||
VMReturn ret(&retval);
|
||||
VMCall(func, params, 2, &ret, 1);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_Wander
|
||||
|
|
|
@ -837,6 +837,26 @@ class Actor : Thinker native
|
|||
ClearPath();
|
||||
|
||||
}
|
||||
|
||||
// Return true to mark the node as ineligible for constructing a path along.
|
||||
virtual bool ExcludeNode(PathNode node)
|
||||
{
|
||||
if (!node) return true;
|
||||
|
||||
// Scale is the size requirements.
|
||||
// STANDSTILL flag is used to require the actor to be bigger instead of smaller.
|
||||
double r = node.Scale.X;
|
||||
double h = node.Scale.Y;
|
||||
|
||||
// Perfect fit.
|
||||
if (radius == r && height == h)
|
||||
return false;
|
||||
|
||||
if ((0.0 < r && r < radius) || (0.0 < h && h < height))
|
||||
return !node.bSTANDSTILL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
native bool TryMove(vector2 newpos, int dropoff, bool missilecheck = false, FCheckPosition tm = null);
|
||||
native bool CheckMove(vector2 newpos, int flags = 0, FCheckPosition tm = null);
|
||||
|
|
|
@ -257,6 +257,9 @@ AMBUSH
|
|||
Useful for tele/portals since the engine makes them "touch"
|
||||
upon transitioning. These nodes are fast forwarded over in Actor's
|
||||
ReachedNode() function.
|
||||
|
||||
STANDSTILL
|
||||
Traveller must be bigger instead of smaller.
|
||||
*/
|
||||
class PathNode : Actor
|
||||
{
|
||||
|
@ -273,7 +276,12 @@ class PathNode : Actor
|
|||
Radius 16;
|
||||
Height 56;
|
||||
RenderStyle "None";
|
||||
MeleeRange 0; // Sight checks limited to this. 0 = infinite. Set within map editor.
|
||||
|
||||
// The following properties can be set directly in Ultimate Doom Builder's Custom tab.
|
||||
|
||||
FriendlySeeBlocks 0; // Sight checks limited to this. <= 0 is infinite.
|
||||
XScale 0; // filter height - actors must be this small for this node. Only effective if > 0.
|
||||
YScale 0; // filter radius - ^ but for radius
|
||||
}
|
||||
|
||||
// Args are TIDs. Can be one way to force single directions.
|
||||
|
|
Loading…
Reference in a new issue