mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* origin/master: (93 commits) Add support for dictionary creation (#277) Add do-while statement (#276) Add foreach loops (#275) New compiler: array initialization (#274) Disambiguator: figure out if label is a case statement dispatch selector, or should apply to a statement within the case dispatch group's block. (#273) New compiler: Add support for case statements (#272) Change "logical" to "bitwise". (#258) Fix divide-by-zero errors, and mask FormatError if it were thrown in a destructor. (#271) Add break and continue statements. (#270) New compiler: assignment to local and global variables. (#269) Add support for while loops (#268) Optimize if statements, and emit module functions in legacy order (#267) Optimizations: binary operators (#266) Add binary operators (#265) Add support for const declarations (#264) Handle default parameter values, pass-by-name, and return statements in functions. (#263) Add limited support for user functions (#262) New compiler: add return and exit statements (#261) Add support for if-then-else statements (#259) OG compiler: set module to Mod_Basic when a token is an identifier (#257) ...
206 lines
5.3 KiB
C++
206 lines
5.3 KiB
C++
/** @file
|
|
*
|
|
* @par History
|
|
* - 2005/09/03 Shinigami: GetSuccessors - added support for non-blocking doors
|
|
*/
|
|
|
|
|
|
#ifndef __UOPATHNODE_H
|
|
#define __UOPATHNODE_H
|
|
// AStar search class
|
|
#include "plib/stlastar.h"
|
|
|
|
#include "base/position.h"
|
|
#include "realms/realm.h"
|
|
#include "realms/realms.h"
|
|
|
|
namespace Pol
|
|
{
|
|
namespace Core
|
|
{
|
|
#define BORDER_SKIRT 5
|
|
class AStarBlockers
|
|
{
|
|
public:
|
|
int xLow, xHigh, yLow, yHigh; // TODO: Area2d
|
|
|
|
struct BlockNode // TODO: Pos3d
|
|
{
|
|
short x;
|
|
short y;
|
|
s8 z;
|
|
};
|
|
|
|
typedef std::vector<BlockNode*> BlockNodeVector;
|
|
|
|
public:
|
|
AStarBlockers( short xL, short xH, short yL, short yH )
|
|
{
|
|
xLow = xL;
|
|
xHigh = xH;
|
|
yLow = yL;
|
|
yHigh = yH;
|
|
}
|
|
|
|
void AddBlocker( short x, short y, s8 z )
|
|
{
|
|
BlockNode* theNode = new BlockNode;
|
|
|
|
theNode->x = x;
|
|
theNode->y = y;
|
|
theNode->z = z;
|
|
|
|
m_List.push_back( theNode );
|
|
}
|
|
|
|
~AStarBlockers()
|
|
{
|
|
for ( auto blockNode : m_List )
|
|
{
|
|
delete blockNode;
|
|
}
|
|
}
|
|
|
|
bool IsBlocking( short x, short y, s8 z )
|
|
{
|
|
for ( const auto blockNode : m_List )
|
|
{
|
|
if ( ( blockNode->x == x ) && ( blockNode->y == y ) &&
|
|
( abs( blockNode->z - z ) < settingsManager.ssopt.default_character_height ) )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
BlockNodeVector m_List;
|
|
};
|
|
|
|
class UOPathState
|
|
{
|
|
public:
|
|
AStarBlockers* theBlockers;
|
|
short x; // TODO: Pos4d?
|
|
short y;
|
|
s8 z;
|
|
Realms::Realm* realm;
|
|
|
|
UOPathState()
|
|
: theBlockers( nullptr ), x( 0 ), y( 0 ), z( 0 ), realm( Core::gamestate.main_realm ){};
|
|
UOPathState( short newx, short newy, s8 newz, Realms::Realm* newrealm, AStarBlockers* blockers )
|
|
{
|
|
x = newx;
|
|
y = newy;
|
|
z = newz;
|
|
realm = newrealm;
|
|
theBlockers = blockers;
|
|
};
|
|
float GoalDistanceEstimate( UOPathState& nodeGoal );
|
|
bool IsGoal( UOPathState& nodeGoal );
|
|
bool GetSuccessors( Plib::AStarSearch<UOPathState>* astarsearch, UOPathState* parent_node,
|
|
bool doors_block );
|
|
float GetCost( UOPathState& successor );
|
|
bool IsSameState( UOPathState& rhs );
|
|
std::string Name();
|
|
};
|
|
bool UOPathState::IsSameState( UOPathState& rhs )
|
|
{
|
|
return ( ( rhs.x == x ) && ( rhs.y == y ) && ( rhs.z == z ) && ( rhs.realm == realm ) );
|
|
}
|
|
float UOPathState::GoalDistanceEstimate( UOPathState& nodeGoal )
|
|
{
|
|
return ( (float)( abs( x - nodeGoal.x ) + abs( y - nodeGoal.y ) + abs( z - nodeGoal.z ) ) );
|
|
}
|
|
bool UOPathState::IsGoal( UOPathState& nodeGoal )
|
|
{
|
|
return ( ( nodeGoal.x == x ) && ( nodeGoal.y == y ) &&
|
|
( abs( nodeGoal.z - z ) <= settingsManager.ssopt.default_character_height ) );
|
|
// return (IsSameState(nodeGoal));
|
|
}
|
|
float UOPathState::GetCost( UOPathState& successor )
|
|
{
|
|
int xdiff = abs( x - successor.x );
|
|
int ydiff = abs( y - successor.y );
|
|
if ( xdiff && ydiff )
|
|
return 1.414f;
|
|
else
|
|
return 1.0f;
|
|
}
|
|
std::string UOPathState::Name()
|
|
{
|
|
fmt::Writer writer;
|
|
writer.Format( "({},{},{})" ) << x << y << (int)z;
|
|
return writer.str();
|
|
}
|
|
bool UOPathState::GetSuccessors( Plib::AStarSearch<UOPathState>* astarsearch,
|
|
UOPathState* /*parent_node*/, bool doors_block )
|
|
{
|
|
Multi::UMulti* supporting_multi = nullptr;
|
|
Items::Item* walkon_item = nullptr;
|
|
|
|
UOPathState SolutionStartNode = ( *( astarsearch->GetSolutionStart() ) );
|
|
UOPathState SolutionEndNode = ( *( astarsearch->GetSolutionEnd() ) );
|
|
UOPathState* NewNode = new UOPathState();
|
|
|
|
for ( short i = -1; i <= 1; i++ )
|
|
{
|
|
for ( short j = -1; j <= 1; j++ )
|
|
{
|
|
if ( ( i == 0 ) && ( j == 0 ) )
|
|
continue;
|
|
|
|
short newx = x + i;
|
|
short newy = y + j;
|
|
s8 newz = z;
|
|
|
|
if ( ( newx < 0 ) || ( newx < ( theBlockers->xLow ) ) || ( newx > ( theBlockers->xHigh ) ) ||
|
|
( newx > ( (int)realm->width() ) ) )
|
|
continue;
|
|
|
|
if ( ( newy < 0 ) || ( newy < ( theBlockers->yLow ) ) || ( ( newy > theBlockers->yHigh ) ) ||
|
|
( newy > ( (int)realm->height() ) ) )
|
|
continue;
|
|
|
|
if ( realm->walkheight( Pos2d( newx, newy ), z, &newz, &supporting_multi, &walkon_item,
|
|
doors_block, Plib::MOVEMODE_LAND ) )
|
|
{
|
|
// Forbid diagonal move, if between 2 blockers - OWHorus {2011-04-26)
|
|
bool blocked = false;
|
|
if ( ( i != 0 ) && ( j != 0 ) ) // do only for diagonal moves
|
|
{
|
|
// If both neighbouring tiles are blocked, the move is illegal (diagonal move)
|
|
if ( !realm->walkheight( Pos2d( x + i, y ), z, &newz, &supporting_multi, &walkon_item,
|
|
doors_block, Plib::MOVEMODE_LAND ) )
|
|
blocked = !( realm->walkheight( Pos2d( x, y + j ), z, &newz, &supporting_multi,
|
|
&walkon_item, doors_block, Plib::MOVEMODE_LAND ) );
|
|
}
|
|
|
|
if ( !blocked )
|
|
{
|
|
NewNode->x = newx;
|
|
NewNode->y = newy;
|
|
NewNode->z = newz;
|
|
NewNode->realm = realm;
|
|
NewNode->theBlockers = theBlockers;
|
|
|
|
if ( ( !NewNode->IsSameState( SolutionStartNode ) ) &&
|
|
( !NewNode->IsSameState( SolutionEndNode ) ) )
|
|
blocked = ( theBlockers->IsBlocking( newx, newy, newz ) );
|
|
}
|
|
|
|
if ( !blocked )
|
|
{
|
|
if ( !astarsearch->AddSuccessor( *NewNode ) )
|
|
{
|
|
delete NewNode;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete NewNode;
|
|
return true;
|
|
}
|
|
} // namespace Core
|
|
} // namespace Pol
|
|
#endif
|