• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • 2026 staff recruitment is open! Check it out and consider applying!

Tibia Astar c++ to java

OTx

Member
Joined
Aug 3, 2012
Messages
126
Reaction score
10
Hello everyone!
I am working on a school project that involves some mechanisms in Tibia. I wanted to know more about pathfinding that Tibia is using. I looked through the source code of Crying Damson 0.3.6pl and found some Astar code in map.cpp and map.h.

map.cpp
Code:
//*********** AStarNodes *************

AStarNodes::AStarNodes()
{
    curNode = 0;
    openNodes.reset();
}

AStarNode* AStarNodes::createOpenNode()
{
    if(curNode >= MAX_NODES)
        return NULL;

    uint32_t retNode = curNode;
    curNode++;

    openNodes[retNode] = 1;
    return &nodes[retNode];
}

AStarNode* AStarNodes::getBestNode()
{
    if(!curNode)
        return NULL;

    int32_t bestNodeF = 100000;
    uint32_t bestNode = 0;

    bool found = false;
    for(uint32_t i = 0; i < curNode; i++)
    {
        if(nodes[i].f < bestNodeF && openNodes[i] == 1)
        {
            found = true;
            bestNodeF = nodes[i].f;
            bestNode = i;
        }
    }

    if(found)
        return &nodes[bestNode];

    return NULL;
}

void AStarNodes::closeNode(AStarNode* node)
{
    uint32_t pos = GET_NODE_INDEX(node);
    if(pos < MAX_NODES)
    {
        openNodes[pos] = 0;
        return;
    }

    assert(pos >= MAX_NODES);
    std::cout << "AStarNodes. trying to close node out of range" << std::endl;
    return;
}

void AStarNodes::openNode(AStarNode* node)
{
    uint32_t pos = GET_NODE_INDEX(node);
    if(pos < MAX_NODES)
    {
        openNodes[pos] = 1;
        return;
    }

    assert(pos >= MAX_NODES);
    std::cout << "AStarNodes. trying to open node out of range" << std::endl;
    return;
}

uint32_t AStarNodes::countClosedNodes()
{
    uint32_t counter = 0;
    for(uint32_t i = 0; i < curNode; i++)
    {
        if(!openNodes[i])
            counter++;
    }

    return counter;
}

uint32_t AStarNodes::countOpenNodes()
{
    uint32_t counter = 0;
    for(uint32_t i = 0; i < curNode; i++)
    {
        if(openNodes[i] == 1)
            counter++;
    }

    return counter;
}

bool AStarNodes::isInList(uint16_t x, uint16_t y)
{
    for(uint32_t i = 0; i < curNode; i++)
    {
        if(nodes[i].x == x && nodes[i].y == y)
            return true;
    }

    return false;
}

AStarNode* AStarNodes::getNodeInList(uint16_t x, uint16_t y)
{
    for(uint32_t i = 0; i < curNode; i++)
    {
        if(nodes[i].x == x && nodes[i].y == y)
            return &nodes[i];
    }

    return NULL;
}

int32_t AStarNodes::getMapWalkCost(const Creature* creature, AStarNode* node,
    const Tile* neighbourTile, const Position& neighbourPos)
{
    if(std::abs(node->x - neighbourPos.x) == std::abs(node->y - neighbourPos.y)) //diagonal movement extra cost
        return MAP_DIAGONALWALKCOST;

    return MAP_NORMALWALKCOST;
}

int32_t AStarNodes::getTileWalkCost(const Creature* creature, const Tile* tile)
{
    int32_t cost = 0;
    if(tile->getTopVisibleCreature(creature)) //destroy creature cost
        cost += MAP_NORMALWALKCOST * 3;

    if(const MagicField* field = tile->getFieldItem())
    {
        if(!creature->isImmune(field->getCombatType()))
            cost += MAP_NORMALWALKCOST * 3;
    }

    return cost;
}

int32_t AStarNodes::getEstimatedDistance(uint16_t x, uint16_t y, uint16_t xGoal, uint16_t yGoal)
{
    int32_t diagonal = std::min(std::abs(x - xGoal), std::abs(y - yGoal));
    return (MAP_DIAGONALWALKCOST * diagonal) + (MAP_NORMALWALKCOST * ((std::abs(
        x - xGoal) + std::abs(y - yGoal)) - (2 * diagonal)));
}

So what I want is to implement this on Java, the language that I am working with right now.

I have already started and got a working piece in my own project but the only problem is that the nodes that I am putting out on my own map, they are not working as great as it does in Tibia. By the way, my project is using astar pathfinding with a navigation mesh, thus navigation mesh with polygons instead of single tiles.

So my question is how Tibia is putting out nodes itself, you know when someone is mapping on RME-mapeditor and every node is connected to each other automaticly.

Thansk in advance if you have any clue!
 
Last edited:
Back
Top