From 44e428bccb9a5b37b6abd3555986c918bdf81b38 Mon Sep 17 00:00:00 2001 From: BeniS Date: Sat, 29 Dec 2012 00:05:45 +1300 Subject: [PATCH] Progress updating to cv981/pv973: * Implemented the new client AND protocol version methods. * Implemented the new speed laws added in cv980 (http://www.tibia.com/news/?subtopic=newsarchive&id=2251). * Added more missing bytea to login packets (client version/type and some unknown bytes). * Fixed the InputMessage::getDouble method. * Cleaned up some of the const values. * Started on the pending state features. TODO: * Pending game state feature. * Ensure version compatibility hasn't been compromised. --- modules/client/client.lua | 6 +-- modules/client_entergame/entergame.lua | 20 +++++-- modules/client_stats/stats.lua | 3 +- modules/corelib/string.lua | 5 +- modules/corelib/table.lua | 15 ++++++ modules/game_console/console.lua | 4 +- modules/game_market/marketprotocol.lua | 4 +- modules/game_minimap/minimap.lua | 12 ++--- modules/game_spelllist/spelllist.lua | 2 +- modules/game_textwindow/textwindow.lua | 8 +-- modules/game_tibiafiles/tibiafiles.lua | 12 ++--- modules/gamelib/game.lua | 10 +++- modules/gamelib/protocollogin.lua | 12 ++++- src/framework/net/inputmessage.cpp | 2 +- src/otclient/const.h | 74 ++++++++++++++------------ src/otclient/creature.cpp | 41 +++++++++++--- src/otclient/creature.h | 7 ++- src/otclient/game.cpp | 52 +++++++++++++----- src/otclient/game.h | 7 +++ src/otclient/item.cpp | 2 +- src/otclient/localplayer.cpp | 6 --- src/otclient/localplayer.h | 23 ++++---- src/otclient/luafunctions.cpp | 2 + src/otclient/map.cpp | 20 +++---- src/otclient/mapio.cpp | 2 +- src/otclient/protocolgame.cpp | 2 +- src/otclient/protocolgameparse.cpp | 21 ++++---- src/otclient/protocolgamesend.cpp | 9 +++- src/otclient/tile.cpp | 2 +- 29 files changed, 258 insertions(+), 127 deletions(-) diff --git a/modules/client/client.lua b/modules/client/client.lua index 428cac4a..c02d5c08 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -82,9 +82,9 @@ function Client.terminate() g_settings.set('window-pos', g_window.getUnmaximizedPos()) g_settings.set('window-maximized', g_window.isMaximized()) - local clientVersion = g_game.getClientVersion() - if clientVersion ~= 0 then - g_settings.set('client-version', clientVersion) + local protocolVersion = g_game.getProtocolVersion() + if protocolVersion ~= 0 then + g_settings.set('protocol-version', protocolVersion) end Client = nil diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 65d25b93..6221e834 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -52,6 +52,11 @@ local function onCharacterList(protocol, characters, account, otui) end end +local function onChangeProtocol(combobox, option) + local clients = g_game.getSupportedClients(option) + protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.toString(clients)) +end + -- public functions function EnterGame.init() enterGame = g_ui.displayUI('entergame.otui') @@ -69,7 +74,7 @@ function EnterGame.init() local host = g_settings.get('host') local port = g_settings.get('port') local autologin = g_settings.getBoolean('autologin') - local clientVersion = g_settings.getInteger('client-version') + local protocolVersion = g_settings.getInteger('protocol-version') if port == nil or port == 0 then port = 7171 end @@ -82,12 +87,13 @@ function EnterGame.init() enterGame:getChildById('accountNameTextEdit'):focus() protocolBox = enterGame:getChildById('protocolComboBox') + protocolBox.onOptionChange = onChangeProtocol for _i, proto in pairs(g_game.getSupportedProtocols()) do protocolBox:addOption(proto) end - if clientVersion then - protocolBox:setCurrentOption(clientVersion) + if protocolVersion then + protocolBox:setCurrentOption(protocolVersion) end enterGame:hide() @@ -153,7 +159,8 @@ function EnterGame.doLogin() G.password = enterGame:getChildById('accountPasswordTextEdit'):getText() G.host = enterGame:getChildById('serverHostTextEdit'):getText() G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText()) - local clientVersion = tonumber(protocolBox:getText()) + local protocolVersion = tonumber(protocolBox:getText()) + local clientVersions = g_game.getSupportedClients(protocolVersion) EnterGame.hide() if g_game.isOnline() then @@ -178,7 +185,10 @@ function EnterGame.doLogin() end }) g_game.chooseRsa(G.host) - g_game.setClientVersion(clientVersion) + g_game.setProtocolVersion(protocolVersion) + if #clientVersions > 0 then + g_game.setClientVersion(clientVersions[#clientVersions]) + end if modules.game_tibiafiles.isLoaded() then protocolLogin:login(G.host, G.port, G.account, G.password) diff --git a/modules/client_stats/stats.lua b/modules/client_stats/stats.lua index 4366694a..ec154299 100644 --- a/modules/client_stats/stats.lua +++ b/modules/client_stats/stats.lua @@ -64,7 +64,8 @@ function onConnect(protocol) post = post .. '&world_name=' .. g_game.getWorldName() post = post .. '&otserv_host=' .. G.host post = post .. '&otserv_port=' .. G.port - post = post .. '&otserv_protocol=' .. g_game.getClientVersion() + post = post .. '&otserv_protocol=' .. g_game.getProtocolVersion() + --post = post .. '&otserv_client=' .. g_game.getClientVersion() post = post .. '&build_version=' .. g_app.getVersion() post = post .. '&build_revision=' .. g_app.getBuildRevision() post = post .. '&build_commit=' .. g_app.getBuildCommit() diff --git a/modules/corelib/string.lua b/modules/corelib/string.lua index 88bd869a..348f989c 100644 --- a/modules/corelib/string.lua +++ b/modules/corelib/string.lua @@ -29,7 +29,7 @@ function string:trim() end function string:explode(sep, limit) - if(type(sep) ~= 'string' or tostring(self):len() == 0 or sep:len() == 0) then + if type(sep) ~= 'string' or tostring(self):len() == 0 or sep:len() == 0 then return {} end @@ -40,7 +40,7 @@ function string:explode(sep, limit) pos = e + 1 i = i + 1 - if(limit ~= nil and i == limit) then + if limit ~= nil and i == limit then break end end @@ -49,3 +49,4 @@ function string:explode(sep, limit) table.insert(t, tmp) return t end + diff --git a/modules/corelib/table.lua b/modules/corelib/table.lua index a5ebae80..82db00ea 100644 --- a/modules/corelib/table.lua +++ b/modules/corelib/table.lua @@ -92,3 +92,18 @@ function table.empty(t) end return true end + +function table.toString(t) + local maxn = #t + local str = "" + for k,v in pairs(t) do + if k == maxn and k ~= 1 then + str = str .. " and " .. v + elseif maxn > 1 and k ~= 1 then + str = str .. ", " .. v + else + str = str .. " " .. v + end + end + return str +end diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index 46e3ae80..26687a5e 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -192,8 +192,8 @@ end function addTab(name, focus) local tab = getTab(name) - if(tab) then -- is channel already open - if(not focus) then focus = true end + if tab then -- is channel already open + if not focus then focus = true end else tab = consoleTabBar:addTab(name) end diff --git a/modules/game_market/marketprotocol.lua b/modules/game_market/marketprotocol.lua index d5a650c2..34e861ad 100644 --- a/modules/game_market/marketprotocol.lua +++ b/modules/game_market/marketprotocol.lua @@ -39,14 +39,14 @@ end -- parsing protocols local function parseMarketEnter(msg) local balance - if(g_game.getClientVersion() >= 980) then + if g_game.getProtocolVersion() >= 973 then balance = msg:getU64() else balance = msg:getU32() end local vocation = -1 - if g_game.getClientVersion() < 950 then + if g_game.getProtocolVersion() < 950 then vocation = msg:getU8() -- get vocation id end local offers = msg:getU8() diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index 5f15a4d2..2314c89f 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -182,7 +182,7 @@ function addMapFlag(pos, icon, message, flagId, version) return end - version = version or g_game.getClientVersion() + version = version or g_game.getProtocolVersion() -- Check if flag is set for that position for i = 1, flagsPanel:getChildCount() do local flag = flagsPanel:getChildByIndex(i) @@ -218,7 +218,7 @@ function getMapArea() end function isFlagVisible(flag, firstPosition, lastPosition) - return flag.version == g_game.getClientVersion() and (minimapWidget:getZoom() >= 30 and minimapWidget:getZoom() <= 150) and flag.position.x >= firstPosition.x and flag.position.x <= lastPosition.x and flag.position.y >= firstPosition.y and flag.position.y <= lastPosition.y and flag.position.z == firstPosition.z + return flag.version == g_game.getProtocolVersion() and (minimapWidget:getZoom() >= 30 and minimapWidget:getZoom() <= 150) and flag.position.x >= firstPosition.x and flag.position.x <= lastPosition.x and flag.position.y >= firstPosition.y and flag.position.y <= lastPosition.y and flag.position.z == firstPosition.z end function updateMapFlag(id) @@ -267,8 +267,8 @@ function offline() end function loadMap() - local clientVersion = g_game.getClientVersion() - local minimapFile = '/minimap_' .. clientVersion .. '.otcm' + local protocolVersion = g_game.getProtocolVersion() + local minimapFile = '/minimap_' .. protocolVersion .. '.otcm' if g_resources.fileExists(minimapFile) then g_map.clean() g_map.loadOtcm(minimapFile) @@ -276,8 +276,8 @@ function loadMap() end function saveMap() - local clientVersion = g_game.getClientVersion() - local minimapFile = '/minimap_' .. clientVersion .. '.otcm' + local protocolVersion = g_game.getProtocolVersion() + local minimapFile = '/minimap_' .. protocolVersion .. '.otcm' g_map.saveOtcm(minimapFile) end diff --git a/modules/game_spelllist/spelllist.lua b/modules/game_spelllist/spelllist.lua index 188810d6..24099ee7 100644 --- a/modules/game_spelllist/spelllist.lua +++ b/modules/game_spelllist/spelllist.lua @@ -80,7 +80,7 @@ function getIconImageClip(id) end function setOptions() - if g_game.getClientVersion() >= 950 then -- Vocation is only send in newer clients + if g_game.getProtocolVersion() >= 950 then -- Vocation is only send in newer clients spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true) else spelllistWindow:getChildById('buttonFilterVocation'):setVisible(false) diff --git a/modules/game_textwindow/textwindow.lua b/modules/game_textwindow/textwindow.lua index bc02ef72..081527f8 100644 --- a/modules/game_textwindow/textwindow.lua +++ b/modules/game_textwindow/textwindow.lua @@ -118,14 +118,14 @@ function onGameEditText(id, itemId, maxLength, text, writter, time) end local newLineCount = string.count(textEdit:getText(), '\n') - if(newLineCount >= 9) then + if newLineCount >= 9 then textScroll:setMaximum(newLineCount-9) end local _prev, _next = 0, 11 local scrollOnValueChange = function(widget, value, delta) local line = getLineByCursorPos(textEdit:getText(), textEdit:getCursorPos(), newLineCount) - if(delta > 0) then + if delta > 0 then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), _next + delta - 1)) if writeable then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + delta)) end else @@ -180,7 +180,7 @@ function onGameEditText(id, itemId, maxLength, text, writter, time) return false end - if(not writeable) then + if not writeable then textEdit:setCursorPos(0) textWindow.onKeyPress = onKeyPress -- textEdit won't receive focus else @@ -244,4 +244,4 @@ function onGameEditList(id, doorId, text) okButton.onClick = doneFunc textWindow.onEnter = doneFunc textWindow.onEscape = destroy -end \ No newline at end of file +end diff --git a/modules/game_tibiafiles/tibiafiles.lua b/modules/game_tibiafiles/tibiafiles.lua index 32148504..f5bfbbb0 100644 --- a/modules/game_tibiafiles/tibiafiles.lua +++ b/modules/game_tibiafiles/tibiafiles.lua @@ -2,11 +2,11 @@ filename = 'Tibia' loaded = false function init() - connect(g_game, { onClientVersionChange = load }) + connect(g_game, { onProtocolVersionChange = load }) end function terminate() - disconnect(g_game, { onClientVersionChange = load }) + disconnect(g_game, { onProtocolVersionChange = load }) end function setFileName(name) @@ -18,7 +18,7 @@ function isLoaded() end function load() - local version = g_game.getClientVersion() + local version = g_game.getProtocolVersion() local datPath = resolvepath(version .. '/' .. filename .. '.dat') local sprPath = resolvepath(version .. '/' .. filename .. '.spr') @@ -36,8 +36,8 @@ function load() local messageBox = displayErrorBox(tr('Error'), errorMessage) addEvent(function() messageBox:raise() messageBox:focus() end) - disconnect(g_game, { onClientVersionChange = load }) - g_game.setClientVersion(0) - connect(g_game, { onClientVersionChange = load }) + disconnect(g_game, { onProtocolVersionChange = load }) + g_game.setprotocolVersion(0) + connect(g_game, { onProtocolVersionChange = load }) end end diff --git a/modules/gamelib/game.lua b/modules/gamelib/game.lua index c0faccfe..94fd9092 100644 --- a/modules/gamelib/game.lua +++ b/modules/gamelib/game.lua @@ -50,8 +50,16 @@ function g_game.getSupportedProtocols() return { 810, 853, 854, 860, 861, 862, 870, 910, 940, 944, 953, 954, 960, 961, - 963, 970, 971, 980, 981 + 963, 970, 971, 973 } end +function g_game.getSupportedClients(protocol) + clients = { + [971] = {980}, + [973] = {981} + } + return clients[protocol] or {protocol} +end + g_game.setRsa(OTSERV_RSA) diff --git a/modules/gamelib/protocollogin.lua b/modules/gamelib/protocollogin.lua index 6d67498e..1532f731 100644 --- a/modules/gamelib/protocollogin.lua +++ b/modules/gamelib/protocollogin.lua @@ -28,7 +28,12 @@ function ProtocolLogin:sendLoginPacket() local msg = OutputMessage.create() msg:addU8(ClientOpcodes.ClientEnterAccount) msg:addU16(g_game.getOsType()) - msg:addU16(g_game.getClientVersion()) + msg:addU16(g_game.getProtocolVersion()) + + if g_game.getProtocolVersion() >= 971 then + msg:addU32(g_game.getClientVersion()) + msg:addU8(182) -- clientType + end msg:addU32(g_things.getDatSignature()) msg:addU32(g_sprites.getSprSignature()) @@ -113,6 +118,11 @@ function ProtocolLogin:parseCharacterList(msg) character.worldIp = iptostring(msg:getU32()) character.worldPort = msg:getU16() characters[i] = character + + -- ?? + if g_game.getProtocolVersion() >= 971 then + msg:getU8() + end end local account = {} diff --git a/src/framework/net/inputmessage.cpp b/src/framework/net/inputmessage.cpp index b4045347..3ed922eb 100644 --- a/src/framework/net/inputmessage.cpp +++ b/src/framework/net/inputmessage.cpp @@ -89,7 +89,7 @@ std::string InputMessage::getString() double InputMessage::getDouble() { uint8 precision = getU8(); - uint32 v = getU32(); + int32 v = getU32() - INT_MAX; return (v / std::pow((float)10, precision)); } diff --git a/src/otclient/const.h b/src/otclient/const.h index 13ad712c..5034fd32 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -348,49 +348,57 @@ namespace Otc }; enum PathFindResult { - PATHFIND_RESULT_OK = 0, - PATHFIND_RESULT_SAME_POSITION, - PATHFIND_RESULT_IMPOSSIBLE, - PATHFIND_RESULT_TOO_FAR, - PATHFIND_RESULT_NO_WAY + PathFineResultOk = 0, + PathFindResultSamePosition, + PathFindResultImpossible, + PathFindResultTooFar, + PathFindResultNoWay }; - enum PathFindFlag { - PATHFIND_ALLOW_NULLTILES = 1, - PATHFIND_ALLOW_CREATURES = 2, - PATHFIND_ALLOW_NONPATHABLE = 4, - PATHFIND_ALLOW_NONWALKABLE = 8 + enum PathFindFlags { + PathFindAllowNullTiles = 1, + PathFindAllowCreatures = 2, + PathFindAllowNonPathable = 4, + PathFindAllowNonWalkable = 8 }; enum AutomapFlags { - MAPMARK_TICK = 0, - MAPMARK_QUESTION, - MAPMARK_EXCLAMATION, - MAPMARK_STAR, - MAPMARK_CROSS, - MAPMARK_TEMPLE, - MAPMARK_KISS, - MAPMARK_SHOVEL, - MAPMARK_SWORD, - MAPMARK_FLAG, - MAPMARK_LOCK, - MAPMARK_BAG, - MAPMARK_SKULL, - MAPMARK_DOLLAR, - MAPMARK_REDNORTH, - MAPMARK_REDSOUTH, - MAPMARK_REDEAST, - MAPMARK_REDWEST, - MAPMARK_GREENNORTH, - MAPMARK_GREENSOUTH + MapMarkTick = 0, + MapMarkQuestion, + MapMarkExclamation, + MapMarkStar, + MapMarkCross, + MapMarkTemple, + MapMarkKiss, + MapMarkShovel, + MapMarkSword, + MapMarkFlag, + MapMarkLock, + MapMarkBag, + MapMarkSkull, + MapMarkDollar, + MapMarkRedNorth, + MapMarkRedSouth, + MapMarkRedEast, + MapMarkRedWest, + MapMarkGreenNorth, + MapMarkGreenSouth }; enum VipState { - VIPSTATE_OFFLINE = 0, - VIPSTATE_ONLINE = 1, - VIPSTATE_PENDING = 2 + VipStateOffline = 0, + VipStateOnline = 1, + VipStatePending = 2 + }; + + enum SpeedFormula + { + SpeedFormulaA = 0, + SpeedFormulaB, + SpeedFormulaC, + LastSpeedFormula }; } diff --git a/src/otclient/creature.cpp b/src/otclient/creature.cpp index 4674480f..1caf4c9b 100644 --- a/src/otclient/creature.cpp +++ b/src/otclient/creature.cpp @@ -57,6 +57,7 @@ Creature::Creature() : Thing() m_nameCache.setFont(g_fonts.getFont("verdana-11px-rounded")); m_nameCache.setAlign(Fw::AlignTopCenter); m_footStep = 0; + m_speedFormula.fill(-1); } void Creature::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView) @@ -615,6 +616,19 @@ void Creature::setEmblemTexture(const std::string& filename) m_emblemTexture = g_textures.getTexture(filename); } +void Creature::setSpeedFormula(double speedA, double speedB, double speedC) +{ + m_speedFormula[Otc::SpeedFormulaA] = speedA; + m_speedFormula[Otc::SpeedFormulaB] = speedB; + m_speedFormula[Otc::SpeedFormulaC] = speedC; +} + +bool Creature::hasSpeedFormula() +{ + return m_speedFormula[Otc::SpeedFormulaA] != -1 && m_speedFormula[Otc::SpeedFormulaB] != -1 + && m_speedFormula[Otc::SpeedFormulaC] != -1; +} + void Creature::addTimedSquare(uint8 color) { m_showTimedSquare = true; @@ -658,28 +672,43 @@ Point Creature::getDrawOffset() int Creature::getStepDuration() { + int speed = m_speed * 2; int groundSpeed = 0; Position tilePos = m_lastStepToPosition; if(!tilePos.isValid()) tilePos = m_position; const TilePtr& tile = g_map.getTile(tilePos); - if(tile) + if(tile) { groundSpeed = tile->getGroundSpeed(); + if(groundSpeed == 0) + groundSpeed = 150; + } int interval = 1000; - if(groundSpeed > 0 && m_speed > 0) - interval = (1000 * groundSpeed) / m_speed; + if(groundSpeed > 0 && speed > 0) + interval = 1000 * groundSpeed; + + if(g_game.getFeature(Otc::GameNewSpeedLaw) && hasSpeedFormula()) { + int formulatedSpeed = 1; + if(speed > -m_speedFormula[Otc::SpeedFormulaB]) { + formulatedSpeed = std::max(1, (int)floor((m_speedFormula[Otc::SpeedFormulaA] * log((speed / 2) + + m_speedFormula[Otc::SpeedFormulaB]) + m_speedFormula[Otc::SpeedFormulaC]) + 0.5)); + } + interval = std::floor(interval / (double)formulatedSpeed); + } + else + interval /= speed; - if(g_game.getClientVersion() >= 900) + if(g_game.getProtocolVersion() >= 900) interval = (interval / g_game.getServerBeat()) * g_game.getServerBeat(); + interval = std::max(interval, g_game.getServerBeat()); + if(m_lastStepDirection == Otc::NorthWest || m_lastStepDirection == Otc::NorthEast || m_lastStepDirection == Otc::SouthWest || m_lastStepDirection == Otc::SouthEast) interval *= 3; - interval = std::max(interval, g_game.getServerBeat()); - return interval; } diff --git a/src/otclient/creature.h b/src/otclient/creature.h index 0b8402b4..b15d9a97 100644 --- a/src/otclient/creature.h +++ b/src/otclient/creature.h @@ -44,7 +44,6 @@ public: Creature(); - virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr); void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView = nullptr); @@ -65,6 +64,7 @@ public: void setShieldTexture(const std::string& filename, bool blink); void setEmblemTexture(const std::string& filename); void setPassable(bool passable) { m_passable = passable; } + void setSpeedFormula(double speedA, double speedB, double speedC); void addTimedSquare(uint8 color); void removeTimedSquare() { m_showTimedSquare = false; } @@ -89,6 +89,9 @@ public: Position getLastStepFromPosition() { return m_lastStepFromPosition; } Position getLastStepToPosition() { return m_lastStepToPosition; } float getStepProgress() { return m_walkTimer.ticksElapsed() / getStepDuration(); } + double getSpeedFormula(Otc::SpeedFormula formula) { return m_speedFormula[formula]; } + bool hasSpeedFormula(); + std::array getSpeedFormulaArray() { return m_speedFormula; } virtual Point getDisplacement(); virtual int getDisplacementX(); virtual int getDisplacementY(); @@ -148,6 +151,8 @@ protected: CachedText m_nameCache; Color m_informationColor; + std::array m_speedFormula; + // walk related int m_walkAnimationPhase; int m_walkedPixels; diff --git a/src/otclient/game.cpp b/src/otclient/game.cpp index 29c586c7..bfa7568e 100644 --- a/src/otclient/game.cpp +++ b/src/otclient/game.cpp @@ -39,7 +39,7 @@ Game g_game; Game::Game() { resetGameStates(); - m_clientVersion = 0; + m_protocolVersion = 0; } void Game::terminate() @@ -118,6 +118,18 @@ void Game::processLoginWait(const std::string& message, int time) g_lua.callGlobalField("g_game", "onLoginWait", message, time); } +void Game::processPendingGame() +{ + m_localPlayer->setPendingGame(true); + g_lua.callGlobalField("g_game", "onPendingGame"); +} + +void Game::processEnterGame() +{ + m_localPlayer->setPendingGame(false); + g_lua.callGlobalField("g_game", "onEnterGame"); +} + void Game::processGameStart() { m_online = true; @@ -432,7 +444,7 @@ void Game::loginWorld(const std::string& account, const std::string& password, c if(m_protocolGame || isOnline()) stdext::throw_exception("Unable to login into a world while already online or logging."); - if(m_clientVersion == 0) + if(m_protocolVersion == 0) stdext::throw_exception("Must set a valid game protocol version before logging."); // reset the new game state @@ -642,7 +654,7 @@ void Game::look(const ThingPtr& thing) if(!canPerformGameAction() || !thing) return; - if(thing->isCreature() && m_clientVersion >= 961) + if(thing->isCreature() && m_protocolVersion >= 961) m_protocolGame->sendLookCreature(thing->getId()); else m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackpos()); @@ -715,7 +727,7 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing) if(!pos.isValid()) // virtual item pos = Position(0xFFFF, 0, 0); // means that is a item in inventory - if(toThing->isCreature() && g_game.getClientVersion() >= 860) + if(toThing->isCreature() && g_game.getProtocolVersion() >= 860) 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()); @@ -785,7 +797,7 @@ void Game::attack(CreaturePtr creature) setAttackingCreature(creature); - if(m_clientVersion >= 963) { + if(m_protocolVersion >= 963) { if(creature) m_seq = creature->getId(); } else @@ -808,7 +820,7 @@ void Game::follow(CreaturePtr creature) setFollowingCreature(creature); - if(m_clientVersion >= 963) { + if(m_protocolVersion >= 963) { if(creature) m_seq = creature->getId(); } else @@ -1173,15 +1185,15 @@ bool Game::canPerformGameAction() return m_online && m_localPlayer && !m_dead && m_protocolGame && m_protocolGame->isConnected() && checkBotProtection(); } -void Game::setClientVersion(int version) +void Game::setProtocolVersion(int version) { - if(m_clientVersion == version) + if(m_protocolVersion == version) return; if(isOnline()) - stdext::throw_exception("Unable to change client version while online"); + stdext::throw_exception("Unable to change protocol version while online"); - if(version != 0 && (version < 810 || version > 981)) + if(version != 0 && (version < 810 || version > 973)) stdext::throw_exception(stdext::format("Protocol version %d not supported", version)); m_features.reset(); @@ -1233,15 +1245,31 @@ void Game::setClientVersion(int version) enableFeature(Otc::GameOfflineTrainingTime); } - if(version >= 980) { + if(version >= 973) { enableFeature(Otc::GameLoginPending); enableFeature(Otc::GameNewSpeedLaw); } - m_clientVersion = version; + m_protocolVersion = version; Proto::buildMessageModesMap(version); + g_lua.callGlobalField("g_game", "onProtocolVersionChange", version); +} + +void Game::setClientVersion(int version) +{ + if(m_clientVersion == version) + return; + + if(isOnline()) + stdext::throw_exception("Unable to change client version while online"); + + if(version != 0 && (version < 981 || version > 981)) + stdext::throw_exception(stdext::format("Client version %d not supported", version)); + + m_clientVersion = version; + g_lua.callGlobalField("g_game", "onClientVersionChange", version); } diff --git a/src/otclient/game.h b/src/otclient/game.h index 0a8bca7d..8d318f81 100644 --- a/src/otclient/game.h +++ b/src/otclient/game.h @@ -59,6 +59,9 @@ protected: void processLoginAdvice(const std::string& message); void processLoginWait(const std::string& message, int time); + void processPendingGame(); + void processEnterGame(); + void processGameStart(); void processGameEnd(); void processDeath(int penality); @@ -248,6 +251,9 @@ public: void setFeature(Otc::GameFeature feature, bool enabled) { m_features.set(feature, enabled); } bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); } + void setProtocolVersion(int version); + int getProtocolVersion() { return m_protocolVersion; } + void setClientVersion(int version); int getClientVersion() { return m_clientVersion; } @@ -308,6 +314,7 @@ private: std::string m_worldName; std::bitset m_features; ScheduledEventPtr m_pingEvent; + int m_protocolVersion; int m_clientVersion; }; diff --git a/src/otclient/item.cpp b/src/otclient/item.cpp index 2eec3783..7f2bd685 100644 --- a/src/otclient/item.cpp +++ b/src/otclient/item.cpp @@ -216,7 +216,7 @@ int Item::getSubType() { if(isSplash() || isFluidContainer()) return m_countOrSubType; - if(g_game.getClientVersion() >= 900) + if(g_game.getProtocolVersion() >= 900) return 0; return 1; } diff --git a/src/otclient/localplayer.cpp b/src/otclient/localplayer.cpp index 9f74933e..bcf8d536 100644 --- a/src/otclient/localplayer.cpp +++ b/src/otclient/localplayer.cpp @@ -28,12 +28,6 @@ LocalPlayer::LocalPlayer() { - m_preWalking = false; - m_lastPrewalkDone = true; - m_autoWalking = false; - m_known = false; - m_premium = false; - m_states = 0; m_vocation = 0; m_walkLockExpiration = 0; diff --git a/src/otclient/localplayer.h b/src/otclient/localplayer.h index 279b4954..f362f883 100644 --- a/src/otclient/localplayer.h +++ b/src/otclient/localplayer.h @@ -53,6 +53,7 @@ public: void setSoul(double soul); void setStamina(double stamina); void setKnown(bool known) { m_known = known; } + void setPendingGame(bool pending) { m_pending = pending; } void setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item); void setVocation(int vocation); void setPremium(bool premium); @@ -92,6 +93,7 @@ public: bool isPreWalking() { return m_preWalking; } bool isAutoWalking() { return m_autoWalking; } bool isPremium() { return m_premium; } + bool isPendingGame() { return m_pending; } LocalPlayerPtr asLocalPlayer() { return static_self_cast(); } bool isLocalPlayer() { return true; } @@ -113,27 +115,30 @@ protected: private: // walk related - bool m_preWalking; - bool m_lastPrewalkDone; - bool m_autoWalking; - bool m_premium; + Timer m_walkPingTimer; Position m_lastPrewalkDestionation; - ItemPtr m_inventoryItems[Otc::LastInventorySlot]; ScheduledEventPtr m_autoWalkEndEvent; + ticks_t m_walkLockExpiration; + int m_lastWalkPing; + stdext::boolean m_preWalking; + stdext::boolean m_lastPrewalkDone; + stdext::boolean m_autoWalking; stdext::boolean m_waitingWalkPong; - Timer m_walkPingTimer; + + stdext::boolean m_premium; + stdext::boolean m_known; + stdext::boolean m_pending; + + ItemPtr m_inventoryItems[Otc::LastInventorySlot]; Timer m_idleTimer; - int m_lastWalkPing; std::array m_skillsLevel; std::array m_skillsBaseLevel; std::array m_skillsLevelPercent; std::vector m_spells; - bool m_known; int m_states; int m_vocation; - ticks_t m_walkLockExpiration; double m_health; double m_maxHealth; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 9478fad9..98e185c2 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -220,6 +220,8 @@ void OTClient::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "getServerBeat", &Game::getServerBeat, &g_game); g_lua.bindSingletonFunction("g_game", "getLocalPlayer", &Game::getLocalPlayer, &g_game); g_lua.bindSingletonFunction("g_game", "getProtocolGame", &Game::getProtocolGame, &g_game); + g_lua.bindSingletonFunction("g_game", "getProtocolVersion", &Game::getProtocolVersion, &g_game); + g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game); g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game); g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game); g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game); diff --git a/src/otclient/map.cpp b/src/otclient/map.cpp index f01e5094..00beb579 100644 --- a/src/otclient/map.cpp +++ b/src/otclient/map.cpp @@ -459,20 +459,20 @@ std::tuple, Otc::PathFindResult> Map::findPath(const std::vector& dirs = std::get<0>(ret); Otc::PathFindResult& result = std::get<1>(ret); - result = Otc::PATHFIND_RESULT_NO_WAY; + result = Otc::PathFindResultNoWay; if(startPos == goalPos) { - result = Otc::PATHFIND_RESULT_SAME_POSITION; + result = Otc::PathFindResultSamePosition; return ret; } if(startPos.z != goalPos.z) { - result = Otc::PATHFIND_RESULT_IMPOSSIBLE; + result = Otc::PathFindResultImpossible; return ret; } if(startPos.distance(goalPos) > maxSteps) { - result = Otc::PATHFIND_RESULT_TOO_FAR; + result = Otc::PathFindResultTooFar; return ret; } @@ -486,7 +486,7 @@ std::tuple, Otc::PathFindResult> Map::findPath(const while(currentNode) { // too far if(currentNode->steps >= maxSteps) { - result = Otc::PATHFIND_RESULT_TOO_FAR; + result = Otc::PathFindResultTooFar; break; } @@ -507,14 +507,14 @@ std::tuple, Otc::PathFindResult> Map::findPath(const const TilePtr& tile = getTile(neighborPos); if(neighborPos != goalPos) { - if(!(flags & Otc::PATHFIND_ALLOW_NULLTILES) && !tile) + if(!(flags & Otc::PathFindAllowNullTiles) && !tile) continue; if(tile) { - if(!(flags & Otc::PATHFIND_ALLOW_CREATURES) && tile->hasCreature()) + if(!(flags & Otc::PathFindAllowCreatures) && tile->hasCreature()) continue; - if(!(flags & Otc::PATHFIND_ALLOW_NONPATHABLE) && !tile->isPathable()) + if(!(flags & Otc::PathFindAllowNonPathable) && !tile->isPathable()) continue; - if(!(flags & Otc::PATHFIND_ALLOW_NONWALKABLE) && !tile->isWalkable()) + if(!(flags & Otc::PathFindAllowNonWalkable) && !tile->isWalkable()) continue; } } @@ -568,7 +568,7 @@ std::tuple, Otc::PathFindResult> Map::findPath(const } dirs.pop_back(); std::reverse(dirs.begin(), dirs.end()); - result = Otc::PATHFIND_RESULT_OK; + result = Otc::PathFineResultOk; } for(auto it : nodes) diff --git a/src/otclient/mapio.cpp b/src/otclient/mapio.cpp index b91014fe..45577a6a 100644 --- a/src/otclient/mapio.cpp +++ b/src/otclient/mapio.cpp @@ -473,7 +473,7 @@ void Map::saveOtcm(const std::string& fileName) // version 1 header fin->addString("OTCM 1.0"); // map description fin->addU32(g_things.getDatSignature()); - fin->addU16(g_game.getClientVersion()); + fin->addU16(g_game.getProtocolVersion()); fin->addString(g_game.getWorldName()); // go back and rewrite where the map data starts diff --git a/src/otclient/protocolgame.cpp b/src/otclient/protocolgame.cpp index 0d1aa0de..e35cbb36 100644 --- a/src/otclient/protocolgame.cpp +++ b/src/otclient/protocolgame.cpp @@ -56,7 +56,7 @@ void ProtocolGame::onRecv(const InputMessagePtr& inputMessage) if(m_firstRecv) { m_firstRecv = false; - if(g_game.getClientVersion() > 810) { + if(g_game.getProtocolVersion() > 810) { int size = inputMessage->getU16(); if(size != inputMessage->getUnreadSize()) { g_logger.traceError("invalid message size"); diff --git a/src/otclient/protocolgameparse.cpp b/src/otclient/protocolgameparse.cpp index 45fc43ef..56270857 100644 --- a/src/otclient/protocolgameparse.cpp +++ b/src/otclient/protocolgameparse.cpp @@ -342,6 +342,7 @@ void ProtocolGame::parseInitGame(const InputMessagePtr& msg) double speedA = msg->getDouble(); double speedB = msg->getDouble(); double speedC = msg->getDouble(); + m_localPlayer->setSpeedFormula(speedA, speedB, speedC); } bool canReportBugs = msg->getU8(); @@ -353,11 +354,13 @@ void ProtocolGame::parseInitGame(const InputMessagePtr& msg) void ProtocolGame::parsePendingGame(const InputMessagePtr& msg) { //set player to pending game state + g_game.processPendingGame(); } void ProtocolGame::parseEnterGame(const InputMessagePtr& msg) { //set player to entered game state + g_game.processEnterGame(); } void ProtocolGame::parseGMActions(const InputMessagePtr& msg) @@ -366,7 +369,7 @@ void ProtocolGame::parseGMActions(const InputMessagePtr& msg) int numViolationReasons; - if(g_game.getClientVersion() >= 854) + if(g_game.getProtocolVersion() >= 854) numViolationReasons = 20; else numViolationReasons = 32; @@ -489,7 +492,7 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg) Position pos = getPosition(msg); int stackPos = -1; - if(g_game.getClientVersion() >= 854) + if(g_game.getProtocolVersion() >= 854) stackPos = msg->getU8(); ThingPtr thing = getThing(msg); @@ -617,7 +620,7 @@ void ProtocolGame::parseOpenNpcTrade(const InputMessagePtr& msg) int listCount; - if(g_game.getClientVersion() >= 900) + if(g_game.getProtocolVersion() >= 900) listCount = msg->getU16(); else listCount = msg->getU8(); @@ -644,7 +647,7 @@ void ProtocolGame::parsePlayerGoods(const InputMessagePtr& msg) std::vector> goods; int money; - if(g_game.getClientVersion() >= 980) + if(g_game.getProtocolVersion() >= 973) money = msg->getU64(); else money = msg->getU32(); @@ -993,7 +996,7 @@ void ProtocolGame::parsePlayerState(const InputMessagePtr& msg) void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg) { uint seq = 0; - if(g_game.getClientVersion() >= 860) + if(g_game.getProtocolVersion() >= 860) seq = msg->getU32(); g_game.processAttackCancel(seq); @@ -1295,7 +1298,7 @@ void ProtocolGame::parseVipAdd(const InputMessagePtr& msg) id = msg->getU32(); name = g_game.formatCreatureName(msg->getString()); - if(g_game.getClientVersion() >= 963) { + if(g_game.getProtocolVersion() >= 963) { desc = msg->getString(); markId = msg->getU32(); notifyLogin = msg->getU8(); @@ -1614,7 +1617,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type) uint id = msg->getU32(); int creatureType; - if(g_game.getClientVersion() >= 910) + if(g_game.getProtocolVersion() >= 910) creatureType = msg->getU8(); else { if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId) @@ -1670,7 +1673,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type) if(g_game.getFeature(Otc::GameCreatureEmblems) && !known) emblem = msg->getU8(); - if(g_game.getClientVersion() >= 854) + if(g_game.getProtocolVersion() >= 854) unpass = msg->getU8(); if(creature) { @@ -1699,7 +1702,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type) if(creature) creature->turn(direction); - if(g_game.getClientVersion() >= 953) { + if(g_game.getProtocolVersion() >= 953) { bool unpass = msg->getU8(); if(creature) diff --git a/src/otclient/protocolgamesend.cpp b/src/otclient/protocolgamesend.cpp index 5d82abb9..7ef465d9 100644 --- a/src/otclient/protocolgamesend.cpp +++ b/src/otclient/protocolgamesend.cpp @@ -51,7 +51,12 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando msg->addU8(Proto::ClientEnterGame); msg->addU16(g_lua.callGlobalField("g_game", "getOsType")); - msg->addU16(g_game.getClientVersion()); + msg->addU16(g_game.getProtocolVersion()); + + if(g_game.getProtocolVersion() >= 971) { + msg->addU32(g_game.getClientVersion()); + msg->addU8(0); // clientType + } int paddingBytes = 128; msg->addU8(0); // first RSA byte must be 0 @@ -588,7 +593,7 @@ void ProtocolGame::sendShareExperience(bool active) msg->addU8(Proto::ClientShareExperience); msg->addU8(active ? 0x01 : 0x00); - if(g_game.getClientVersion() < 910) + if(g_game.getProtocolVersion() < 910) msg->addU8(0); send(msg); diff --git a/src/otclient/tile.cpp b/src/otclient/tile.cpp index 08df965e..502d0ada 100644 --- a/src/otclient/tile.cpp +++ b/src/otclient/tile.cpp @@ -189,7 +189,7 @@ void Tile::addThing(const ThingPtr& thing, int stackPos) append = (priority <= 3); // newer protocols does not store creatures in reverse order - if(g_game.getClientVersion() >= 854 && priority == 4) + if(g_game.getProtocolVersion() >= 854 && priority == 4) append = !append; }