Browse Source

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.
BeniS 8 years ago
parent
commit
44e428bccb

+ 3
- 3
modules/client/client.lua View File

@@ -82,9 +82,9 @@ function Client.terminate()
82 82
   g_settings.set('window-pos', g_window.getUnmaximizedPos())
83 83
   g_settings.set('window-maximized', g_window.isMaximized())
84 84
 
85
-  local clientVersion = g_game.getClientVersion()
86
-  if clientVersion ~= 0 then
87
-    g_settings.set('client-version', clientVersion)
85
+  local protocolVersion = g_game.getProtocolVersion()
86
+  if protocolVersion ~= 0 then
87
+    g_settings.set('protocol-version', protocolVersion)
88 88
   end
89 89
 
90 90
   Client = nil

+ 15
- 5
modules/client_entergame/entergame.lua View File

@@ -52,6 +52,11 @@ local function onCharacterList(protocol, characters, account, otui)
52 52
   end
53 53
 end
54 54
 
55
+local function onChangeProtocol(combobox, option)
56
+  local clients = g_game.getSupportedClients(option)
57
+  protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.toString(clients))
58
+end
59
+
55 60
 -- public functions
56 61
 function EnterGame.init()
57 62
   enterGame = g_ui.displayUI('entergame.otui')
@@ -69,7 +74,7 @@ function EnterGame.init()
69 74
   local host = g_settings.get('host')
70 75
   local port = g_settings.get('port')
71 76
   local autologin = g_settings.getBoolean('autologin')
72
-  local clientVersion = g_settings.getInteger('client-version')
77
+  local protocolVersion = g_settings.getInteger('protocol-version')
73 78
 
74 79
   if port == nil or port == 0 then port = 7171 end
75 80
 
@@ -82,12 +87,13 @@ function EnterGame.init()
82 87
   enterGame:getChildById('accountNameTextEdit'):focus()
83 88
 
84 89
   protocolBox = enterGame:getChildById('protocolComboBox')
90
+  protocolBox.onOptionChange = onChangeProtocol  
85 91
   for _i, proto in pairs(g_game.getSupportedProtocols()) do
86 92
     protocolBox:addOption(proto)
87 93
   end
88 94
 
89
-  if clientVersion then
90
-    protocolBox:setCurrentOption(clientVersion)
95
+  if protocolVersion then
96
+    protocolBox:setCurrentOption(protocolVersion)
91 97
   end
92 98
 
93 99
   enterGame:hide()
@@ -153,7 +159,8 @@ function EnterGame.doLogin()
153 159
   G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
154 160
   G.host = enterGame:getChildById('serverHostTextEdit'):getText()
155 161
   G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
156
-  local clientVersion = tonumber(protocolBox:getText())
162
+  local protocolVersion = tonumber(protocolBox:getText())
163
+  local clientVersions = g_game.getSupportedClients(protocolVersion)
157 164
   EnterGame.hide()
158 165
 
159 166
   if g_game.isOnline() then
@@ -178,7 +185,10 @@ function EnterGame.doLogin()
178 185
                                 end })
179 186
 
180 187
   g_game.chooseRsa(G.host)
181
-  g_game.setClientVersion(clientVersion)
188
+  g_game.setProtocolVersion(protocolVersion)
189
+  if #clientVersions > 0 then
190
+    g_game.setClientVersion(clientVersions[#clientVersions])
191
+  end
182 192
 
183 193
   if modules.game_tibiafiles.isLoaded() then
184 194
     protocolLogin:login(G.host, G.port, G.account, G.password)

+ 2
- 1
modules/client_stats/stats.lua View File

@@ -64,7 +64,8 @@ function onConnect(protocol)
64 64
   post = post .. '&world_name='        .. g_game.getWorldName()
65 65
   post = post .. '&otserv_host='       .. G.host
66 66
   post = post .. '&otserv_port='       .. G.port
67
-  post = post .. '&otserv_protocol='   .. g_game.getClientVersion()
67
+  post = post .. '&otserv_protocol='   .. g_game.getProtocolVersion()
68
+  --post = post .. '&otserv_client='     .. g_game.getClientVersion()
68 69
   post = post .. '&build_version='     .. g_app.getVersion()
69 70
   post = post .. '&build_revision='    .. g_app.getBuildRevision()
70 71
   post = post .. '&build_commit='      .. g_app.getBuildCommit()

+ 3
- 2
modules/corelib/string.lua View File

@@ -29,7 +29,7 @@ function string:trim()
29 29
 end
30 30
 
31 31
 function string:explode(sep, limit)
32
-  if(type(sep) ~= 'string' or tostring(self):len() == 0 or sep:len() == 0) then
32
+  if type(sep) ~= 'string' or tostring(self):len() == 0 or sep:len() == 0 then
33 33
     return {}
34 34
   end
35 35
 
@@ -40,7 +40,7 @@ function string:explode(sep, limit)
40 40
     pos = e + 1
41 41
 
42 42
     i = i + 1
43
-    if(limit ~= nil and i == limit) then
43
+    if limit ~= nil and i == limit then
44 44
       break
45 45
     end
46 46
   end
@@ -49,3 +49,4 @@ function string:explode(sep, limit)
49 49
   table.insert(t, tmp)
50 50
   return t
51 51
 end
52
+

+ 15
- 0
modules/corelib/table.lua View File

@@ -92,3 +92,18 @@ function table.empty(t)
92 92
   end
93 93
   return true
94 94
 end
95
+
96
+function table.toString(t)
97
+  local maxn = #t
98
+  local str = ""
99
+  for k,v in pairs(t) do
100
+    if k == maxn and k ~= 1 then
101
+      str = str .. " and " .. v
102
+    elseif maxn > 1 and k ~= 1 then
103
+      str = str .. ", " .. v
104
+    else
105
+      str = str .. " " .. v
106
+    end
107
+  end
108
+  return str
109
+end

+ 2
- 2
modules/game_console/console.lua View File

@@ -192,8 +192,8 @@ end
192 192
 
193 193
 function addTab(name, focus)
194 194
   local tab = getTab(name)
195
-  if(tab) then -- is channel already open
196
-    if(not focus) then focus = true end
195
+  if tab then -- is channel already open
196
+    if not focus then focus = true end
197 197
   else
198 198
     tab = consoleTabBar:addTab(name)
199 199
   end

+ 2
- 2
modules/game_market/marketprotocol.lua View File

@@ -39,14 +39,14 @@ end
39 39
 -- parsing protocols
40 40
 local function parseMarketEnter(msg)
41 41
   local balance
42
-  if(g_game.getClientVersion() >= 980) then
42
+  if g_game.getProtocolVersion() >= 973 then
43 43
     balance = msg:getU64()
44 44
   else
45 45
     balance = msg:getU32()
46 46
   end
47 47
 
48 48
   local vocation = -1
49
-  if g_game.getClientVersion() < 950 then
49
+  if g_game.getProtocolVersion() < 950 then
50 50
     vocation = msg:getU8() -- get vocation id
51 51
   end
52 52
   local offers = msg:getU8()

+ 6
- 6
modules/game_minimap/minimap.lua View File

@@ -182,7 +182,7 @@ function addMapFlag(pos, icon, message, flagId, version)
182 182
     return 
183 183
   end
184 184
   
185
-  version = version or g_game.getClientVersion()
185
+  version = version or g_game.getProtocolVersion()
186 186
   -- Check if flag is set for that position
187 187
   for i = 1, flagsPanel:getChildCount() do
188 188
     local flag = flagsPanel:getChildByIndex(i)
@@ -218,7 +218,7 @@ function getMapArea()
218 218
 end
219 219
 
220 220
 function isFlagVisible(flag, firstPosition, lastPosition)
221
-  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
221
+  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
222 222
 end
223 223
 
224 224
 function updateMapFlag(id)  
@@ -267,8 +267,8 @@ function offline()
267 267
 end
268 268
 
269 269
 function loadMap()
270
-  local clientVersion = g_game.getClientVersion()
271
-  local minimapFile = '/minimap_' .. clientVersion .. '.otcm'
270
+  local protocolVersion = g_game.getProtocolVersion()
271
+  local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
272 272
   if g_resources.fileExists(minimapFile) then
273 273
     g_map.clean()
274 274
     g_map.loadOtcm(minimapFile)
@@ -276,8 +276,8 @@ function loadMap()
276 276
 end
277 277
 
278 278
 function saveMap()
279
-  local clientVersion = g_game.getClientVersion()
280
-  local minimapFile = '/minimap_' .. clientVersion .. '.otcm'
279
+  local protocolVersion = g_game.getProtocolVersion()
280
+  local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
281 281
   g_map.saveOtcm(minimapFile)
282 282
 end
283 283
 

+ 1
- 1
modules/game_spelllist/spelllist.lua View File

@@ -80,7 +80,7 @@ function getIconImageClip(id)
80 80
 end
81 81
 
82 82
 function setOptions()
83
-  if g_game.getClientVersion() >= 950 then -- Vocation is only send in newer clients
83
+  if g_game.getProtocolVersion() >= 950 then -- Vocation is only send in newer clients
84 84
     spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true)
85 85
   else
86 86
     spelllistWindow:getChildById('buttonFilterVocation'):setVisible(false)

+ 4
- 4
modules/game_textwindow/textwindow.lua View File

@@ -118,14 +118,14 @@ function onGameEditText(id, itemId, maxLength, text, writter, time)
118 118
   end
119 119
   
120 120
   local newLineCount = string.count(textEdit:getText(), '\n')
121
-  if(newLineCount >= 9) then
121
+  if newLineCount >= 9 then
122 122
     textScroll:setMaximum(newLineCount-9)
123 123
   end
124 124
     
125 125
   local _prev, _next = 0, 11
126 126
   local scrollOnValueChange = function(widget, value, delta)
127 127
     local line = getLineByCursorPos(textEdit:getText(), textEdit:getCursorPos(), newLineCount)
128
-    if(delta > 0) then
128
+    if delta > 0 then
129 129
       textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), _next + delta - 1))
130 130
       if writeable then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + delta)) end
131 131
     else
@@ -180,7 +180,7 @@ function onGameEditText(id, itemId, maxLength, text, writter, time)
180 180
     return false
181 181
   end
182 182
   
183
-  if(not writeable) then
183
+  if not writeable then
184 184
     textEdit:setCursorPos(0)
185 185
     textWindow.onKeyPress = onKeyPress  -- textEdit won't receive focus
186 186
   else
@@ -244,4 +244,4 @@ function onGameEditList(id, doorId, text)
244 244
   okButton.onClick = doneFunc
245 245
   textWindow.onEnter = doneFunc
246 246
   textWindow.onEscape = destroy
247
-end
247
+end

+ 6
- 6
modules/game_tibiafiles/tibiafiles.lua View File

@@ -2,11 +2,11 @@ filename = 'Tibia'
2 2
 loaded = false
3 3
 
4 4
 function init()
5
-  connect(g_game, { onClientVersionChange = load })
5
+  connect(g_game, { onProtocolVersionChange = load })
6 6
 end
7 7
 
8 8
 function terminate()
9
-  disconnect(g_game, { onClientVersionChange = load })
9
+  disconnect(g_game, { onProtocolVersionChange = load })
10 10
 end
11 11
 
12 12
 function setFileName(name)
@@ -18,7 +18,7 @@ function isLoaded()
18 18
 end
19 19
 
20 20
 function load()
21
-  local version = g_game.getClientVersion()
21
+  local version = g_game.getProtocolVersion()
22 22
   local datPath = resolvepath(version .. '/' .. filename .. '.dat')
23 23
   local sprPath = resolvepath(version .. '/' .. filename .. '.spr')
24 24
 
@@ -36,8 +36,8 @@ function load()
36 36
     local messageBox = displayErrorBox(tr('Error'), errorMessage)
37 37
     addEvent(function() messageBox:raise() messageBox:focus() end)
38 38
 
39
-    disconnect(g_game, { onClientVersionChange = load })
40
-    g_game.setClientVersion(0)
41
-    connect(g_game, { onClientVersionChange = load })
39
+    disconnect(g_game, { onProtocolVersionChange = load })
40
+    g_game.setprotocolVersion(0)
41
+    connect(g_game, { onProtocolVersionChange = load })
42 42
   end
43 43
 end

+ 9
- 1
modules/gamelib/game.lua View File

@@ -50,8 +50,16 @@ function g_game.getSupportedProtocols()
50 50
   return {
51 51
     810, 853, 854, 860, 861, 862, 870,
52 52
     910, 940, 944, 953, 954, 960, 961,
53
-    963, 970, 971, 980, 981
53
+    963, 970, 971, 973
54 54
   }
55 55
 end
56 56
 
57
+function g_game.getSupportedClients(protocol)
58
+  clients = {
59
+    [971] = {980},
60
+    [973] = {981}
61
+  }
62
+  return clients[protocol] or {protocol}
63
+end
64
+
57 65
 g_game.setRsa(OTSERV_RSA)

+ 11
- 1
modules/gamelib/protocollogin.lua View File

@@ -28,7 +28,12 @@ function ProtocolLogin:sendLoginPacket()
28 28
   local msg = OutputMessage.create()
29 29
   msg:addU8(ClientOpcodes.ClientEnterAccount)
30 30
   msg:addU16(g_game.getOsType())
31
-  msg:addU16(g_game.getClientVersion())
31
+  msg:addU16(g_game.getProtocolVersion())
32
+
33
+  if g_game.getProtocolVersion() >= 971 then
34
+    msg:addU32(g_game.getClientVersion())
35
+    msg:addU8(182) -- clientType
36
+  end
32 37
 
33 38
   msg:addU32(g_things.getDatSignature())
34 39
   msg:addU32(g_sprites.getSprSignature())
@@ -113,6 +118,11 @@ function ProtocolLogin:parseCharacterList(msg)
113 118
     character.worldIp = iptostring(msg:getU32())
114 119
     character.worldPort = msg:getU16()
115 120
     characters[i] = character
121
+
122
+    -- ??
123
+    if g_game.getProtocolVersion() >= 971 then
124
+      msg:getU8()
125
+    end
116 126
   end
117 127
 
118 128
   local account = {}

+ 1
- 1
src/framework/net/inputmessage.cpp View File

@@ -89,7 +89,7 @@ std::string InputMessage::getString()
89 89
 double InputMessage::getDouble()
90 90
 {
91 91
     uint8 precision = getU8();
92
-    uint32 v = getU32();
92
+    int32 v = getU32() - INT_MAX;
93 93
     return (v / std::pow((float)10, precision));
94 94
 }
95 95
 

+ 41
- 33
src/otclient/const.h View File

@@ -348,49 +348,57 @@ namespace Otc
348 348
     };
349 349
 
350 350
     enum PathFindResult {
351
-        PATHFIND_RESULT_OK = 0,
352
-        PATHFIND_RESULT_SAME_POSITION,
353
-        PATHFIND_RESULT_IMPOSSIBLE,
354
-        PATHFIND_RESULT_TOO_FAR,
355
-        PATHFIND_RESULT_NO_WAY
351
+        PathFineResultOk = 0,
352
+        PathFindResultSamePosition,
353
+        PathFindResultImpossible,
354
+        PathFindResultTooFar,
355
+        PathFindResultNoWay
356 356
     };
357 357
 
358
-    enum PathFindFlag {
359
-        PATHFIND_ALLOW_NULLTILES = 1,
360
-        PATHFIND_ALLOW_CREATURES = 2,
361
-        PATHFIND_ALLOW_NONPATHABLE = 4,
362
-        PATHFIND_ALLOW_NONWALKABLE = 8
358
+    enum PathFindFlags {
359
+        PathFindAllowNullTiles = 1,
360
+        PathFindAllowCreatures = 2,
361
+        PathFindAllowNonPathable = 4,
362
+        PathFindAllowNonWalkable = 8
363 363
     };
364 364
 
365 365
     enum AutomapFlags
366 366
     {
367
-        MAPMARK_TICK = 0,
368
-        MAPMARK_QUESTION,
369
-        MAPMARK_EXCLAMATION,
370
-        MAPMARK_STAR,
371
-        MAPMARK_CROSS,
372
-        MAPMARK_TEMPLE,
373
-        MAPMARK_KISS,
374
-        MAPMARK_SHOVEL,
375
-        MAPMARK_SWORD,
376
-        MAPMARK_FLAG,
377
-        MAPMARK_LOCK,
378
-        MAPMARK_BAG,
379
-        MAPMARK_SKULL,
380
-        MAPMARK_DOLLAR,
381
-        MAPMARK_REDNORTH,
382
-        MAPMARK_REDSOUTH,
383
-        MAPMARK_REDEAST,
384
-        MAPMARK_REDWEST,
385
-        MAPMARK_GREENNORTH,
386
-        MAPMARK_GREENSOUTH
367
+        MapMarkTick = 0,
368
+        MapMarkQuestion,
369
+        MapMarkExclamation,
370
+        MapMarkStar,
371
+        MapMarkCross,
372
+        MapMarkTemple,
373
+        MapMarkKiss,
374
+        MapMarkShovel,
375
+        MapMarkSword,
376
+        MapMarkFlag,
377
+        MapMarkLock,
378
+        MapMarkBag,
379
+        MapMarkSkull,
380
+        MapMarkDollar,
381
+        MapMarkRedNorth,
382
+        MapMarkRedSouth,
383
+        MapMarkRedEast,
384
+        MapMarkRedWest,
385
+        MapMarkGreenNorth,
386
+        MapMarkGreenSouth
387 387
     };
388 388
 
389 389
     enum VipState
390 390
     {
391
-        VIPSTATE_OFFLINE = 0,
392
-        VIPSTATE_ONLINE = 1,
393
-        VIPSTATE_PENDING = 2
391
+        VipStateOffline = 0,
392
+        VipStateOnline = 1,
393
+        VipStatePending = 2
394
+    };
395
+
396
+    enum SpeedFormula
397
+    {
398
+        SpeedFormulaA = 0,
399
+        SpeedFormulaB,
400
+        SpeedFormulaC,
401
+        LastSpeedFormula
394 402
     };
395 403
 }
396 404
 

+ 35
- 6
src/otclient/creature.cpp View File

@@ -57,6 +57,7 @@ Creature::Creature() : Thing()
57 57
     m_nameCache.setFont(g_fonts.getFont("verdana-11px-rounded"));
58 58
     m_nameCache.setAlign(Fw::AlignTopCenter);
59 59
     m_footStep = 0;
60
+    m_speedFormula.fill(-1);
60 61
 }
61 62
 
62 63
 void Creature::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
@@ -615,6 +616,19 @@ void Creature::setEmblemTexture(const std::string& filename)
615 616
     m_emblemTexture = g_textures.getTexture(filename);
616 617
 }
617 618
 
619
+void Creature::setSpeedFormula(double speedA, double speedB, double speedC)
620
+{
621
+    m_speedFormula[Otc::SpeedFormulaA] = speedA;
622
+    m_speedFormula[Otc::SpeedFormulaB] = speedB;
623
+    m_speedFormula[Otc::SpeedFormulaC] = speedC;
624
+}
625
+
626
+bool Creature::hasSpeedFormula()
627
+{
628
+    return m_speedFormula[Otc::SpeedFormulaA] != -1 && m_speedFormula[Otc::SpeedFormulaB] != -1
629
+            && m_speedFormula[Otc::SpeedFormulaC] != -1;
630
+}
631
+
618 632
 void Creature::addTimedSquare(uint8 color)
619 633
 {
620 634
     m_showTimedSquare = true;
@@ -658,28 +672,43 @@ Point Creature::getDrawOffset()
658 672
 
659 673
 int Creature::getStepDuration()
660 674
 {
675
+    int speed = m_speed * 2;
661 676
     int groundSpeed = 0;
662 677
 
663 678
     Position tilePos = m_lastStepToPosition;
664 679
     if(!tilePos.isValid())
665 680
         tilePos = m_position;
666 681
     const TilePtr& tile = g_map.getTile(tilePos);
667
-    if(tile)
682
+    if(tile) {
668 683
         groundSpeed = tile->getGroundSpeed();
684
+        if(groundSpeed == 0)
685
+            groundSpeed = 150;
686
+    }
669 687
 
670 688
     int interval = 1000;
671
-    if(groundSpeed > 0 && m_speed > 0)
672
-        interval = (1000 * groundSpeed) / m_speed;
689
+    if(groundSpeed > 0 && speed > 0)
690
+        interval = 1000 * groundSpeed;
691
+
692
+    if(g_game.getFeature(Otc::GameNewSpeedLaw) && hasSpeedFormula()) {
693
+        int formulatedSpeed = 1;
694
+        if(speed > -m_speedFormula[Otc::SpeedFormulaB]) {
695
+            formulatedSpeed = std::max(1, (int)floor((m_speedFormula[Otc::SpeedFormulaA] * log((speed / 2)
696
+                 + m_speedFormula[Otc::SpeedFormulaB]) + m_speedFormula[Otc::SpeedFormulaC]) + 0.5));
697
+        }
698
+        interval = std::floor(interval / (double)formulatedSpeed);
699
+    }
700
+    else
701
+        interval /= speed;
673 702
 
674
-    if(g_game.getClientVersion() >= 900)
703
+    if(g_game.getProtocolVersion() >= 900)
675 704
         interval = (interval / g_game.getServerBeat()) * g_game.getServerBeat();
676 705
 
706
+    interval = std::max(interval, g_game.getServerBeat());
707
+
677 708
     if(m_lastStepDirection == Otc::NorthWest || m_lastStepDirection == Otc::NorthEast ||
678 709
        m_lastStepDirection == Otc::SouthWest || m_lastStepDirection == Otc::SouthEast)
679 710
         interval *= 3;
680 711
 
681
-    interval = std::max(interval, g_game.getServerBeat());
682
-
683 712
     return interval;
684 713
 }
685 714
 

+ 6
- 1
src/otclient/creature.h View File

@@ -44,7 +44,6 @@ public:
44 44
 
45 45
     Creature();
46 46
 
47
-
48 47
     virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
49 48
 
50 49
     void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView = nullptr);
@@ -65,6 +64,7 @@ public:
65 64
     void setShieldTexture(const std::string& filename, bool blink);
66 65
     void setEmblemTexture(const std::string& filename);
67 66
     void setPassable(bool passable) { m_passable = passable; }
67
+    void setSpeedFormula(double speedA, double speedB, double speedC);
68 68
 
69 69
     void addTimedSquare(uint8 color);
70 70
     void removeTimedSquare() { m_showTimedSquare = false; }
@@ -89,6 +89,9 @@ public:
89 89
     Position getLastStepFromPosition() { return m_lastStepFromPosition; }
90 90
     Position getLastStepToPosition() { return m_lastStepToPosition; }
91 91
     float getStepProgress() { return m_walkTimer.ticksElapsed() / getStepDuration(); }
92
+    double getSpeedFormula(Otc::SpeedFormula formula) { return m_speedFormula[formula]; }
93
+    bool hasSpeedFormula();
94
+    std::array<double, Otc::LastSpeedFormula> getSpeedFormulaArray() { return m_speedFormula; }
92 95
     virtual Point getDisplacement();
93 96
     virtual int getDisplacementX();
94 97
     virtual int getDisplacementY();
@@ -148,6 +151,8 @@ protected:
148 151
     CachedText m_nameCache;
149 152
     Color m_informationColor;
150 153
 
154
+    std::array<double, Otc::LastSpeedFormula> m_speedFormula;
155
+
151 156
     // walk related
152 157
     int m_walkAnimationPhase;
153 158
     int m_walkedPixels;

+ 40
- 12
src/otclient/game.cpp View File

@@ -39,7 +39,7 @@ Game g_game;
39 39
 Game::Game()
40 40
 {
41 41
     resetGameStates();
42
-    m_clientVersion = 0;
42
+    m_protocolVersion = 0;
43 43
 }
44 44
 
45 45
 void Game::terminate()
@@ -118,6 +118,18 @@ void Game::processLoginWait(const std::string& message, int time)
118 118
     g_lua.callGlobalField("g_game", "onLoginWait", message, time);
119 119
 }
120 120
 
121
+void Game::processPendingGame()
122
+{
123
+    m_localPlayer->setPendingGame(true);
124
+    g_lua.callGlobalField("g_game", "onPendingGame");
125
+}
126
+
127
+void Game::processEnterGame()
128
+{
129
+    m_localPlayer->setPendingGame(false);
130
+    g_lua.callGlobalField("g_game", "onEnterGame");
131
+}
132
+
121 133
 void Game::processGameStart()
122 134
 {
123 135
     m_online = true;
@@ -432,7 +444,7 @@ void Game::loginWorld(const std::string& account, const std::string& password, c
432 444
     if(m_protocolGame || isOnline())
433 445
         stdext::throw_exception("Unable to login into a world while already online or logging.");
434 446
 
435
-    if(m_clientVersion == 0)
447
+    if(m_protocolVersion == 0)
436 448
         stdext::throw_exception("Must set a valid game protocol version before logging.");
437 449
 
438 450
     // reset the new game state
@@ -642,7 +654,7 @@ void Game::look(const ThingPtr& thing)
642 654
     if(!canPerformGameAction() || !thing)
643 655
         return;
644 656
 
645
-    if(thing->isCreature() && m_clientVersion >= 961)
657
+    if(thing->isCreature() && m_protocolVersion >= 961)
646 658
         m_protocolGame->sendLookCreature(thing->getId());
647 659
     else
648 660
         m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackpos());
@@ -715,7 +727,7 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing)
715 727
     if(!pos.isValid()) // virtual item
716 728
         pos = Position(0xFFFF, 0, 0); // means that is a item in inventory
717 729
 
718
-    if(toThing->isCreature() && g_game.getClientVersion() >= 860)
730
+    if(toThing->isCreature() && g_game.getProtocolVersion() >= 860)
719 731
         m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackpos(), toThing->getId());
720 732
     else
721 733
         m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackpos(), toThing->getPosition(), toThing->getId(), toThing->getStackpos());
@@ -785,7 +797,7 @@ void Game::attack(CreaturePtr creature)
785 797
 
786 798
     setAttackingCreature(creature);
787 799
 
788
-    if(m_clientVersion >= 963) {
800
+    if(m_protocolVersion >= 963) {
789 801
         if(creature)
790 802
             m_seq = creature->getId();
791 803
     } else
@@ -808,7 +820,7 @@ void Game::follow(CreaturePtr creature)
808 820
 
809 821
     setFollowingCreature(creature);
810 822
 
811
-    if(m_clientVersion >= 963) {
823
+    if(m_protocolVersion >= 963) {
812 824
         if(creature)
813 825
             m_seq = creature->getId();
814 826
     } else
@@ -1173,15 +1185,15 @@ bool Game::canPerformGameAction()
1173 1185
     return m_online && m_localPlayer && !m_dead && m_protocolGame && m_protocolGame->isConnected() && checkBotProtection();
1174 1186
 }
1175 1187
 
1176
-void Game::setClientVersion(int version)
1188
+void Game::setProtocolVersion(int version)
1177 1189
 {
1178
-    if(m_clientVersion == version)
1190
+    if(m_protocolVersion == version)
1179 1191
         return;
1180 1192
 
1181 1193
     if(isOnline())
1182
-        stdext::throw_exception("Unable to change client version while online");
1194
+        stdext::throw_exception("Unable to change protocol version while online");
1183 1195
 
1184
-    if(version != 0 && (version < 810 || version > 981))
1196
+    if(version != 0 && (version < 810 || version > 973))
1185 1197
         stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
1186 1198
 
1187 1199
     m_features.reset();
@@ -1233,15 +1245,31 @@ void Game::setClientVersion(int version)
1233 1245
         enableFeature(Otc::GameOfflineTrainingTime);
1234 1246
     }
1235 1247
 
1236
-    if(version >= 980) {
1248
+    if(version >= 973) {
1237 1249
         enableFeature(Otc::GameLoginPending);
1238 1250
         enableFeature(Otc::GameNewSpeedLaw);
1239 1251
     }
1240 1252
 
1241
-    m_clientVersion = version;
1253
+    m_protocolVersion = version;
1242 1254
 
1243 1255
     Proto::buildMessageModesMap(version);
1244 1256
 
1257
+    g_lua.callGlobalField("g_game", "onProtocolVersionChange", version);
1258
+}
1259
+
1260
+void Game::setClientVersion(int version)
1261
+{
1262
+    if(m_clientVersion == version)
1263
+        return;
1264
+
1265
+    if(isOnline())
1266
+        stdext::throw_exception("Unable to change client version while online");
1267
+
1268
+    if(version != 0 && (version < 981 || version > 981))
1269
+        stdext::throw_exception(stdext::format("Client version %d not supported", version));
1270
+
1271
+    m_clientVersion = version;
1272
+
1245 1273
     g_lua.callGlobalField("g_game", "onClientVersionChange", version);
1246 1274
 }
1247 1275
 

+ 7
- 0
src/otclient/game.h View File

@@ -59,6 +59,9 @@ protected:
59 59
     void processLoginAdvice(const std::string& message);
60 60
     void processLoginWait(const std::string& message, int time);
61 61
 
62
+    void processPendingGame();
63
+    void processEnterGame();
64
+
62 65
     void processGameStart();
63 66
     void processGameEnd();
64 67
     void processDeath(int penality);
@@ -248,6 +251,9 @@ public:
248 251
     void setFeature(Otc::GameFeature feature, bool enabled) { m_features.set(feature, enabled); }
249 252
     bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
250 253
 
254
+    void setProtocolVersion(int version);
255
+    int getProtocolVersion() { return m_protocolVersion; }
256
+
251 257
     void setClientVersion(int version);
252 258
     int getClientVersion() { return m_clientVersion; }
253 259
 
@@ -308,6 +314,7 @@ private:
308 314
     std::string m_worldName;
309 315
     std::bitset<Otc::LastGameFeature> m_features;
310 316
     ScheduledEventPtr m_pingEvent;
317
+    int m_protocolVersion;
311 318
     int m_clientVersion;
312 319
 };
313 320
 

+ 1
- 1
src/otclient/item.cpp View File

@@ -216,7 +216,7 @@ int Item::getSubType()
216 216
 {
217 217
     if(isSplash() || isFluidContainer())
218 218
         return m_countOrSubType;
219
-    if(g_game.getClientVersion() >= 900)
219
+    if(g_game.getProtocolVersion() >= 900)
220 220
         return 0;
221 221
     return 1;
222 222
 }

+ 0
- 6
src/otclient/localplayer.cpp View File

@@ -28,12 +28,6 @@
28 28
 
29 29
 LocalPlayer::LocalPlayer()
30 30
 {
31
-    m_preWalking = false;
32
-    m_lastPrewalkDone = true;
33
-    m_autoWalking = false;
34
-    m_known = false;
35
-    m_premium = false;
36
-
37 31
     m_states = 0;
38 32
     m_vocation = 0;
39 33
     m_walkLockExpiration = 0;

+ 14
- 9
src/otclient/localplayer.h View File

@@ -53,6 +53,7 @@ public:
53 53
     void setSoul(double soul);
54 54
     void setStamina(double stamina);
55 55
     void setKnown(bool known) { m_known = known; }
56
+    void setPendingGame(bool pending) { m_pending = pending; }
56 57
     void setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item);
57 58
     void setVocation(int vocation);
58 59
     void setPremium(bool premium);
@@ -92,6 +93,7 @@ public:
92 93
     bool isPreWalking() { return m_preWalking; }
93 94
     bool isAutoWalking() { return m_autoWalking; }
94 95
     bool isPremium() { return m_premium; }
96
+    bool isPendingGame() { return m_pending; }
95 97
 
96 98
     LocalPlayerPtr asLocalPlayer() { return static_self_cast<LocalPlayer>(); }
97 99
     bool isLocalPlayer() { return true; }
@@ -113,27 +115,30 @@ protected:
113 115
 
114 116
 private:
115 117
     // walk related
116
-    bool m_preWalking;
117
-    bool m_lastPrewalkDone;
118
-    bool m_autoWalking;
119
-    bool m_premium;
118
+    Timer m_walkPingTimer;
120 119
     Position m_lastPrewalkDestionation;
121
-    ItemPtr m_inventoryItems[Otc::LastInventorySlot];
122 120
     ScheduledEventPtr m_autoWalkEndEvent;
121
+    ticks_t m_walkLockExpiration;
122
+    int m_lastWalkPing;
123
+    stdext::boolean<false> m_preWalking;
124
+    stdext::boolean<true> m_lastPrewalkDone;
125
+    stdext::boolean<false> m_autoWalking;
123 126
     stdext::boolean<false> m_waitingWalkPong;
124
-    Timer m_walkPingTimer;
127
+
128
+    stdext::boolean<false> m_premium;
129
+    stdext::boolean<false> m_known;
130
+    stdext::boolean<false> m_pending;
131
+
132
+    ItemPtr m_inventoryItems[Otc::LastInventorySlot];
125 133
     Timer m_idleTimer;
126
-    int m_lastWalkPing;
127 134
 
128 135
     std::array<int, Otc::LastSkill> m_skillsLevel;
129 136
     std::array<int, Otc::LastSkill> m_skillsBaseLevel;
130 137
     std::array<int, Otc::LastSkill> m_skillsLevelPercent;
131 138
     std::vector<int> m_spells;
132 139
 
133
-    bool m_known;
134 140
     int m_states;
135 141
     int m_vocation;
136
-    ticks_t m_walkLockExpiration;
137 142
 
138 143
     double m_health;
139 144
     double m_maxHealth;

+ 2
- 0
src/otclient/luafunctions.cpp View File

@@ -220,6 +220,8 @@ void OTClient::registerLuaFunctions()
220 220
     g_lua.bindSingletonFunction("g_game", "getServerBeat", &Game::getServerBeat, &g_game);
221 221
     g_lua.bindSingletonFunction("g_game", "getLocalPlayer", &Game::getLocalPlayer, &g_game);
222 222
     g_lua.bindSingletonFunction("g_game", "getProtocolGame", &Game::getProtocolGame, &g_game);
223
+    g_lua.bindSingletonFunction("g_game", "getProtocolVersion", &Game::getProtocolVersion, &g_game);
224
+    g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
223 225
     g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
224 226
     g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
225 227
     g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);

+ 10
- 10
src/otclient/map.cpp View File

@@ -459,20 +459,20 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
459 459
     std::vector<Otc::Direction>& dirs = std::get<0>(ret);
460 460
     Otc::PathFindResult& result = std::get<1>(ret);
461 461
 
462
-    result = Otc::PATHFIND_RESULT_NO_WAY;
462
+    result = Otc::PathFindResultNoWay;
463 463
 
464 464
     if(startPos == goalPos) {
465
-        result = Otc::PATHFIND_RESULT_SAME_POSITION;
465
+        result = Otc::PathFindResultSamePosition;
466 466
         return ret;
467 467
     }
468 468
 
469 469
     if(startPos.z != goalPos.z) {
470
-        result = Otc::PATHFIND_RESULT_IMPOSSIBLE;
470
+        result = Otc::PathFindResultImpossible;
471 471
         return ret;
472 472
     }
473 473
 
474 474
     if(startPos.distance(goalPos) > maxSteps) {
475
-        result = Otc::PATHFIND_RESULT_TOO_FAR;
475
+        result = Otc::PathFindResultTooFar;
476 476
         return ret;
477 477
     }
478 478
 
@@ -486,7 +486,7 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
486 486
     while(currentNode) {
487 487
         // too far
488 488
         if(currentNode->steps >= maxSteps) {
489
-            result = Otc::PATHFIND_RESULT_TOO_FAR;
489
+            result = Otc::PathFindResultTooFar;
490 490
             break;
491 491
         }
492 492
 
@@ -507,14 +507,14 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
507 507
                 const TilePtr& tile = getTile(neighborPos);
508 508
 
509 509
                 if(neighborPos != goalPos) {
510
-                    if(!(flags & Otc::PATHFIND_ALLOW_NULLTILES) && !tile)
510
+                    if(!(flags & Otc::PathFindAllowNullTiles) && !tile)
511 511
                         continue;
512 512
                     if(tile) {
513
-                        if(!(flags & Otc::PATHFIND_ALLOW_CREATURES) && tile->hasCreature())
513
+                        if(!(flags & Otc::PathFindAllowCreatures) && tile->hasCreature())
514 514
                             continue;
515
-                        if(!(flags & Otc::PATHFIND_ALLOW_NONPATHABLE) && !tile->isPathable())
515
+                        if(!(flags & Otc::PathFindAllowNonPathable) && !tile->isPathable())
516 516
                             continue;
517
-                        if(!(flags & Otc::PATHFIND_ALLOW_NONWALKABLE) && !tile->isWalkable())
517
+                        if(!(flags & Otc::PathFindAllowNonWalkable) && !tile->isWalkable())
518 518
                             continue;
519 519
                     }
520 520
                 }
@@ -568,7 +568,7 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
568 568
         }
569 569
         dirs.pop_back();
570 570
         std::reverse(dirs.begin(), dirs.end());
571
-        result = Otc::PATHFIND_RESULT_OK;
571
+        result = Otc::PathFineResultOk;
572 572
     }
573 573
 
574 574
     for(auto it : nodes)

+ 1
- 1
src/otclient/mapio.cpp View File

@@ -473,7 +473,7 @@ void Map::saveOtcm(const std::string& fileName)
473 473
         // version 1 header
474 474
         fin->addString("OTCM 1.0"); // map description
475 475
         fin->addU32(g_things.getDatSignature());
476
-        fin->addU16(g_game.getClientVersion());
476
+        fin->addU16(g_game.getProtocolVersion());
477 477
         fin->addString(g_game.getWorldName());
478 478
 
479 479
         // go back and rewrite where the map data starts

+ 1
- 1
src/otclient/protocolgame.cpp View File

@@ -56,7 +56,7 @@ void ProtocolGame::onRecv(const InputMessagePtr& inputMessage)
56 56
     if(m_firstRecv) {
57 57
         m_firstRecv = false;
58 58
 
59
-        if(g_game.getClientVersion() > 810) {
59
+        if(g_game.getProtocolVersion() > 810) {
60 60
             int size = inputMessage->getU16();
61 61
             if(size != inputMessage->getUnreadSize()) {
62 62
                 g_logger.traceError("invalid message size");

+ 12
- 9
src/otclient/protocolgameparse.cpp View File

@@ -342,6 +342,7 @@ void ProtocolGame::parseInitGame(const InputMessagePtr& msg)
342 342
         double speedA = msg->getDouble();
343 343
         double speedB = msg->getDouble();
344 344
         double speedC = msg->getDouble();
345
+        m_localPlayer->setSpeedFormula(speedA, speedB, speedC);
345 346
     }
346 347
     bool canReportBugs = msg->getU8();
347 348
 
@@ -353,11 +354,13 @@ void ProtocolGame::parseInitGame(const InputMessagePtr& msg)
353 354
 void ProtocolGame::parsePendingGame(const InputMessagePtr& msg)
354 355
 {
355 356
     //set player to pending game state
357
+    g_game.processPendingGame();
356 358
 }
357 359
 
358 360
 void ProtocolGame::parseEnterGame(const InputMessagePtr& msg)
359 361
 {
360 362
     //set player to entered game state
363
+    g_game.processEnterGame();
361 364
 }
362 365
 
363 366
 void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
@@ -366,7 +369,7 @@ void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
366 369
 
367 370
     int numViolationReasons;
368 371
 
369
-    if(g_game.getClientVersion() >= 854)
372
+    if(g_game.getProtocolVersion() >= 854)
370 373
         numViolationReasons = 20;
371 374
     else
372 375
         numViolationReasons = 32;
@@ -489,7 +492,7 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg)
489 492
     Position pos = getPosition(msg);
490 493
     int stackPos = -1;
491 494
 
492
-    if(g_game.getClientVersion() >= 854)
495
+    if(g_game.getProtocolVersion() >= 854)
493 496
         stackPos = msg->getU8();
494 497
 
495 498
     ThingPtr thing = getThing(msg);
@@ -617,7 +620,7 @@ void ProtocolGame::parseOpenNpcTrade(const InputMessagePtr& msg)
617 620
 
618 621
     int listCount;
619 622
 
620
-    if(g_game.getClientVersion() >= 900)
623
+    if(g_game.getProtocolVersion() >= 900)
621 624
         listCount = msg->getU16();
622 625
     else
623 626
         listCount = msg->getU8();
@@ -644,7 +647,7 @@ void ProtocolGame::parsePlayerGoods(const InputMessagePtr& msg)
644 647
     std::vector<std::tuple<ItemPtr, int>> goods;
645 648
 
646 649
     int money;
647
-    if(g_game.getClientVersion() >= 980)
650
+    if(g_game.getProtocolVersion() >= 973)
648 651
         money = msg->getU64();
649 652
     else
650 653
         money = msg->getU32();
@@ -993,7 +996,7 @@ void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
993 996
 void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg)
994 997
 {
995 998
     uint seq = 0;
996
-    if(g_game.getClientVersion() >= 860)
999
+    if(g_game.getProtocolVersion() >= 860)
997 1000
         seq = msg->getU32();
998 1001
 
999 1002
     g_game.processAttackCancel(seq);
@@ -1295,7 +1298,7 @@ void ProtocolGame::parseVipAdd(const InputMessagePtr& msg)
1295 1298
 
1296 1299
     id = msg->getU32();
1297 1300
     name = g_game.formatCreatureName(msg->getString());
1298
-    if(g_game.getClientVersion() >= 963) {
1301
+    if(g_game.getProtocolVersion() >= 963) {
1299 1302
         desc = msg->getString();
1300 1303
         markId = msg->getU32();
1301 1304
         notifyLogin = msg->getU8();
@@ -1614,7 +1617,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
1614 1617
             uint id = msg->getU32();
1615 1618
 
1616 1619
             int creatureType;
1617
-            if(g_game.getClientVersion() >= 910)
1620
+            if(g_game.getProtocolVersion() >= 910)
1618 1621
                 creatureType = msg->getU8();
1619 1622
             else {
1620 1623
                 if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId)
@@ -1670,7 +1673,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
1670 1673
         if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
1671 1674
             emblem = msg->getU8();
1672 1675
 
1673
-        if(g_game.getClientVersion() >= 854)
1676
+        if(g_game.getProtocolVersion() >= 854)
1674 1677
             unpass = msg->getU8();
1675 1678
 
1676 1679
         if(creature) {
@@ -1699,7 +1702,7 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
1699 1702
         if(creature)
1700 1703
             creature->turn(direction);
1701 1704
 
1702
-        if(g_game.getClientVersion() >= 953) {
1705
+        if(g_game.getProtocolVersion() >= 953) {
1703 1706
             bool unpass = msg->getU8();
1704 1707
 
1705 1708
             if(creature)

+ 7
- 2
src/otclient/protocolgamesend.cpp View File

@@ -51,7 +51,12 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
51 51
     msg->addU8(Proto::ClientEnterGame);
52 52
 
53 53
     msg->addU16(g_lua.callGlobalField<int>("g_game", "getOsType"));
54
-    msg->addU16(g_game.getClientVersion());
54
+    msg->addU16(g_game.getProtocolVersion());
55
+
56
+    if(g_game.getProtocolVersion() >= 971) {
57
+        msg->addU32(g_game.getClientVersion());
58
+        msg->addU8(0); // clientType
59
+    }
55 60
 
56 61
     int paddingBytes = 128;
57 62
     msg->addU8(0); // first RSA byte must be 0
@@ -588,7 +593,7 @@ void ProtocolGame::sendShareExperience(bool active)
588 593
     msg->addU8(Proto::ClientShareExperience);
589 594
     msg->addU8(active ? 0x01 : 0x00);
590 595
 
591
-    if(g_game.getClientVersion() < 910)
596
+    if(g_game.getProtocolVersion() < 910)
592 597
         msg->addU8(0);
593 598
 
594 599
     send(msg);

+ 1
- 1
src/otclient/tile.cpp View File

@@ -189,7 +189,7 @@ void Tile::addThing(const ThingPtr& thing, int stackPos)
189 189
                 append = (priority <= 3);
190 190
 
191 191
                 // newer protocols does not store creatures in reverse order
192
-                if(g_game.getClientVersion() >= 854 && priority == 4)
192
+                if(g_game.getProtocolVersion() >= 854 && priority == 4)
193 193
                     append = !append;
194 194
             }
195 195
 

Loading…
Cancel
Save