Beispiel #1
0
void Game::autoWalk(const std::vector<Otc::Direction>& dirs)
{
    if(!canPerformGameAction())
        return;

    // protocol limits walk path up to 255 directions
    if(dirs.size() > 127) {
        g_logger.error("Auto walk path too great, the maximum number of directions is 127");
        return;
    }

    if(dirs.size() == 0)
        return;

    // must cancel follow before any new walk
    if(isFollowing())
        cancelFollow();

    Otc::Direction direction = dirs.front();
    if(m_localPlayer->canWalk(direction)) {
        TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
        if(toTile && toTile->isWalkable() && !m_localPlayer->isAutoWalking())
            m_localPlayer->preWalk(direction);
    }

    m_protocolGame->sendAutoWalk(dirs);

    g_lua.callGlobalField("g_game", "onAutoWalk", dirs);
}
Beispiel #2
0
void Game::stop()
{
    if(!canPerformGameAction())
        return;

    if(isFollowing())
        cancelFollow();

    m_protocolGame->sendStop();
}
Beispiel #3
0
void Game::attack(const CreaturePtr& creature)
{
    if(!canPerformGameAction() || creature == m_localPlayer)
        return;

    if(creature && creature == m_attackingCreature) {
        cancelAttack();
        return;
    }

    if(creature && isFollowing())
        cancelFollow();

    setAttackingCreature(creature);
    m_protocolGame->sendAttack(creature ? creature->getId() : 0, ++m_seq);
}
Beispiel #4
0
void Game::attack(CreaturePtr creature)
{
    if(!canPerformGameAction() || creature == m_localPlayer)
        return;

    // cancel when attacking again
    if(creature && creature == m_attackingCreature)
        creature = nullptr;

    if(creature && isFollowing())
        cancelFollow();

    setAttackingCreature(creature);
    m_localPlayer->stopAutoWalk();

    if(m_protocolVersion >= 963) {
        if(creature)
            m_seq = creature->getId();
    } else
        m_seq++;

    m_protocolGame->sendAttack(creature ? creature->getId() : 0, m_seq);
}
Beispiel #5
0
void Game::autoWalk(std::vector<Otc::Direction> dirs)
{
    if(!canPerformGameAction())
        return;

    // protocol limits walk path up to 255 directions
    if(dirs.size() > 127) {
        g_logger.error("Auto walk path too great, the maximum number of directions is 127");
        return;
    }

    if(dirs.size() == 0)
        return;

    // must cancel follow before any new walk
    if(isFollowing())
        cancelFollow();

    auto it = dirs.begin();
    Otc::Direction direction = *it;
    if(!m_localPlayer->canWalk(direction))
        return;

    TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
    if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
        m_localPlayer->preWalk(direction);

        if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
            forceWalk(direction);
            dirs.erase(it);
        }
    }

    g_lua.callGlobalField("g_game", "onAutoWalk", dirs);

    m_protocolGame->sendAutoWalk(dirs);
}
Beispiel #6
0
void Game::walk(Otc::Direction direction)
{
    if(!canPerformGameAction())
        return;

    // must cancel follow before any new walk
    if(isFollowing())
        cancelFollow();

    // msut cancel auto walking and wait next try
    if(m_localPlayer->isAutoWalking()) {
        m_protocolGame->sendStop();
        return;
    }

    if(!m_localPlayer->canWalk(direction))
        return;

    Position toPos = m_localPlayer->getPosition().translatedToDirection(direction);
    TilePtr toTile = g_map.getTile(toPos);
    // only do prewalks to walkable tiles (like grounds and not walls)
    if(toTile && toTile->isWalkable())
        m_localPlayer->preWalk(direction);
    // check walk to another floor (e.g: when above 3 parcels)
    else {
        // check if can walk to a lower floor
        auto canChangeFloorDown = [&]() -> bool {
            Position pos = toPos;
            if(!pos.down())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(toTile && toTile->hasElevation(3))
                return true;
            return false;
        };

        // check if can walk to a higher floor
        auto canChangeFloorUp = [&]() -> bool {
            TilePtr fromTile = m_localPlayer->getTile();
            if(!fromTile || !fromTile->hasElevation(3))
                return false;
            Position pos = toPos;
            if(!pos.up())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(!toTile || !toTile->isWalkable())
                return false;
            return true;
        };

        if(canChangeFloorDown() || canChangeFloorUp() ||
            (!toTile || toTile->isEmpty())) {
            m_localPlayer->lockWalk();
        } else
            return;
    }

    forceWalk(direction);

    g_lua.callGlobalField("g_game", "onWalk", direction);
}
Beispiel #7
0
bool Game::walk(Otc::Direction direction, bool dash)
{
    if(!canPerformGameAction())
        return false;

    // must cancel follow before any new walk
    if(isFollowing())
        cancelFollow();

    // must cancel auto walking, and wait next try
    if(m_localPlayer->isAutoWalking() || m_localPlayer->isServerWalking()) {
        m_protocolGame->sendStop();
        if(m_localPlayer->isAutoWalking())
            m_localPlayer->stopAutoWalk();
        return false;
    }

    if(dash) {
        if(m_localPlayer->isWalking() && m_dashTimer.ticksElapsed() < std::max<int>(m_localPlayer->getStepDuration(false, direction) - m_ping, 30))
            return false;
    }
    else {
        // check we can walk and add new walk event if false
        if(!m_localPlayer->canWalk(direction)) {
            if(m_lastWalkDir != direction) {
                // must add a new walk event
                float ticks = m_localPlayer->getStepTicksLeft();
                if(ticks <= 0) { ticks = 1; }

                if(m_walkEvent) {
                    m_walkEvent->cancel();
                    m_walkEvent = nullptr;
                }
                m_walkEvent = g_dispatcher.scheduleEvent([=] { walk(direction, false); }, ticks);
            }
            return false;
        }
    }

    Position toPos = m_localPlayer->getPosition().translatedToDirection(direction);
    TilePtr toTile = g_map.getTile(toPos);
    // only do prewalks to walkable tiles (like grounds and not walls)
    if(toTile && toTile->isWalkable()) {
        m_localPlayer->preWalk(direction);
    // check walk to another floor (e.g: when above 3 parcels)
    } else {
        // check if can walk to a lower floor
        auto canChangeFloorDown = [&]() -> bool {
            Position pos = toPos;
            if(!pos.down())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(toTile && toTile->hasElevation(3))
                return true;
            return false;
        };

        // check if can walk to a higher floor
        auto canChangeFloorUp = [&]() -> bool {
            TilePtr fromTile = m_localPlayer->getTile();
            if(!fromTile || !fromTile->hasElevation(3))
                return false;
            Position pos = toPos;
            if(!pos.up())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(!toTile || !toTile->isWalkable())
                return false;
            return true;
        };

        if(canChangeFloorDown() || canChangeFloorUp() ||
            (!toTile || toTile->isEmpty())) {
            m_localPlayer->lockWalk();
        } else
            return false;
    }

    m_localPlayer->stopAutoWalk();

    g_lua.callGlobalField("g_game", "onWalk", direction, dash);

    forceWalk(direction);
    if(dash)
      m_dashTimer.restart();

    m_lastWalkDir = direction;
    return true;
}
Beispiel #8
0
bool Game::dashWalk(Otc::Direction direction)
{
    if(!canPerformGameAction())
        return false;

    // must cancel follow before any new walk
    if(isFollowing())
        cancelFollow();

    // must cancel auto walking
    if(m_localPlayer->isAutoWalking()) {
        m_protocolGame->sendStop();
        m_localPlayer->stopAutoWalk();
    }

    if(m_localPlayer->isWalking() && m_dashTimer.ticksElapsed() < std::max<int>(m_localPlayer->getStepDuration(false, direction) - m_ping, 30))
        return false;

    Position toPos = m_localPlayer->getPosition().translatedToDirection(direction);
    TilePtr toTile = g_map.getTile(toPos);
    // only do prewalks to walkable tiles (like grounds and not walls)
    if(toTile && toTile->isWalkable()) {
        if(!m_localPlayer->isWalking() && m_localPlayer->getWalkTicksElapsed() >= m_localPlayer->getStepDuration() + 100)
            m_localPlayer->preWalk(direction);
    // check walk to another floor (e.g: when above 3 parcels)
    } else {
        // check if can walk to a lower floor
        auto canChangeFloorDown = [&]() -> bool {
            Position pos = toPos;
            if(!pos.down())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(toTile && toTile->hasElevation(3))
                return true;
            return false;
        };

        // check if can walk to a higher floor
        auto canChangeFloorUp = [&]() -> bool {
            TilePtr fromTile = m_localPlayer->getTile();
            if(!fromTile || !fromTile->hasElevation(3))
                return false;
            Position pos = toPos;
            if(!pos.up())
                return false;
            TilePtr toTile = g_map.getTile(pos);
            if(!toTile || !toTile->isWalkable())
                return false;
            return true;
        };

        if(canChangeFloorDown() || canChangeFloorUp() ||
            (!toTile || toTile->isEmpty())) {
            m_localPlayer->lockWalk();
        } else
            return false;
    }

    forceWalk(direction);
    m_dashTimer.restart();
    m_lastWalkDir = direction;
    return true;
}