diff --git a/data/images/ui/button_topgame.png b/data/images/ui/button_topgame.png index 7820d506..c6f115f6 100644 Binary files a/data/images/ui/button_topgame.png and b/data/images/ui/button_topgame.png differ diff --git a/modules/game_battle/battle.lua b/modules/game_battle/battle.lua index ddae046b..cdce4a56 100644 --- a/modules/game_battle/battle.lua +++ b/modules/game_battle/battle.lua @@ -209,7 +209,7 @@ function addCreature(creature) battleButton:setup(creature) battleButton.onHoverChange = onBattleButtonHoverChange - battleButton.onMouseRelease = onMouseRelease + battleButton.onMouseRelease = onBattleButtonMouseRelease battleButtonsByCreaturesList[creatureId] = battleButton @@ -225,7 +225,27 @@ function addCreature(creature) end end -function onMouseRelease(self, mousePosition, mouseButton) +function removeAllCreatures() + for i, v in pairs(battleButtonsByCreaturesList) do + removeCreature(v.creature) + end +end + +function removeCreature(creature) + if hasCreature(creature) then + local creatureId = creature:getId() + + if lastBattleButtonSwitched == battleButtonsByCreaturesList[creatureId] then + lastBattleButtonSwitched = nil + end + + battleButtonsByCreaturesList[creatureId].creature:hideStaticSquare() + battleButtonsByCreaturesList[creatureId]:destroy() + battleButtonsByCreaturesList[creatureId] = nil + end +end + +function onBattleButtonMouseRelease(self, mousePosition, mouseButton) if mouseWidget.cancelNextRelease then mouseWidget.cancelNextRelease = false return false @@ -249,26 +269,6 @@ function onMouseRelease(self, mousePosition, mouseButton) return false end -function removeAllCreatures() - for i, v in pairs(battleButtonsByCreaturesList) do - removeCreature(v.creature) - end -end - -function removeCreature(creature) - if hasCreature(creature) then - local creatureId = creature:getId() - - if lastBattleButtonSwitched == battleButtonsByCreaturesList[creatureId] then - lastBattleButtonSwitched = nil - end - - battleButtonsByCreaturesList[creatureId].creature:hideStaticSquare() - battleButtonsByCreaturesList[creatureId]:destroy() - battleButtonsByCreaturesList[creatureId] = nil - end -end - function onBattleButtonHoverChange(widget, hovered) if widget.isBattleButton then widget.isHovered = hovered diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index ba14d6d1..2da23331 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -49,7 +49,7 @@ function init() gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel') connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange }) - logoutButton = modules.client_topmenu.addLeftButton('logoutButton', 'Logout', '/images/topbuttons/logout', tryLogout, true) + logoutButton = modules.client_topmenu.addLeftButton('logoutButton', 'Exit', '/images/topbuttons/logout', tryLogout, true) bindKeys() @@ -111,6 +111,7 @@ function terminate() end function onGameStart() + logoutButton:setTooltip('Logout') show() -- open tibia has delay in auto walking @@ -120,6 +121,7 @@ function onGameStart() end function onGameEnd() + logoutButton:setTooltip('Exit') hide() end diff --git a/src/client/const.h b/src/client/const.h index 2c6d63f8..afee6ada 100644 --- a/src/client/const.h +++ b/src/client/const.h @@ -40,7 +40,8 @@ namespace Otc STATIC_DURATION_PER_CHARACTER = 60, MIN_STATIC_TEXT_DURATION = 3000, MAX_STATIC_TEXT_WIDTH = 200, - MAX_AUTOWALK_STEPS_RETRY = 10 + MAX_AUTOWALK_STEPS_RETRY = 10, + MAX_AUTOWALK_DIST = 127 }; enum DrawFlags { diff --git a/src/client/game.cpp b/src/client/game.cpp index b1739d58..388abb2a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -717,7 +717,7 @@ void Game::look(const ThingPtr& thing) if(thing->isCreature() && m_protocolVersion >= 961) m_protocolGame->sendLookCreature(thing->getId()); else - m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackpos()); + m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackPos()); } void Game::move(const ThingPtr& thing, const Position& toPos, int count) @@ -734,7 +734,7 @@ void Game::move(const ThingPtr& thing, const Position& toPos, int count) id = Proto::Creature; } - m_protocolGame->sendMove(thing->getPosition(), id, thing->getStackpos(), toPos, count); + m_protocolGame->sendMove(thing->getPosition(), id, thing->getStackPos(), toPos, count); } void Game::moveToParentContainer(const ThingPtr& thing, int count) @@ -751,7 +751,7 @@ void Game::rotate(const ThingPtr& thing) if(!canPerformGameAction() || !thing) return; - m_protocolGame->sendRotateItem(thing->getPosition(), thing->getId(), thing->getStackpos()); + m_protocolGame->sendRotateItem(thing->getPosition(), thing->getId(), thing->getStackPos()); } void Game::use(const ThingPtr& thing) @@ -765,7 +765,7 @@ void Game::use(const ThingPtr& thing) // some itens, e.g. parcel, are not set as containers but they are. // always try to use these items in free container slots. - m_protocolGame->sendUseItem(pos, thing->getId(), thing->getStackpos(), findEmptyContainerId()); + m_protocolGame->sendUseItem(pos, thing->getId(), thing->getStackPos(), findEmptyContainerId()); } void Game::useInventoryItem(int itemId) @@ -788,9 +788,9 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing) pos = Position(0xFFFF, 0, 0); // means that is a item in inventory if(toThing->isCreature()) - m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackpos(), toThing->getId()); + m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId()); else - m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackpos(), toThing->getPosition(), toThing->getId(), toThing->getStackpos()); + m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackPos(), toThing->getPosition(), toThing->getId(), toThing->getStackPos()); } void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing) @@ -803,7 +803,7 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing) if(toThing->isCreature()) m_protocolGame->sendUseOnCreature(pos, itemId, 0, toThing->getId()); else - m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackpos()); + m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackPos()); } int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer) @@ -817,7 +817,7 @@ int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer) else id = previousContainer->getId(); - m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), id); + m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackPos(), id); return id; } @@ -1121,7 +1121,7 @@ void Game::requestTrade(const ItemPtr& item, const CreaturePtr& creature) { if(!canPerformGameAction() || !item || !creature) return; - m_protocolGame->sendRequestTrade(item->getPosition(), item->getId(), item->getStackpos(), creature->getId()); + m_protocolGame->sendRequestTrade(item->getPosition(), item->getId(), item->getStackPos(), creature->getId()); } void Game::inspectTrade(bool counterOffer, int index) diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index 556d3550..9b6677c6 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -184,33 +184,41 @@ void LocalPlayer::cancelWalk(Otc::Direction direction) void LocalPlayer::updateAutoWalkSteps(bool walkFailed) { - if(!m_autoWalking) { - m_autoWalkSteps.clear(); - return; - } - if(!m_lastAutoWalkDestination.isValid()) { return; } - // for now this cannot be done from lua, due to bot protection - m_autoWalkSteps.push_back(m_lastAutoWalkDestination); - if(m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed) { + m_autoWalkSteps.push_back(m_position); + if(m_lastAutoWalkDestination != m_position && (m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed)) { autoWalk(m_lastAutoWalkDestination); } + else if(m_position == m_lastAutoWalkDestination && !m_autoWalkQueue.empty()) { + m_autoWalkQueue.pop_back(); + + // task the next destination + if(!m_autoWalkQueue.empty()) { + std::vector destinations = m_position.translatedToDirections(m_autoWalkQueue.back()); + autoWalk(destinations.back()); + } + } } bool LocalPlayer::autoWalk(const Position& destination) { m_autoWalkSteps.clear(); - m_lastAutoWalkDestination = destination; - std::tuple, Otc::PathFindResult> result = g_map.findPath(m_position, destination, 127, Otc::PathFindAllowNullTiles); + + std::tuple, Otc::PathFindResult> result = g_map.findPath(m_position, destination, 1000, Otc::PathFindAllowNullTiles); std::vector dirs = std::get<0>(result); if(dirs.size() == 0) return false; + if(dirs.size() > Otc::MAX_AUTOWALK_DIST) { + dirs = calculateAutoWalk(dirs); + m_lastAutoWalkDestination = m_position.translatedToDirections(dirs).back(); + } + g_game.autoWalk(dirs); return true; } @@ -219,6 +227,7 @@ void LocalPlayer::stopAutoWalkUpdate() { m_lastAutoWalkDestination = Position(); m_autoWalkSteps.clear(); + m_autoWalkQueue.clear(); } void LocalPlayer::stopWalk() @@ -229,6 +238,29 @@ void LocalPlayer::stopWalk() m_lastPrewalkDestionation = Position(); } +std::vector LocalPlayer::calculateAutoWalk(std::vector& dirs) +{ + if(dirs.size() > Otc::MAX_AUTOWALK_DIST) { + // populate auto walk queue + m_autoWalkQueue.clear(); + size_t blocks = std::ceil((float)dirs.size() / Otc::MAX_AUTOWALK_DIST); + + size_t size = Otc::MAX_AUTOWALK_DIST; + for(size_t i = 0, offset=0 ; i < blocks ; ++i) { + std::vector::iterator next = dirs.begin() + offset; + if((offset + size) < dirs.size()) + m_autoWalkQueue.push_back(std::vector(next, next + size)); + else + m_autoWalkQueue.push_back(std::vector(next, dirs.end())); + offset += size; + } + std::reverse(m_autoWalkQueue.begin(), m_autoWalkQueue.end()); + + return m_autoWalkQueue.back(); + } + return dirs; +} + void LocalPlayer::updateWalkOffset(int totalPixelsWalked) { // pre walks offsets are calculated in the oposite direction diff --git a/src/client/localplayer.h b/src/client/localplayer.h index f8fbf19a..3c7feb36 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -43,6 +43,7 @@ public: void updateAutoWalkSteps(bool walkFailed = false); bool autoWalk(const Position& destination); bool canWalk(Otc::Direction direction); + std::vector calculateAutoWalk(std::vector& dirs); void setStates(int states); void setSkill(Otc::Skill skill, int level, int levelPercent); @@ -145,6 +146,7 @@ private: std::array m_skillsLevelPercent; std::vector m_spells; std::vector m_autoWalkSteps; + std::vector > m_autoWalkQueue; int m_states; int m_vocation; diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index 5b4f2662..63813986 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -285,6 +285,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("getId", &Thing::getId); g_lua.bindClassMemberFunction("getPosition", &Thing::getPosition); g_lua.bindClassMemberFunction("getStackPriority", &Thing::getStackPriority); + g_lua.bindClassMemberFunction("getStackPos", &Thing::getStackPos); g_lua.bindClassMemberFunction("getAnimationPhases", &Thing::getAnimationPhases); g_lua.bindClassMemberFunction("getTile", &Thing::getTile); g_lua.bindClassMemberFunction("isItem", &Thing::isItem); @@ -486,7 +487,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("getThing", &Tile::getThing); g_lua.bindClassMemberFunction("getThings", &Tile::getThings); g_lua.bindClassMemberFunction("getItems", &Tile::getItems); - g_lua.bindClassMemberFunction("getThingStackpos", &Tile::getThingStackpos); + g_lua.bindClassMemberFunction("getThingStackPos", &Tile::getThingStackPos); g_lua.bindClassMemberFunction("getThingCount", &Tile::getThingCount); g_lua.bindClassMemberFunction("getTopThing", &Tile::getTopThing); g_lua.bindClassMemberFunction("removeThing", &Tile::removeThing); diff --git a/src/client/position.h b/src/client/position.h index e1028386..3f95ef0f 100644 --- a/src/client/position.h +++ b/src/client/position.h @@ -28,6 +28,8 @@ #include #include +#include + class Position { public: @@ -122,6 +124,22 @@ public: return angle; } + std::vector translatedToDirections(const std::vector& dirs) const { + Position lastPos = *this; + std::vector positions; + + positions.push_back(lastPos); + + for(auto dir : dirs) { + if(lastPos.isValid()) { + positions.push_back(lastPos); + } + lastPos = lastPos.translatedToDirection(dir); + } + + return positions; + } + Otc::Direction getDirectionFromPosition(const Position& position) const { int dx = position.x - x; int dy = position.y - y; diff --git a/src/client/protocolgame.h b/src/client/protocolgame.h index 2fa81bd1..f357450a 100644 --- a/src/client/protocolgame.h +++ b/src/client/protocolgame.h @@ -65,7 +65,7 @@ public: void sendAcceptTrade(); void sendRejectTrade(); void sendUseItem(const Position& position, int itemId, int stackpos, int index); - void sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos); + void sendUseItemWith(const Position& fromPos, int itemId, int fromStackPos, const Position& toPos, int toThingId, int toStackPos); void sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId); void sendRotateItem(const Position& pos, int thingId, int stackpos); void sendCloseContainer(int containerId); diff --git a/src/client/protocolgameparse.cpp b/src/client/protocolgameparse.cpp index c6564558..3b89724a 100644 --- a/src/client/protocolgameparse.cpp +++ b/src/client/protocolgameparse.cpp @@ -553,7 +553,7 @@ void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg) } Position pos = thing->getPosition(); - int stackpos = thing->getStackpos(); + int stackpos = thing->getStackPos(); if(!g_map.removeThing(thing)) { g_logger.traceError("unable to remove thing"); diff --git a/src/client/protocolgamesend.cpp b/src/client/protocolgamesend.cpp index c93c864e..76ef2ab5 100644 --- a/src/client/protocolgamesend.cpp +++ b/src/client/protocolgamesend.cpp @@ -390,16 +390,16 @@ void ProtocolGame::sendUseItem(const Position& position, int itemId, int stackpo send(msg); } -void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos) +void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackPos, const Position& toPos, int toThingId, int toStackPos) { OutputMessagePtr msg(new OutputMessage); msg->addU8(Proto::ClientUseItemWith); addPosition(msg, fromPos); msg->addU16(itemId); - msg->addU8(fromStackpos); + msg->addU8(fromStackPos); addPosition(msg, toPos); msg->addU16(toThingId); - msg->addU8(toStackpos); + msg->addU8(toStackPos); send(msg); } diff --git a/src/client/thing.cpp b/src/client/thing.cpp index 2d0261da..27cedada 100644 --- a/src/client/thing.cpp +++ b/src/client/thing.cpp @@ -73,12 +73,12 @@ ContainerPtr Thing::getParentContainer() return nullptr; } -int Thing::getStackpos() +int Thing::getStackPos() { if(m_position.x == 65535 && isItem()) // is inside a container return m_position.z; else if(const TilePtr& tile = getTile()) - return tile->getThingStackpos(static_self_cast()); + return tile->getThingStackPos(static_self_cast()); else { g_logger.traceError("got a thing with invalid stackpos"); return -1; diff --git a/src/client/thing.h b/src/client/thing.h index 7a660530..03934250 100644 --- a/src/client/thing.h +++ b/src/client/thing.h @@ -46,7 +46,7 @@ public: int getStackPriority(); const TilePtr& getTile(); ContainerPtr getParentContainer(); - int getStackpos(); + int getStackPos(); virtual bool isItem() { return false; } virtual bool isEffect() { return false; } diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 613e437c..015e8c22 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -276,7 +276,7 @@ bool Tile::hasThing(const ThingPtr& thing) return std::find(m_things.begin(), m_things.end(), thing) != m_things.end(); } -int Tile::getThingStackpos(const ThingPtr& thing) +int Tile::getThingStackPos(const ThingPtr& thing) { for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos) if(thing == m_things[stackpos]) diff --git a/src/client/tile.h b/src/client/tile.h index 4ed74845..eb662e22 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -74,7 +74,7 @@ public: ThingPtr getThing(int stackPos); EffectPtr getEffect(uint16 id); bool hasThing(const ThingPtr& thing); - int getThingStackpos(const ThingPtr& thing); + int getThingStackPos(const ThingPtr& thing); ThingPtr getTopThing(); ThingPtr getTopLookThing();