diff --git a/modules/client_options/game.otui b/modules/client_options/game.otui index 2d81ea8e..63d73613 100644 --- a/modules/client_options/game.otui +++ b/modules/client_options/game.otui @@ -12,6 +12,11 @@ Panel !text: tr('Enable smart walking') !tooltip: tr('Will detect when to use diagonal step based on the\nkeys you are pressing') + OptionCheckBox + id: dashWalk + !text: tr('Enable dash walking') + !tooltip: tr('Will boost your walk on high speed characters') + OptionCheckBox id: showPing !text: tr('Show connection ping') diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index 4e7c7770..91459bba 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -5,6 +5,7 @@ local defaultOptions = { fullscreen = false, classicControl = false, smartWalk = false, + dashWalk = false, autoChaseOverride = true, showStatusMessagesInConsole = true, showEventMessagesInConsole = true, diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index 394f8117..7e27a223 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -15,14 +15,13 @@ limitZoom = false currentViewMode = 0 smartWalkDirs = {} smartWalkDir = nil -walkFunction = g_game.walk +walkFunction = nil function init() g_ui.importStyle('styles/countwindow') connect(g_game, { onGameStart = onGameStart, - onGMActions = onGMActions, onGameEnd = onGameEnd, onLoginAdvice = onLoginAdvice, }, true) @@ -119,7 +118,6 @@ function terminate() disconnect(g_game, { onGameStart = onGameStart, - onGMActions = onGMActions, onGameEnd = onGameEnd, onLoginAdvice = onLoginAdvice }) @@ -139,6 +137,16 @@ function onGameStart() else g_game.disableFeature(GameForceFirstAutoWalkStep) end + + addEvent(function() + if not limitZoom or g_game.isGM() then + gameMapPanel:setMaxZoomOut(513) + gameMapPanel:setLimitVisibleRange(false) + else + gameMapPanel:setMaxZoomOut(11) + gameMapPanel:setLimitVisibleRange(true) + end + end) end function onGameEnd() @@ -152,8 +160,6 @@ function show() gameRootPanel:show() gameRootPanel:focus() gameMapPanel:followCreature(g_game.getLocalPlayer()) - gameMapPanel:setMaxZoomOut(11) - gameMapPanel:setLimitVisibleRange(true) setupViewMode(0) updateStretchShrink() logoutButton:setTooltip(tr('Logout')) @@ -199,6 +205,7 @@ function onLoginAdvice(message) end function forceExit() + g_game.cancelLogin() scheduleEvent(exit, 10) return true end @@ -284,11 +291,16 @@ end function smartWalk(dir) if g_keyboard.getModifiers() == KeyboardNoModifier then - if smartWalkDir then - walkFunction(smartWalkDir) - else - walkFunction(dir) + local func = walkFunction + if not func then + if modules.client_options.getOption('dashWalk') then + func = g_game.dashWalk + else + func = g_game.walk + end end + local dire = smartWalkDir or dir + func(dire) return true end return false @@ -760,9 +772,3 @@ end function limitZoom() limitZoom = true end - -function onGMActions() - if not limitZoom then return end - gameMapPanel:setMaxZoomOut(513) - gameMapPanel:setLimitVisibleRange(false) -end diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index a387a58e..b3de05ce 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -50,6 +50,10 @@ function terminate() onGameEnd = offline, }) + disconnect(LocalPlayer, { + onPositionChange = updateCameraPosition + }) + local gameRootPanel = modules.game_interface.getRootPanel() g_keyboard.unbindKeyPress('Alt+Left', gameRootPanel) g_keyboard.unbindKeyPress('Alt+Right', gameRootPanel) diff --git a/src/client/creature.cpp b/src/client/creature.cpp index e3ede2bf..97cfd444 100644 --- a/src/client/creature.cpp +++ b/src/client/creature.cpp @@ -782,7 +782,7 @@ Point Creature::getDrawOffset() return drawOffset; } -int Creature::getStepDuration(bool ignoreDiagonal) +int Creature::getStepDuration(bool ignoreDiagonal, Otc::Direction dir) { int speed = m_speed; if(speed < 1) @@ -792,7 +792,13 @@ int Creature::getStepDuration(bool ignoreDiagonal) speed *= 2; int groundSpeed = 0; - Position tilePos = m_lastStepToPosition; + Position tilePos; + + if(dir == Otc::InvalidDirection) + tilePos = m_lastStepToPosition; + else + tilePos = m_position.translatedToDirection(dir); + if(!tilePos.isValid()) tilePos = m_position; const TilePtr& tile = g_map.getTile(tilePos); diff --git a/src/client/creature.h b/src/client/creature.h index cc39a22a..ff2c5258 100644 --- a/src/client/creature.h +++ b/src/client/creature.h @@ -85,7 +85,7 @@ public: uint8 getEmblem() { return m_emblem; } bool isPassable() { return m_passable; } Point getDrawOffset(); - int getStepDuration(bool ignoreDiagonal = false); + int getStepDuration(bool ignoreDiagonal = false, Otc::Direction dir = Otc::InvalidDirection); Point getWalkOffset() { return m_walkOffset; } Position getLastStepFromPosition() { return m_lastStepFromPosition; } Position getLastStepToPosition() { return m_lastStepToPosition; } diff --git a/src/client/game.cpp b/src/client/game.cpp index 3e5b8486..f3cef166 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -613,6 +613,70 @@ bool Game::walk(Otc::Direction direction) return true; } +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(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; +} + void Game::autoWalk(std::vector dirs) { if(!canPerformGameAction()) diff --git a/src/client/game.h b/src/client/game.h index 9590a8db..ac878009 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -143,6 +143,7 @@ public: // walk related bool walk(Otc::Direction direction); + bool dashWalk(Otc::Direction direction); void autoWalk(std::vector dirs); void forceWalk(Otc::Direction direction); void turn(Otc::Direction direction); @@ -325,6 +326,7 @@ private: uint m_pingSent; uint m_pingReceived; stdext::timer m_pingTimer; + Timer m_dashTimer; uint m_seq; int m_pingDelay; Otc::FightModes m_fightMode; diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index dc43d316..559811cf 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -149,6 +149,7 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "forceLogout", &Game::forceLogout, &g_game); g_lua.bindSingletonFunction("g_game", "safeLogout", &Game::safeLogout, &g_game); g_lua.bindSingletonFunction("g_game", "walk", &Game::walk, &g_game); + g_lua.bindSingletonFunction("g_game", "dashWalk", &Game::dashWalk, &g_game); g_lua.bindSingletonFunction("g_game", "autoWalk", &Game::autoWalk, &g_game); g_lua.bindSingletonFunction("g_game", "forceWalk", &Game::forceWalk, &g_game); g_lua.bindSingletonFunction("g_game", "turn", &Game::turn, &g_game);