From a1a8d28f5cc3e3ee73258bebca74a1a9cc13adb4 Mon Sep 17 00:00:00 2001 From: BeniS Date: Wed, 9 Jan 2013 04:32:37 +1300 Subject: [PATCH] Auto walker update must be done from C++ not lua due to bot protection. * Moved the auto walk checker to the source. * Implemented a temporary fix for findPath method (will now choose other tiles over null tiles). --- modules/game_interface/gameinterface.lua | 59 +++----------------- modules/game_interface/widgets/uigamemap.lua | 1 - modules/game_interface/widgets/uiitem.lua | 1 - modules/game_minimap/minimap.lua | 5 +- modules/gamelib/player.lua | 44 --------------- src/otclient/const.h | 3 +- src/otclient/game.cpp | 8 ++- src/otclient/localplayer.cpp | 49 ++++++++++++++++ src/otclient/localplayer.h | 7 +++ src/otclient/luafunctions.cpp | 4 ++ src/otclient/map.cpp | 8 +-- 11 files changed, 84 insertions(+), 105 deletions(-) diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index 801e3a5f..a3eb87cc 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -31,15 +31,9 @@ function init() connect(g_game, { onGameStart = show, onGameEnd = hide, - onLoginAdvice = onLoginAdvice, - onWalk = onWalk + onLoginAdvice = onLoginAdvice }, true) - connect(LocalPlayer, { - onCancelWalk = onCancelWalk, - onPositionChange = onPositionChange - }) - gameRootPanel = g_ui.displayUI('gameinterface.otui') gameRootPanel:hide() gameRootPanel:lower() @@ -92,13 +86,12 @@ function bindKeys() g_keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) - g_keyboard.bindKeyPress('Escape', function() cancelAutoWalkCheck() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) + g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel, 250) g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel, 250) g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel) - g_keyboard.bindKeyDown('Ctrl+;', toggleDash, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+.', toggleAspectRatio, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+N', function() gameMapPanel:setDrawTexts(not gameMapPanel:isDrawingTexts()) end, gameRootPanel) end @@ -193,45 +186,6 @@ function tryLogout() anchor=AnchorHorizontalCenter}, yesCallback, noCallback) end -function onWalk(dir) - cancelAutoWalkCheck() -end - -function onPositionChange(newPos, oldPos) - checkAutoWalking() -end - -function onCancelWalk(dir) - checkAutoWalking(true) -end - -function checkAutoWalking(stepCancelled) - local stepCancelled = stepCancelled or false - local player = g_game.getLocalPlayer() - if not player:isAutoWalking() then - player:clearWalkSteps() - end - - local lastDestination = player:getLastDestination() - if not lastDestination then - return -- auto walk has been cancelled - end - player:setWalkStep(lastDestination) - - local playerPos = player:getPosition() - local walkSteps = player:getWalkSteps(lastDestination) - - if (not table.empty(walkSteps) and #walkSteps >= WALK_STEPS_RETRY) or stepCancelled then - if lastDestination then player:autoWalk(lastDestination) end - end -end - -function cancelAutoWalkCheck() - local player = g_game.getLocalPlayer() - player:setLastDestination(nil) -- cancel retries - player:clearWalkSteps() -end - function smartWalk(defaultDir) local rebindKey = false local lastKey = arrowKeys[lastWalkDir] @@ -281,7 +235,6 @@ function smartWalk(defaultDir) else g_game.walk(dir) end - cancelAutoWalkCheck() -- cancel the auto walker check if rebindKey then g_keyboard.bindKeyPress(lastKey, function() smartWalk(lastWalkDir) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) @@ -565,12 +518,14 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u end end + local player = g_game.getLocalPlayer() + player:stopAutoWalkUpdate() + if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then - local player = g_game.getLocalPlayer() if not player:autoWalk(autoWalkPos) then - return false + modules.game_textmessage.displayStatusMessage(tr('There is no way.')) + return true end - return true end return false diff --git a/modules/game_interface/widgets/uigamemap.lua b/modules/game_interface/widgets/uigamemap.lua index 3557f75a..8072ff61 100644 --- a/modules/game_interface/widgets/uigamemap.lua +++ b/modules/game_interface/widgets/uigamemap.lua @@ -86,7 +86,6 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton) local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, multiUseThing) if ret then - modules.game_interface.cancelAutoWalkCheck() self.cancelNextRelease = true end diff --git a/modules/game_interface/widgets/uiitem.lua b/modules/game_interface/widgets/uiitem.lua index b6fb4c8b..af067ed6 100644 --- a/modules/game_interface/widgets/uiitem.lua +++ b/modules/game_interface/widgets/uiitem.lua @@ -87,7 +87,6 @@ function UIItem:onMouseRelease(mousePosition, mouseButton) self.cancelNextRelease = true return true elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item) then - modules.game_interface.cancelAutoWalkCheck() return true end return false diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index 73aad9b9..fd5e7c95 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -383,7 +383,10 @@ function onMinimapMouseRelease(self, mousePosition, mouseButton) local pos = self:getPosition(mousePosition) if pos and mouseButton == MouseLeftButton and self:isPressed() then local player = g_game.getLocalPlayer() - if not player:autoWalk(pos) then return false end + if not player:autoWalk(pos) then + modules.game_textmessage.displayStatusMessage(tr('There is no way.')) + return false + end return true end return false diff --git a/modules/gamelib/player.lua b/modules/gamelib/player.lua index 7576926c..b2b89c6e 100644 --- a/modules/gamelib/player.lua +++ b/modules/gamelib/player.lua @@ -98,47 +98,3 @@ function Player:dismount() g_game.mount(false) end end - -function Player:getLastDestination() - return self.lastDestination -end - -function Player:setLastDestination(destination) - self.lastDestination = destination -end - -function Player:getWalkSteps(destination) - if not self.walkSteps or not destination then - return nil - end - return self.walkSteps[destination] -end - -function Player:setWalkStep(destination) - if not self.walkSteps then - self.walkSteps = {} - end - if destination then - if not self.walkSteps[destination] then - self.walkSteps[destination] = {} - end - table.insert(self.walkSteps[destination], true) - end -end - -function Player:clearWalkSteps() - self.walkSteps = {} -end - -function Player:autoWalk(destination) - self:clearWalkSteps() - self:setLastDestination(destination) - local dirs = g_map.findPath(self:getPosition(), destination, 127, PathFindFlags.AllowNullTiles) - - if #dirs == 0 then - modules.game_textmessage.displayStatusMessage(tr('There is no way.')) - return false - end - g_game.autoWalk(dirs) - return true -end \ No newline at end of file diff --git a/src/otclient/const.h b/src/otclient/const.h index 745cb392..72e43b01 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -47,7 +47,8 @@ namespace Otc ANIMATED_TEXT_DURATION = 1000, STATIC_DURATION_PER_CHARACTER = 60, MIN_STATIC_TEXT_DURATION = 3000, - MAX_STATIC_TEXT_WIDTH = 200 + MAX_STATIC_TEXT_WIDTH = 200, + MAX_AUTOWALK_STEPS_RETRY = 10 }; enum DrawFlags { diff --git a/src/otclient/game.cpp b/src/otclient/game.cpp index 22f6730c..99512104 100644 --- a/src/otclient/game.cpp +++ b/src/otclient/game.cpp @@ -158,7 +158,7 @@ void Game::processGameStart() m_protocolGame->sendPing(); disableBotCall(); } - }, 3000); + }, 2000); } } @@ -564,6 +564,8 @@ bool Game::walk(Otc::Direction direction) return false; } + m_localPlayer->stopAutoWalkUpdate(); + g_lua.callGlobalField("g_game", "onWalk", direction); forceWalk(direction); @@ -824,6 +826,7 @@ void Game::attack(CreaturePtr creature) cancelFollow(); setAttackingCreature(creature); + m_localPlayer->stopAutoWalkUpdate(); if(m_protocolVersion >= 963) { if(creature) @@ -847,6 +850,7 @@ void Game::follow(CreaturePtr creature) cancelAttack(); setFollowingCreature(creature); + m_localPlayer->stopAutoWalkUpdate(); if(m_protocolVersion >= 963) { if(creature) @@ -867,6 +871,8 @@ void Game::cancelAttackAndFollow() if(isAttacking()) setAttackingCreature(nullptr); + m_localPlayer->stopAutoWalkUpdate(); + m_protocolGame->sendCancelAttackAndFollow(); g_lua.callGlobalField("g_game", "onCancelAttackAndFollow"); diff --git a/src/otclient/localplayer.cpp b/src/otclient/localplayer.cpp index 50768f26..f3e5a07f 100644 --- a/src/otclient/localplayer.cpp +++ b/src/otclient/localplayer.cpp @@ -161,12 +161,54 @@ void LocalPlayer::cancelWalk(Otc::Direction direction) if(direction != Otc::InvalidDirection) setDirection(direction); + updateAutoWalkSteps(true); + callLuaField("onCancelWalk", 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) { + autoWalk(m_lastAutoWalkDestination); + } +} + +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::vector dirs = std::get<0>(result); + if(dirs.size() == 0) + return false; + + g_game.autoWalk(dirs); + return true; +} + +void LocalPlayer::stopAutoWalkUpdate() +{ + m_lastAutoWalkDestination = Position(); + m_autoWalkSteps.clear(); +} + void LocalPlayer::stopWalk() { Creature::stopWalk(); // will call terminateWalk + m_lastPrewalkDone = true; m_lastPrewalkDestionation = Position(); } @@ -231,6 +273,13 @@ void LocalPlayer::onAppear() lockWalk(); } +void LocalPlayer::onPositionChange(const Position& newPos, const Position& oldPos) +{ + Creature::onPositionChange(newPos, oldPos); + + updateAutoWalkSteps(); +} + void LocalPlayer::setStates(int states) { if(m_states != states) { diff --git a/src/otclient/localplayer.h b/src/otclient/localplayer.h index f362f883..a15b602a 100644 --- a/src/otclient/localplayer.h +++ b/src/otclient/localplayer.h @@ -37,6 +37,9 @@ public: void unlockWalk() { m_walkLockExpiration = 0; } void lockWalk(int millis = 250); + void stopAutoWalkUpdate(); + void updateAutoWalkSteps(bool walkFailed = false); + bool autoWalk(const Position& destination); bool canWalk(Otc::Direction direction); void setStates(int states); @@ -87,6 +90,7 @@ public: double getOfflineTrainingTime() { return m_offlineTrainingTime; } std::vector getSpells() { return m_spells; } ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; } + std::vector getAutoWalkSteps() { return m_autoWalkSteps; } bool hasSight(const Position& pos); bool isKnown() { return m_known; } @@ -99,6 +103,7 @@ public: bool isLocalPlayer() { return true; } virtual void onAppear(); + virtual void onPositionChange(const Position& newPos, const Position& oldPos); protected: void walk(const Position& oldPos, const Position& newPos); @@ -117,6 +122,7 @@ private: // walk related Timer m_walkPingTimer; Position m_lastPrewalkDestionation; + Position m_lastAutoWalkDestination; ScheduledEventPtr m_autoWalkEndEvent; ticks_t m_walkLockExpiration; int m_lastWalkPing; @@ -136,6 +142,7 @@ private: std::array m_skillsBaseLevel; std::array m_skillsLevelPercent; std::vector m_spells; + std::vector m_autoWalkSteps; int m_states; int m_vocation; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index cfe69c18..c280b8c3 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -459,6 +459,10 @@ void OTClient::registerLuaFunctions() g_lua.bindClassMemberFunction("isPreWalking", &LocalPlayer::isPreWalking); g_lua.bindClassMemberFunction("hasSight", &LocalPlayer::hasSight); g_lua.bindClassMemberFunction("isAutoWalking", &LocalPlayer::isAutoWalking); + g_lua.bindClassMemberFunction("stopAutoWalkUpdate", &LocalPlayer::stopAutoWalkUpdate); + g_lua.bindClassMemberFunction("updateAutoWalkSteps", &LocalPlayer::updateAutoWalkSteps); + g_lua.bindClassMemberFunction("autoWalk", &LocalPlayer::autoWalk); + g_lua.bindClassMemberFunction("getAutoWalkSteps", &LocalPlayer::getAutoWalkSteps); g_lua.registerClass(); g_lua.bindClassMemberFunction("clean", &Tile::clean); diff --git a/src/otclient/map.cpp b/src/otclient/map.cpp index a2dc1de8..b06c7008 100644 --- a/src/otclient/map.cpp +++ b/src/otclient/map.cpp @@ -506,6 +506,7 @@ std::tuple, Otc::PathFindResult> Map::findPath(const Position neighborPos = currentNode->pos.translated(i, j); const TilePtr& tile = getTile(neighborPos); + float walkFactor = 0; if(neighborPos != goalPos) { /* Known Issue with Otc::PathFindAllowNullTiles flag: @@ -514,7 +515,7 @@ std::tuple, Otc::PathFindResult> Map::findPath(const but it is breaking normal path finding. */ if(!(flags & Otc::PathFindAllowNullTiles) && !tile) - continue; + walkFactor = 1.0f; if(tile) { if(!(flags & Otc::PathFindAllowCreatures) && tile->hasCreature()) continue; @@ -525,12 +526,11 @@ std::tuple, Otc::PathFindResult> Map::findPath(const } } - float walkFactor; Otc::Direction walkDir = currentNode->pos.getDirectionFromPosition(neighborPos); if(walkDir >= Otc::NorthEast) - walkFactor = 3.0f; + walkFactor += 3.0f; else - walkFactor = 1.0f; + walkFactor += 1.0f; int groundSpeed = tile ? tile->getGroundSpeed() : 100; float cost = currentNode->cost + (groundSpeed * walkFactor) / 100.0f;