Browse Source

Implemented the mount interface, Fixed some interface stuff, Some cosmetics, and Updated the outfits window

* Added new arrow buttons.
* Fixed the vertical separator.
* Added new game_playermount module to handle player mounting.
* Moved the battle icons to /images.
* Outfit window accommodates for mounts, loads addons more efficiently and keeps addons set on update, added new Outfit.randomize function that allows you to randomize your outfit colors, and set up a new layout.
BeniS 8 years ago
parent
commit
5520501673
39 changed files with 507 additions and 268 deletions
  1. BIN
      modules/client_skins/skins/default/images/arrow_down.png
  2. BIN
      modules/client_skins/skins/default/images/arrow_left.png
  3. BIN
      modules/client_skins/skins/default/images/arrow_right.png
  4. BIN
      modules/client_skins/skins/default/images/arrow_up.png
  5. BIN
      modules/client_skins/skins/default/images/vertical_separator.png
  6. 1
    1
      modules/client_skins/skins/default/styles/buttons.otui
  7. 1
    1
      modules/client_skins/skins/default/styles/separators.otui
  8. 1
    1
      modules/corelib/mouse.lua
  9. 1
    0
      modules/game/game.otmod
  10. 3
    3
      modules/game_battle/battle.lua
  11. 5
    5
      modules/game_battle/battle.otui
  12. 0
    0
      modules/game_battle/images/battle_monsters.png
  13. 0
    0
      modules/game_battle/images/battle_npcs.png
  14. 0
    0
      modules/game_battle/images/battle_party.png
  15. 0
    0
      modules/game_battle/images/battle_players.png
  16. 0
    0
      modules/game_battle/images/battle_skulls.png
  17. 5
    5
      modules/game_interface/gameinterface.lua
  18. 6
    4
      modules/game_minimap/minimap.lua
  19. 5
    9
      modules/game_minimap/minimap.otui
  20. 126
    49
      modules/game_outfit/outfit.lua
  21. 0
    145
      modules/game_outfit/outfit.otui
  22. 221
    0
      modules/game_outfit/outfitwindow.otui
  23. 2
    2
      modules/game_playerdeath/playerdeath.lua
  24. 1
    1
      modules/game_playerdeath/playerdeath.otmod
  25. 38
    0
      modules/game_playermount/playermount.lua
  26. 15
    0
      modules/game_playermount/playermount.otmod
  27. 0
    0
      modules/game_playermount/playermount.otui
  28. 3
    3
      modules/game_textwindow/textwindow.lua
  29. 21
    11
      src/otclient/game.cpp
  30. 9
    6
      src/otclient/game.h
  31. 1
    0
      src/otclient/luafunctions.cpp
  32. 8
    0
      src/otclient/luavaluecasts.cpp
  33. 1
    0
      src/otclient/luavaluecasts.h
  34. 3
    1
      src/otclient/outfit.h
  35. 3
    3
      src/otclient/protocolcodes.h
  36. 1
    1
      src/otclient/protocolgame.h
  37. 14
    11
      src/otclient/protocolgameparse.cpp
  38. 11
    5
      src/otclient/protocolgamesend.cpp
  39. 1
    1
      src/otclient/uimap.cpp

BIN
modules/client_skins/skins/default/images/arrow_down.png View File


BIN
modules/client_skins/skins/default/images/arrow_left.png View File


BIN
modules/client_skins/skins/default/images/arrow_right.png View File


BIN
modules/client_skins/skins/default/images/arrow_up.png View File


BIN
modules/client_skins/skins/default/images/vertical_separator.png View File


+ 1
- 1
modules/client_skins/skins/default/styles/buttons.otui View File

@@ -38,4 +38,4 @@ TabButton < UIButton
38 38
 
39 39
   $on:
40 40
     image-clip: 0 40 20 20
41
-    color: #80c7f8
41
+    color: #80c7f8

+ 1
- 1
modules/client_skins/skins/default/styles/separators.otui View File

@@ -6,7 +6,7 @@ HorizontalSeparator < UIWidget
6 6
   focusable: false
7 7
 
8 8
 VerticalSeparator < UIWidget
9
-  image-source: /images/horizontal_separator.png
9
+  image-source: /images/vertical_separator.png
10 10
   image-border-left: 2
11 11
   width: 2
12 12
   phantom: true

+ 1
- 1
modules/corelib/mouse.lua View File

@@ -35,7 +35,7 @@ end
35 35
 function g_mouse.bindAutoPress(widget, callback, delay, button)
36 36
   local button = button or MouseLeftButton
37 37
   connect(widget, { onMousePress = function(widget, mousePos, mouseButton)
38
-    if(mouseButton ~= button) then
38
+    if mouseButton ~= button then
39 39
       return false
40 40
     end
41 41
     local startTime = g_clock.millis()

+ 1
- 0
modules/game/game.otmod View File

@@ -31,6 +31,7 @@ Module
31 31
     - game_bugreport
32 32
     - game_shaders
33 33
     - game_playerdeath
34
+    - game_playermount
34 35
 
35 36
   @onLoad: |
36 37
     dofile 'const'

+ 3
- 3
modules/game_battle/battle.lua View File

@@ -84,10 +84,10 @@ function Battle.terminate()
84 84
   mouseWidget:destroy()
85 85
   mouseWidget = nil
86 86
 
87
-  disconnect(Creature, {  onSkullChange = Battle.checkCreatureSkull,
87
+  disconnect(Creature, { onSkullChange = Battle.checkCreatureSkull,
88 88
                           onEmblemChange = Battle.checkCreatureEmblem } )
89 89
 
90
-  disconnect(g_game, {    onAttackingCreatureChange = Battle.onAttack } )
90
+  disconnect(g_game, { onAttackingCreatureChange = Battle.onAttack } )
91 91
 
92 92
   Battle = nil
93 93
 end
@@ -191,7 +191,7 @@ function Battle.addCreature(creature)
191 191
   local creatureId = creature:getId()
192 192
 
193 193
   if battleButtonsByCreaturesList[creatureId] == nil then
194
-    local battleButton = g_ui.loadUI('battleButton.otui', battlePanel)
194
+    local battleButton = g_ui.loadUI('battlebutton.otui', battlePanel)
195 195
     local creatureWidget = battleButton:getChildById('creature')
196 196
     local labelWidget = battleButton:getChildById('label')
197 197
     local lifeBarWidget = battleButton:getChildById('lifeBar')

+ 5
- 5
modules/game_battle/battle.otui View File

@@ -22,19 +22,19 @@ BattleIcon < UICheckBox
22 22
     image-color: #ffffff88
23 23
 
24 24
 BattlePlayers < BattleIcon
25
-  image-source: /game_battle/battle_players.png
25
+  image-source: /game_battle/images/battle_players.png
26 26
 
27 27
 BattleNPCs < BattleIcon
28
-  image-source: /game_battle/battle_npcs.png
28
+  image-source: /game_battle/images/battle_npcs.png
29 29
 
30 30
 BattleMonsters < BattleIcon
31
-  image-source: /game_battle/battle_monsters.png
31
+  image-source: /game_battle/images/battle_monsters.png
32 32
 
33 33
 BattleSkulls < BattleIcon
34
-  image-source: /game_battle/battle_skulls.png
34
+  image-source: /game_battle/images/battle_skulls.png
35 35
 
36 36
 BattleParty < BattleIcon
37
-  image-source: /game_battle/battle_party.png
37
+  image-source: /game_battle/images/battle_party.png
38 38
 
39 39
 MiniWindow
40 40
   id: battleWindow

modules/game_battle/battle_monsters.png → modules/game_battle/images/battle_monsters.png View File


modules/game_battle/battle_npcs.png → modules/game_battle/images/battle_npcs.png View File


modules/game_battle/battle_party.png → modules/game_battle/images/battle_party.png View File


modules/game_battle/battle_players.png → modules/game_battle/images/battle_players.png View File


modules/game_battle/battle_skulls.png → modules/game_battle/images/battle_skulls.png View File


+ 5
- 5
modules/game_interface/gameinterface.lua View File

@@ -117,15 +117,15 @@ function GameInterface.show()
117 117
 end
118 118
 
119 119
 function GameInterface.hide()
120
-  if(logoutWindow) then
120
+  if logoutWindow then
121 121
     logoutWindow:destroy()
122 122
     logoutWindow = nil
123 123
   end
124
-  if(exitWindow) then
124
+  if exitWindow then
125 125
     exitWindow:destroy()
126 126
     exitWindow = nil
127 127
   end
128
-  if(countWindow) then 
128
+  if countWindow then 
129 129
     countWindow:destroy()
130 130
     countWindow = nil
131 131
   end
@@ -144,7 +144,7 @@ function GameInterface.exit()
144 144
 end
145 145
 
146 146
 function GameInterface.tryExit()
147
-  if(exitWindow) then
147
+  if exitWindow then
148 148
     return true
149 149
   end
150 150
   exitWindow = g_ui.createWidget('ExitWindow', rootWidget)
@@ -183,7 +183,7 @@ function GameInterface.logout()
183 183
 end
184 184
 
185 185
 function GameInterface.tryLogout()
186
-  if(logoutWindow) then
186
+  if logoutWindow then
187 187
     return
188 188
   end
189 189
   logoutWindow = g_ui.createWidget('LogoutWindow', rootWidget)

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

@@ -1,5 +1,8 @@
1 1
 Minimap = {}
2 2
 
3
+-- public variables
4
+minimapFirstLoad = true
5
+
3 6
 -- private variables
4 7
 local minimapWidget
5 8
 local minimapButton
@@ -8,7 +11,6 @@ local DEFAULT_ZOOM = 60
8 11
 local MAX_FLOOR_UP = 0
9 12
 local MAX_FLOOR_DOWN = 15
10 13
 local navigating = false
11
-minimapFirstLoad = true
12 14
 
13 15
 -- private functions
14 16
 function onMinimapMouseRelease(self, mousePosition, mouseButton)
@@ -54,9 +56,9 @@ function Minimap.init()
54 56
 
55 57
   minimapWindow = g_ui.loadUI('minimap.otui', GameInterface.getRightPanel())
56 58
 
57
-
58 59
   minimapWidget = minimapWindow:recursiveGetChildById('minimap')
59 60
   g_mouse.bindAutoPress(minimapWidget, Minimap.compassClick, nil, MouseRightButton)
61
+  g_mouse.bindAutoPress(minimapWidget, Minimap.compassClick, nil, MouseLeftButton)
60 62
   minimapWidget:setAutoViewMode(false)
61 63
   minimapWidget:setViewMode(1) -- mid view
62 64
   minimapWidget:setDrawMinimapColors(true)
@@ -150,13 +152,13 @@ function Minimap.onButtonClick(id)
150 152
   elseif id == "floorUp" then
151 153
     local pos = minimapWidget:getCameraPosition()
152 154
     pos.z = pos.z - 1
153
-    if(pos.z > MAX_FLOOR_UP) then
155
+    if pos.z > MAX_FLOOR_UP then
154 156
       minimapWidget:setCameraPosition(pos)
155 157
     end
156 158
   elseif id == "floorDown" then
157 159
     local pos = minimapWidget:getCameraPosition()
158 160
     pos.z = pos.z + 1
159
-    if(pos.z < MAX_FLOOR_DOWN) then
161
+    if pos.z < MAX_FLOOR_DOWN then
160 162
       minimapWidget:setCameraPosition(pos)
161 163
     end
162 164
   end

+ 5
- 9
modules/game_minimap/minimap.otui View File

@@ -1,5 +1,6 @@
1 1
 MapControl < Button
2 2
   size: 20 20
3
+  icon-clip: 0 32 16 16
3 4
 
4 5
   $pressed:
5 6
     icon-clip: 0 0 16 16
@@ -7,19 +8,16 @@ MapControl < Button
7 8
   $hover !pressed:
8 9
     icon-clip: 0 16 16 16
9 10
 
10
-  $!pressed !hover:
11
-    icon-clip: 0 32 16 16
12
-
13 11
 FloorUpControl < MapControl
14 12
   icon-source: /game_minimap/floor_up.png
15 13
 
16 14
 FloorDownControl < MapControl
17 15
   icon-source: /game_minimap/floor_down.png
18 16
 
19
-//ZoomOutControl < MapControl
17
+ZoomOutControl < MapControl
20 18
   //image-source: /game_minimap/zoom_out.png
21 19
 
22
-//ZoomInControl < MapControl
20
+ZoomInControl < MapControl
23 21
   //image-source: /game_minimap/zoom_in.png
24 22
 
25 23
 MiniWindow
@@ -64,10 +62,9 @@ MiniWindow
64 62
       enabled: true
65 63
       @onClick: Minimap.onButtonClick(self:getId())
66 64
 
67
-    Button
65
+    ZoomInControl
68 66
       id: zoomIn
69 67
       text: +
70
-      size: 20 20
71 68
       anchors.right: parent.right
72 69
       anchors.bottom: parent.bottom
73 70
       margin-right: 4
@@ -75,11 +72,10 @@ MiniWindow
75 72
       enabled: true
76 73
       @onClick: Minimap.onButtonClick(self:getId())
77 74
 
78
-    Button
75
+    ZoomOutControl
79 76
       id: zoomOut
80 77
       text: -
81 78
       font: terminus-14px-bold
82
-      size: 20 20
83 79
       anchors.right: parent.right
84 80
       anchors.bottom: parent.bottom
85 81
       margin-right: 4

+ 126
- 49
modules/game_outfit/outfit.lua View File

@@ -1,13 +1,30 @@
1 1
 Outfit = {}
2 2
 
3 3
 -- private variables
4
+local addonSets = {
5
+  [1] = { 1 },
6
+  [2] = { 2 },
7
+  [3] = { 1, 2 },
8
+  [4] = { 3 },
9
+  [5] = { 1, 3 },
10
+  [6] = { 2, 3 },
11
+  [7] = { 1, 2, 3 }
12
+}
4 13
 local outfitWindow
5
-local outfitCreature
6 14
 local outfit
7 15
 local outfits
16
+local outfitCreature
8 17
 local currentOutfit = 1
18
+
19
+local addons
9 20
 local currentColorBox
10 21
 local currentClotheButtonBox
22
+local colorBoxes = {}
23
+
24
+local mount
25
+local mounts
26
+local mountCreature
27
+local currentMount = 1
11 28
 
12 29
 -- private functions
13 30
 local function onAddonCheckChange(addon, value)
@@ -71,51 +88,50 @@ local function onClotheCheckChange(clotheButtonBox)
71 88
   end
72 89
 end
73 90
 
74
-local function update()
91
+local function updateOutfit()
92
+  if table.empty(outfits) then
93
+    return
94
+  end
75 95
   local nameWidget = outfitWindow:getChildById('outfitName')
76 96
   nameWidget:setText(outfits[currentOutfit][2])
77 97
 
78 98
   local availableAddons = outfits[currentOutfit][3]
79
-  local addon1 = outfitWindow:getChildById('addon1')
80
-  local addon2 = outfitWindow:getChildById('addon2')
81
-  local addon3 = outfitWindow:getChildById('addon3')
82
-  addon1:setChecked(false)
83
-  addon2:setChecked(false)
84
-  addon3:setChecked(false)
85
-  addon1.onCheckChange = function(self) onAddonCheckChange(self, 1) end
86
-  addon2.onCheckChange = function(self) onAddonCheckChange(self, 2) end
87
-  addon3.onCheckChange = function(self) onAddonCheckChange(self, 4) end
88
-  addon1:setEnabled(false)
89
-  addon2:setEnabled(false)
90
-  addon3:setEnabled(false)
91
-
92
-  -- Maybe rework this someday
93
-  if availableAddons == 1 then
94
-    addon1:setEnabled(true)
95
-  elseif availableAddons == 2 then
96
-    addon2:setEnabled(true)
97
-  elseif availableAddons == 3 then
98
-    addon1:setEnabled(true)
99
-    addon2:setEnabled(true)
100
-  elseif availableAddons == 4 then
101
-    addon3:setEnabled(true)
102
-  elseif availableAddons == 5 then
103
-    addon1:setEnabled(true)
104
-    addon3:setEnabled(true)
105
-  elseif availableAddons == 6 then
106
-    addon2:setEnabled(true)
107
-    addon3:setEnabled(true)
108
-  elseif availableAddons == 7 then
109
-    addon1:setEnabled(true)
110
-    addon2:setEnabled(true)
111
-    addon3:setEnabled(true)
99
+
100
+  local prevAddons = {}
101
+  for k, addon in pairs(addons) do
102
+    prevAddons[k] = addon.widget:isChecked()
103
+    addon.widget:setChecked(false)
104
+    addon.widget:setEnabled(false)
105
+  end
106
+
107
+  if availableAddons > 0 then
108
+    for _, i in pairs(addonSets[availableAddons]) do
109
+      addons[i].widget:setEnabled(true)
110
+    end
112 111
   end
113 112
 
114
-  outfit.type = outfits[currentOutfit][1]
115 113
   outfit.addons = 0
114
+  for k, addon in pairs(prevAddons) do
115
+    if addon and addons[k].widget:isEnabled() then
116
+      addons[k].widget:setChecked(true)
117
+    end
118
+  end
119
+
120
+  outfit.type = outfits[currentOutfit][1]
116 121
   outfitCreature:setOutfit(outfit)
117 122
 end
118 123
 
124
+function updateMount()
125
+  if table.empty(mounts) then
126
+    return
127
+  end
128
+  local nameMountWidget = outfitWindow:getChildById('mountName')
129
+  nameMountWidget:setText(mounts[currentMount][2])
130
+  
131
+  mount.type = mounts[currentMount][1]
132
+  mountCreature:setOutfit(mount)
133
+end
134
+
119 135
 -- public functions
120 136
 function Outfit.init()
121 137
   connect(g_game, { onOpenOutfitWindow = Outfit.create,
@@ -126,20 +142,36 @@ function Outfit.terminate()
126 142
   disconnect(g_game, { onOpenOutfitWindow = Outfit.create,
127 143
                        onGameEnd = Outfit.destroy })
128 144
   Outfit.destroy()
129
-
130 145
   Outfit = nil
131 146
 end
132 147
 
133
-function Outfit.create(creature, outfitList)
134
-  outfitCreature = creature
148
+function Outfit.create(creatureOutfit, outfitList, creatureMount, mountList)
149
+  outfitCreature = creatureOutfit
150
+  mountCreature = creatureMount
135 151
   outfits = outfitList
136
-  Outfit.destroy()
137
-
138
-  outfitWindow = g_ui.displayUI('outfit.otui')
139
-  --outfitWindow:lock()
152
+  mounts = mountList
153
+  Outfit.destroy() 
140 154
 
155
+  outfitWindow = g_ui.displayUI('outfitwindow.otui')
141 156
   outfit = outfitCreature:getOutfit()
142
-
157
+  mount = mountCreature:getOutfit()
158
+  
159
+  addons = {
160
+    [1] = {widget = outfitWindow:getChildById('addon1'), value = 1},
161
+    [2] = {widget = outfitWindow:getChildById('addon2'), value = 2},
162
+    [3] = {widget = outfitWindow:getChildById('addon3'), value = 4}
163
+  }
164
+  
165
+  for k, addon in pairs(addons) do
166
+    addon.widget.onCheckChange = function(self) onAddonCheckChange(self, addon.value) end
167
+  end
168
+  
169
+  if outfit.addons > 0 then
170
+    for _, i in pairs(addonSets[outfit.addons]) do
171
+      addons[i].widget:setChecked(true)
172
+    end
173
+  end
174
+  
143 175
   currentClotheButtonBox = outfitWindow:getChildById('head')
144 176
   outfitWindow:getChildById('head').onCheckChange = onClotheCheckChange
145 177
   outfitWindow:getChildById('primary').onCheckChange = onClotheCheckChange
@@ -150,6 +182,9 @@ function Outfit.create(creature, outfitList)
150 182
   local colorBoxPanel = outfitWindow:getChildById('colorBoxPanel')
151 183
   outfitCreatureBox:setCreature(outfitCreature)
152 184
 
185
+  local mountCreatureBox = outfitWindow:getChildById('mountCreatureBox')
186
+  mountCreatureBox:setCreature(mountCreature)
187
+
153 188
   for j=0,6 do
154 189
     for i=0,18 do
155 190
       local colorBox = g_ui.createWidget('ColorBox', colorBoxPanel)
@@ -163,6 +198,7 @@ function Outfit.create(creature, outfitList)
163 198
         colorBox:setChecked(true)
164 199
       end
165 200
       colorBox.onCheckChange = onColorCheckChange
201
+      table.insert(colorBoxes, colorBox)
166 202
     end
167 203
   end
168 204
 
@@ -173,8 +209,16 @@ function Outfit.create(creature, outfitList)
173 209
       break
174 210
     end
175 211
   end
212
+  currentMount = 1
213
+  for i=1,#mountList do
214
+    if mountList[i][1] == mount.type then
215
+      currentMount = i
216
+      break
217
+    end
218
+  end
176 219
 
177
-  update()
220
+  updateOutfit()
221
+  updateMount()
178 222
 end
179 223
 
180 224
 function Outfit.destroy()
@@ -182,29 +226,62 @@ function Outfit.destroy()
182 226
     outfitWindow:destroy()
183 227
     outfitWindow = nil
184 228
     outfitCreature = nil
229
+    mountCreature = nil
185 230
     currentColorBox = nil
186 231
     currentClotheButtonBox = nil
187 232
   end
188 233
 end
189 234
 
235
+function Outfit.randomize()
236
+  local outfitTemplate = {
237
+    outfitWindow:getChildById('head'),
238
+    outfitWindow:getChildById('primary'),
239
+    outfitWindow:getChildById('secondary'),
240
+    outfitWindow:getChildById('detail')
241
+  }
242
+  
243
+  for k, section in pairs(outfitTemplate) do
244
+    section:setChecked(true)
245
+    colorBoxes[math.random(1, #colorBoxes)]:setChecked(true)
246
+    section:setChecked(false)
247
+  end
248
+  outfitTemplate[1]:setChecked(true)
249
+end
250
+
190 251
 function Outfit.accept()
252
+  outfit.mount = mount.type
191 253
   g_game.changeOutfit(outfit)
192 254
   Outfit.destroy()
193 255
 end
194 256
 
195
-function Outfit.nextType()
257
+function Outfit.nextOutfitType()
196 258
   currentOutfit = currentOutfit + 1
197 259
   if currentOutfit > #outfits then
198 260
     currentOutfit = 1
199 261
   end
200
-  update()
262
+  updateOutfit()
201 263
 end
202 264
 
203
-function Outfit.previousType()
265
+function Outfit.previousOutfitType()
204 266
   currentOutfit = currentOutfit - 1
205 267
   if currentOutfit <= 0 then
206 268
     currentOutfit = #outfits
207 269
   end
208
-  update()
270
+  updateOutfit()
209 271
 end
210 272
 
273
+function Outfit.nextMountType()
274
+  currentMount = currentMount + 1
275
+  if currentMount > #mounts then
276
+    currentMount = 1
277
+  end
278
+  updateMount()
279
+end
280
+
281
+function Outfit.previousMountType()
282
+  currentMount = currentMount - 1
283
+  if currentMount <= 0 then
284
+    currentMount = #mounts
285
+  end
286
+  updateMount()
287
+end

+ 0
- 145
modules/game_outfit/outfit.otui View File

@@ -1,145 +0,0 @@
1
-Window
2
-  !text: tr('Select Outfit')
3
-  size: 550 280
4
-  padding: 0 0 0 0
5
-
6
-  anchors.horizontalCenter: parent.horizontalCenter
7
-  anchors.verticalCenter: parent.verticalCenter
8
-
9
-  @onEnter: Outfit.accept()
10
-  @onEscape: Outfit.destroy()
11
-
12
-  Label
13
-    id: outfitName
14
-    !text: tr('Outfit Name')
15
-    width: 100
16
-    anchors.top: parent.top
17
-    anchors.left: parent.left
18
-    margin-top: 34
19
-    margin-left: 20
20
-
21
-  Creature
22
-    id: outfitCreatureBox
23
-    anchors.top: outfitName.bottom
24
-    anchors.left: outfitName.left
25
-    margin-top: 5
26
-    padding: 4 4 4 4
27
-    fixed-creature-size: true
28
-
29
-  Panel
30
-    id: colorBoxPanel
31
-    anchors.top: parent.top
32
-    anchors.right: parent.right
33
-    margin-top: 54
34
-    margin-right: 20
35
-    width: 323
36
-    height: 119
37
-    layout:
38
-      type: grid
39
-      cell-size: 16 16
40
-      cell-spacing: 2
41
-      num-columns: 19
42
-      num-lines: 7
43
-
44
-  ButtonBox
45
-    id: head
46
-    !text: tr('Head')
47
-    anchors.top: outfitCreatureBox.top
48
-    anchors.left: outfitCreatureBox.right
49
-    margin-left: 10
50
-    checked: true
51
-    width: 90
52
-
53
-  ButtonBox
54
-    id: primary
55
-    !text: tr('Primary')
56
-    anchors.top: prev.bottom
57
-    anchors.left: prev.left
58
-    width: 90
59
-
60
-  ButtonBox
61
-    id: secondary
62
-    !text: tr('Secondary')
63
-    anchors.top: prev.bottom
64
-    anchors.left: prev.left
65
-    width: 90
66
-
67
-  ButtonBox
68
-    id: detail
69
-    !text: tr('Detail')
70
-    anchors.top: prev.bottom
71
-    anchors.left: prev.left
72
-    width: 90
73
-
74
-  Button
75
-    id: outfitNextButton
76
-    @onClick: Outfit.nextType()
77
-    text: >>
78
-    width: 32
79
-    margin-top: 4
80
-    anchors.top: outfitCreatureBox.bottom
81
-    anchors.right: outfitCreatureBox.right
82
-
83
-  Button
84
-    id: outfitPreviousButton
85
-    @onClick: Outfit.previousType()
86
-    text: <<
87
-    width: 32
88
-    margin-top: 4
89
-    anchors.top: outfitCreatureBox.bottom
90
-    anchors.left: outfitCreatureBox.left
91
-
92
-  CheckBox
93
-    id: addon1
94
-    !text: tr('Addon 1')
95
-    enabled: false
96
-    margin-top: 6
97
-    width: 100
98
-    anchors.top: prev.bottom
99
-    anchors.left: prev.left
100
-
101
-  CheckBox
102
-    id: addon2
103
-    !text: tr('Addon 2')
104
-    enabled: false
105
-    margin-top: 2
106
-    width: 100
107
-    anchors.top: prev.bottom
108
-    anchors.left: prev.left
109
-
110
-  CheckBox
111
-    id: addon3
112
-    !text: tr('Addon 3')
113
-    enabled: false
114
-    margin-top: 2
115
-    width: 100
116
-    anchors.top: prev.bottom
117
-    anchors.left: prev.left
118
-
119
-  HorizontalSeparator
120
-    anchors.left: parent.left
121
-    anchors.right: parent.right
122
-    anchors.bottom: next.top
123
-    margin-left: 16
124
-    margin-right: 16
125
-    margin-bottom: 10
126
-
127
-  Button
128
-    id: outfitOkButton
129
-    !text: tr('Ok')
130
-    width: 64
131
-    anchors.right: next.left
132
-    anchors.bottom: parent.bottom
133
-    margin-bottom: 16
134
-    margin-right: 16
135
-    @onClick: Outfit.accept()
136
-
137
-  Button
138
-    id: outfitCancelButton
139
-    !text: tr('Cancel')
140
-    width: 64
141
-    anchors.right: parent.right
142
-    anchors.bottom: parent.bottom
143
-    margin-bottom: 16
144
-    margin-right: 16
145
-    @onClick: Outfit.destroy()

+ 221
- 0
modules/game_outfit/outfitwindow.otui View File

@@ -0,0 +1,221 @@
1
+BrowseButton < Button
2
+  size: 20 29
3
+  icon-clip: 0 0 12 21
4
+
5
+  $hover !disabled:
6
+    icon-clip: 0 21 12 21
7
+
8
+  $pressed:
9
+    icon-clip: 0 22 12 21
10
+
11
+  $disabled:
12
+    color: #f0ad4d88
13
+
14
+NextOutfitButton < BrowseButton
15
+  icon-source: /images/arrow_right.png
16
+
17
+PrevOutfitButton < BrowseButton
18
+  icon-source: /images/arrow_left.png
19
+
20
+NextMountButton < BrowseButton
21
+  icon-source: /images/arrow_right.png
22
+
23
+PrevMountButton < BrowseButton
24
+  icon-source: /images/arrow_left.png
25
+
26
+Window
27
+  !text: tr('Select Outfit')
28
+  size: 338 375
29
+  padding: 0 0 0 0
30
+
31
+  anchors.horizontalCenter: parent.horizontalCenter
32
+  anchors.verticalCenter: parent.verticalCenter
33
+
34
+  @onEnter: Outfit.accept()
35
+  @onEscape: Outfit.destroy()
36
+
37
+  // Creature Boxes
38
+
39
+  Creature
40
+    id: outfitCreatureBox
41
+    anchors.top: parent.top
42
+    anchors.left: parent.left
43
+    margin-top: 48
44
+    margin-left: 40
45
+    padding: 4 4 4 4
46
+    fixed-creature-size: true
47
+
48
+  Label
49
+    id: outfitName
50
+    !text: tr('No Outfit')
51
+    width: 100
52
+    anchors.bottom: prev.top
53
+    anchors.left: prev.left
54
+    margin-bottom: 2
55
+
56
+  NextOutfitButton
57
+    id: outfitNextButton
58
+    anchors.left: outfitCreatureBox.right
59
+    anchors.verticalCenter: outfitCreatureBox.verticalCenter
60
+    margin-left: 3
61
+    enabled: true
62
+    @onClick: Outfit.nextOutfitType()
63
+
64
+  PrevOutfitButton
65
+    id: outfitPrevButton
66
+    anchors.right: outfitCreatureBox.left
67
+    anchors.verticalCenter: outfitCreatureBox.verticalCenter
68
+    margin-right: 3
69
+    enabled: true
70
+    @onClick: Outfit.previousOutfitType()
71
+
72
+  Creature
73
+    id: mountCreatureBox
74
+    anchors.top: parent.top
75
+    anchors.right: parent.right
76
+    margin-top: 48
77
+    margin-right: 40
78
+    padding: 4 4 4 4
79
+    fixed-creature-size: true
80
+
81
+  Label
82
+    id: mountName
83
+    !text: tr('No Mount')
84
+    width: 140
85
+    anchors.bottom: prev.top
86
+    anchors.left: prev.left
87
+    margin-bottom: 2
88
+
89
+  NextMountButton
90
+    id: mountNextButton
91
+    anchors.left: mountCreatureBox.right
92
+    anchors.verticalCenter: mountCreatureBox.verticalCenter
93
+    margin-left: 3
94
+    enabled: true
95
+    @onClick: Outfit.nextMountType()
96
+
97
+  PrevMountButton
98
+    id: mountPreviousButton
99
+    anchors.right: mountCreatureBox.left
100
+    anchors.verticalCenter: mountCreatureBox.verticalCenter
101
+    margin-right: 3
102
+    enabled: true
103
+    @onClick: Outfit.previousMountType()
104
+
105
+  // Addon Check Boxes
106
+
107
+  CheckBox
108
+    id: addon1
109
+    !text: tr('Addon 1')
110
+    width: 80
111
+    anchors.top: outfitCreatureBox.bottom
112
+    anchors.left: parent.left
113
+    margin-top: 6
114
+    margin-left: 18
115
+    enabled: false
116
+
117
+  CheckBox
118
+    id: addon2
119
+    !text: tr('Addon 2')
120
+    width: 80
121
+    anchors.top: prev.top
122
+    anchors.left: prev.right
123
+    enabled: false
124
+
125
+  CheckBox
126
+    id: addon3
127
+    !text: tr('Addon 3')
128
+    width: 80
129
+    anchors.top: prev.top
130
+    anchors.left: prev.right
131
+    enabled: false
132
+
133
+  // Body Selection Buttons
134
+
135
+  ButtonBox
136
+    id: head
137
+    !text: tr('Head')
138
+    anchors.top: addon1.bottom
139
+    anchors.left: addon1.left
140
+    margin-top: 5
141
+    checked: true
142
+    width: 76
143
+
144
+  ButtonBox
145
+    id: primary
146
+    !text: tr('Primary')
147
+    anchors.top: prev.top
148
+    anchors.left: prev.right
149
+    width: 76
150
+
151
+  ButtonBox
152
+    id: secondary
153
+    !text: tr('Secondary')
154
+    anchors.top: prev.top
155
+    anchors.left: prev.right
156
+    width: 76
157
+
158
+  ButtonBox
159
+    id: detail
160
+    !text: tr('Detail')
161
+    anchors.top: prev.top
162
+    anchors.left: prev.right
163
+    width: 76
164
+
165
+  // Color Panel
166
+
167
+  Panel
168
+    id: colorBoxPanel
169
+    anchors.top: head.bottom
170
+    anchors.left: head.left
171
+    margin-top: 3
172
+    margin-right: 20
173
+    width: 323
174
+    height: 119
175
+    layout:
176
+      type: grid
177
+      cell-size: 14 14
178
+      cell-spacing: 2
179
+      num-columns: 19
180
+      num-lines: 7
181
+
182
+  // Action Button Section
183
+
184
+  Button
185
+    id: randomizeButton
186
+    !text: tr('Randomize')
187
+    !tooltip: tr('Randomize characters outfit')
188
+    width: 75
189
+    anchors.left: prev.left
190
+    anchors.top: prev.bottom
191
+    margin-right: 16
192
+    @onClick: Outfit.randomize()
193
+
194
+  HorizontalSeparator
195
+    anchors.left: parent.left
196
+    anchors.right: parent.right
197
+    anchors.bottom: next.top
198
+    margin-left: 16
199
+    margin-right: 16
200
+    margin-bottom: 10
201
+    margin-top: 5
202
+
203
+  Button
204
+    id: outfitOkButton
205
+    !text: tr('Okay')
206
+    width: 64
207
+    anchors.right: next.left
208
+    anchors.bottom: parent.bottom
209
+    margin-bottom: 16
210
+    margin-right: 16
211
+    @onClick: Outfit.accept()
212
+
213
+  Button
214
+    id: outfitCancelButton
215
+    !text: tr('Cancel')
216
+    width: 64
217
+    anchors.right: parent.right
218
+    anchors.bottom: parent.bottom
219
+    margin-bottom: 16
220
+    margin-right: 16
221
+    @onClick: Outfit.destroy()

+ 2
- 2
modules/game_playerdeath/playerdeath.lua View File

@@ -23,7 +23,7 @@ end
23 23
 
24 24
 function PlayerDeath.reset()
25 25
   GameInterface.getMapPanel():recursiveGetChildById('centerAdvance'):hide()
26
-  if(deathWindow) then
26
+  if deathWindow then
27 27
     deathWindow:destroy()
28 28
     deathWindow = nil
29 29
   end
@@ -44,7 +44,7 @@ function PlayerDeath.displayDeadMessage()
44 44
 end
45 45
 
46 46
 function PlayerDeath.openWindow()
47
-  if(deathWindow) then
47
+  if deathWindow then
48 48
     return
49 49
   end
50 50
   deathWindow = g_ui.createWidget('DeathWindow', rootWidget)

+ 1
- 1
modules/game_playerdeath/playerdeath.otmod View File

@@ -1,7 +1,7 @@
1 1
 Module
2 2
   name: game_playerdeath
3 3
   description: Manage player deaths
4
-  author: edubart, BeniS
4
+  author: BeniS, edubart
5 5
   website: www.otclient.info
6 6
 
7 7
   dependencies:

+ 38
- 0
modules/game_playermount/playermount.lua View File

@@ -0,0 +1,38 @@
1
+PlayerMount = {}
2
+
3
+-- private variables
4
+
5
+-- private functions
6
+
7
+-- public functions
8
+function PlayerMount.init()
9
+  g_ui.importStyle('playermount.otui')
10
+  
11
+  connect(g_game, { onDeath = PlayerMount.dismount,
12
+                    onGameEnd = PlayerMount.dismount })
13
+  
14
+  g_keyboard.bindKeyDown('Ctrl+R', PlayerMount.toggleMount, gameRootPanel)
15
+end
16
+
17
+function PlayerMount.terminate()
18
+  disconnect(g_game, { onDeath = PlayerMount.dismount,
19
+                       onGameEnd = PlayerMount.dismount })
20
+
21
+  g_keyboard.unbindKeyDown('Ctrl+R', PlayerMount.toggleMount, gameRootPanel)
22
+  PlayerMount.reset()
23
+  
24
+  PlayerMount = nil
25
+end
26
+
27
+-- hooked events
28
+function PlayerMount.toggleMount()
29
+  if g_game.isMounted() then
30
+    g_game.mount(false)
31
+  else
32
+    g_game.mount(true)
33
+  end
34
+end
35
+
36
+function PlayerMount.dismount()
37
+  g_game.mount(false)
38
+end

+ 15
- 0
modules/game_playermount/playermount.otmod View File

@@ -0,0 +1,15 @@
1
+Module
2
+  name: game_playermount
3
+  description: Manage player mounts
4
+  author: BeniS
5
+  website: www.otclient.info
6
+
7
+  dependencies:
8
+    - client_entergame
9
+
10
+  @onLoad: |
11
+    dofile 'playermount'
12
+    PlayerMount.init()
13
+
14
+  @onUnload: |
15
+    PlayerMount.terminate()

+ 0
- 0
modules/game_playermount/playermount.otui View File


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

@@ -5,7 +5,7 @@ local textWindow
5 5
 
6 6
 -- private functions
7 7
 local function onGameEditText(id, itemId, maxLength, text, writter, time)
8
-  if(textWindow) then
8
+  if textWindow then
9 9
     return
10 10
   end
11 11
   textWindow = g_ui.createWidget('TextWindow', rootWidget)
@@ -61,7 +61,7 @@ local function onGameEditText(id, itemId, maxLength, text, writter, time)
61 61
 end
62 62
 
63 63
 local function onGameEditList(id, doorId, text)
64
-  if(textWindow) then
64
+  if textWindow then
65 65
     return
66 66
   end
67 67
   textWindow = g_ui.createWidget('TextWindow', rootWidget)
@@ -105,7 +105,7 @@ function TextWindow.terminate()
105 105
 end
106 106
 
107 107
 function TextWindow.destroy()
108
-  if(textWindow) then
108
+  if textWindow then
109 109
     textWindow:destroy()
110 110
     textWindow = nil
111 111
   end

+ 21
- 11
src/otclient/game.cpp View File

@@ -257,7 +257,7 @@ void Game::processCreatureTeleport(const CreaturePtr& creature)
257 257
     g_lua.callGlobalField("g_game", "onCreatureTeleport", creature);
258 258
 }
259 259
 
260
-void Game::processChannelList(const std::vector<std::tuple<int, std::string>>& channelList)
260
+void Game::processChannelList(const std::vector<std::tuple<int, std::string> >& channelList)
261 261
 {
262 262
     g_lua.callGlobalField("g_game", "onChannelList", channelList);
263 263
 }
@@ -324,21 +324,31 @@ void Game::processAutomapFlag(const Position& pos, int icon, const std::string&
324 324
     g_lua.callGlobalField("g_game", "onAutomapFlag", pos, icon, message);
325 325
 }
326 326
 
327
-void Game::processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int>>& outfitList)
327
+void Game::processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int> >& outfitList,
328
+                                   const std::vector<std::tuple<int, std::string> >& mountList)
328 329
 {
329
-    CreaturePtr virtualCreature = CreaturePtr(new Creature);
330
-    virtualCreature->setDirection(Otc::South);
331
-    virtualCreature->setOutfit(currentOufit);
330
+    // create virtual creature outfit
331
+    CreaturePtr virtualOutfitCreature = CreaturePtr(new Creature);
332
+    virtualOutfitCreature->setDirection(Otc::South);
333
+    virtualOutfitCreature->setOutfit(currentOufit);
332 334
 
333
-    g_lua.callGlobalField("g_game", "onOpenOutfitWindow", virtualCreature, outfitList);
335
+    // creature virtual mount outfit
336
+    CreaturePtr virtualMountCreature = CreaturePtr(new Creature);
337
+    virtualMountCreature->setDirection(Otc::South);
338
+
339
+    Outfit mountOutfit;
340
+    mountOutfit.setId(currentOufit.getMount());
341
+    virtualMountCreature->setOutfit(mountOutfit);
342
+
343
+    g_lua.callGlobalField("g_game", "onOpenOutfitWindow", virtualOutfitCreature, outfitList, virtualMountCreature, mountList);
334 344
 }
335 345
 
336
-void Game::processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int, int>>& items)
346
+void Game::processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int, int> >& items)
337 347
 {
338 348
     g_lua.callGlobalField("g_game", "onOpenNpcTrade", items);
339 349
 }
340 350
 
341
-void Game::processPlayerGoods(int money, const std::vector<std::tuple<ItemPtr, int>>& goods)
351
+void Game::processPlayerGoods(int money, const std::vector<std::tuple<ItemPtr, int> >& goods)
342 352
 {
343 353
     g_lua.callGlobalField("g_game", "onPlayerGoods", money, goods);
344 354
 }
@@ -373,12 +383,12 @@ void Game::processEditList(uint id, int doorId, const std::string& text)
373 383
     g_lua.callGlobalField("g_game", "onEditList", id, doorId, text);
374 384
 }
375 385
 
376
-void Game::processQuestLog(const std::vector<std::tuple<int, std::string, bool>>& questList)
386
+void Game::processQuestLog(const std::vector<std::tuple<int, std::string, bool> >& questList)
377 387
 {
378 388
     g_lua.callGlobalField("g_game", "onQuestLog", questList);
379 389
 }
380 390
 
381
-void Game::processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string>>& questMissions)
391
+void Game::processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions)
382 392
 {
383 393
     g_lua.callGlobalField("g_game", "onQuestLine", questId, questMissions);
384 394
 }
@@ -1044,7 +1054,7 @@ void Game::mount(bool mount)
1044 1054
 {
1045 1055
     if(!canPerformGameAction())
1046 1056
         return;
1047
-    m_protocolGame->sendMount(mount);
1057
+    m_protocolGame->sendMounted(mount);
1048 1058
 }
1049 1059
 
1050 1060
 bool Game::checkBotProtection()

+ 9
- 6
src/otclient/game.h View File

@@ -71,7 +71,7 @@ protected:
71 71
     void processContainerRemoveItem(int containerId, int slot);
72 72
 
73 73
     // channel related
74
-    void processChannelList(const std::vector<std::tuple<int, std::string>>& channelList);
74
+    void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList);
75 75
     void processOpenChannel(int channelId, const std::string& name);
76 76
     void processOpenPrivateChannel(const std::string& name);
77 77
     void processOpenOwnPrivateChannel(int channelId, const std::string& name);
@@ -92,11 +92,12 @@ protected:
92 92
     void processAutomapFlag(const Position& pos, int icon, const std::string& message);
93 93
 
94 94
     // outfit
95
-    void processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int>>& outfitList);
95
+    void processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int> >& outfitList,
96
+                                 const std::vector<std::tuple<int, std::string> >& mountList);
96 97
 
97 98
     // npc trade
98
-    void processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int, int>>& items);
99
-    void processPlayerGoods(int money, const std::vector<std::tuple<ItemPtr, int>>& goods);
99
+    void processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int, int> >& items);
100
+    void processPlayerGoods(int money, const std::vector<std::tuple<ItemPtr, int> >& goods);
100 101
     void processCloseNpcTrade();
101 102
 
102 103
     // player trade
@@ -109,8 +110,8 @@ protected:
109 110
     void processEditList(uint id, int doorId, const std::string& text);
110 111
 
111 112
     // questlog
112
-    void processQuestLog(const std::vector<std::tuple<int, std::string, bool>>& questList);
113
-    void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string>>& questMissions);
113
+    void processQuestLog(const std::vector<std::tuple<int, std::string, bool> >& questList);
114
+    void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
114 115
 
115 116
     friend class ProtocolGame;
116 117
     friend class Map;
@@ -245,6 +246,7 @@ public:
245 246
     bool isDead() { return m_dead; }
246 247
     bool isAttacking() { return !!m_attackingCreature; }
247 248
     bool isFollowing() { return !!m_followingCreature; }
249
+    bool isMounted() { return m_mounted; }
248 250
 
249 251
     ContainerPtr getContainer(int index) { return m_containers[index]; }
250 252
     std::map<int, ContainerPtr> getContainers() { return m_containers; }
@@ -276,6 +278,7 @@ private:
276 278
 
277 279
     bool m_denyBotCall;
278 280
     bool m_dead;
281
+    bool m_mounted;
279 282
     int m_serverBeat;
280 283
     Otc::FightModes m_fightMode;
281 284
     Otc::ChaseModes m_chaseMode;

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

@@ -177,6 +177,7 @@ void OTClient::registerLuaFunctions()
177 177
     g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
178 178
     g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
179 179
     g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
180
+    g_lua.bindSingletonFunction("g_game", "isMounted", &Game::isMounted, &g_game);
180 181
     g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
181 182
     g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
182 183
     g_lua.bindSingletonFunction("g_game", "getVips", &Game::getVips, &g_game);

+ 8
- 0
src/otclient/luavaluecasts.cpp View File

@@ -38,6 +38,10 @@ int push_luavalue(const Outfit& outfit)
38 38
     g_lua.setField("legs");
39 39
     g_lua.pushInteger(outfit.getFeet());
40 40
     g_lua.setField("feet");
41
+    if(g_game.getFeature(Otc::GamePlayerMounts)) {
42
+        g_lua.pushInteger(outfit.getMount());
43
+        g_lua.setField("mount");
44
+    }
41 45
     return 1;
42 46
 }
43 47
 
@@ -56,6 +60,10 @@ bool luavalue_cast(int index, Outfit& outfit)
56 60
         outfit.setLegs(g_lua.popInteger());
57 61
         g_lua.getField("feet", index);
58 62
         outfit.setFeet(g_lua.popInteger());
63
+        if(g_game.getFeature(Otc::GamePlayerMounts)) {
64
+            g_lua.getField("mount", index);
65
+            outfit.setMount(g_lua.popInteger());
66
+        }
59 67
         return true;
60 68
     }
61 69
     return false;

+ 1
- 0
src/otclient/luavaluecasts.h View File

@@ -25,6 +25,7 @@
25 25
 
26 26
 #include "global.h"
27 27
 #include <framework/luaengine/declarations.h>
28
+#include "game.h"
28 29
 #include "outfit.h"
29 30
 
30 31
 // outfit

+ 3
- 1
src/otclient/outfit.h View File

@@ -44,6 +44,7 @@ public:
44 44
     void setLegs(int legs) { m_legs = legs; m_legsColor = getColor(legs); }
45 45
     void setFeet(int feet) { m_feet = feet; m_feetColor = getColor(feet); }
46 46
     void setAddons(int addons) { m_addons = addons; }
47
+    void setMount(int mount) { m_mount = mount; }
47 48
     void setCategory(DatCategory category) { m_category = category; }
48 49
 
49 50
     void resetClothes();
@@ -54,6 +55,7 @@ public:
54 55
     int getLegs() const { return m_legs; }
55 56
     int getFeet() const { return m_feet; }
56 57
     int getAddons() const { return m_addons; }
58
+    int getMount() const { return m_mount; }
57 59
     DatCategory getCategory() const { return m_category; }
58 60
 
59 61
     Color getHeadColor() const { return m_headColor; }
@@ -63,7 +65,7 @@ public:
63 65
 
64 66
 private:
65 67
     DatCategory m_category;
66
-    int m_id, m_head, m_body, m_legs, m_feet, m_addons;
68
+    int m_id, m_head, m_body, m_legs, m_feet, m_addons, m_mount;
67 69
     Color m_headColor, m_bodyColor, m_legsColor, m_feetColor;
68 70
 };
69 71
 

+ 3
- 3
src/otclient/protocolcodes.h View File

@@ -57,7 +57,7 @@ namespace Proto {
57 57
         OsFlash = 3,
58 58
         OsOtclientLinux = 10,
59 59
         OsOtclientWindows = 11,
60
-        OsOtclientMac = 12,
60
+        OsOtclientMac = 12
61 61
     };
62 62
 
63 63
 #ifdef OSTYPE
@@ -177,7 +177,7 @@ namespace Proto {
177 177
         GameServerMarketEnter               = 246, // 944
178 178
         GameServerMarketLeave               = 247, // 944
179 179
         GameServerMarketDetail              = 248, // 944
180
-        GameServerMarketBrowse              = 249, // 944
180
+        GameServerMarketBrowse              = 249 // 944
181 181
     };
182 182
 
183 183
     enum ClientOpcodes {
@@ -267,7 +267,7 @@ namespace Proto {
267 267
         ClientMarketBrowse                  = 245, // 944
268 268
         ClientMarketCreate                  = 246, // 944
269 269
         ClientMarketCancel                  = 247, // 944
270
-        ClientMarketAccept                  = 248, // 944
270
+        ClientMarketAccept                  = 248 // 944
271 271
     };
272 272
 
273 273
     enum ServerSpeakType {

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

@@ -102,7 +102,7 @@ protected:
102 102
     void sendRefreshContainer();
103 103
     void sendRequestOutfit();
104 104
     void sendChangeOutfit(const Outfit& outfit);
105
-    void sendMount(bool mount);
105
+    void sendMountStatus(bool mount);
106 106
     void sendAddVip(const std::string& name);
107 107
     void sendRemoveVip(uint playerId);
108 108
     void sendBugReport(const std::string& comment);

+ 14
- 11
src/otclient/protocolgameparse.cpp View File

@@ -920,7 +920,6 @@ void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg)
920 920
     g_game.processAttackCancel();
921 921
 }
922 922
 
923
-
924 923
 void ProtocolGame::parseSpellDelay(const InputMessagePtr& msg)
925 924
 {
926 925
     msg->getU16(); // spell id
@@ -935,7 +934,6 @@ void ProtocolGame::parseSpellGroupDelay(const InputMessagePtr& msg)
935 934
     msg->getU8(); // unknown
936 935
 }
937 936
 
938
-
939 937
 void ProtocolGame::parseMultiUseDelay(const InputMessagePtr& msg)
940 938
 {
941 939
     //TODO
@@ -991,7 +989,7 @@ void ProtocolGame::parseCreatureSpeak(const InputMessagePtr& msg)
991 989
 void ProtocolGame::parseChannelList(const InputMessagePtr& msg)
992 990
 {
993 991
     int count = msg->getU8();
994
-    std::vector<std::tuple<int, std::string>> channelList;
992
+    std::vector<std::tuple<int, std::string> > channelList;
995 993
     for(int i = 0; i < count; i++) {
996 994
         int id = msg->getU16();
997 995
         std::string name = msg->getString();
@@ -1130,7 +1128,8 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
1130 1128
 {
1131 1129
     Outfit currentOutfit = getOutfit(msg);
1132 1130
 
1133
-    std::vector<std::tuple<int, std::string, int>> outfitList;
1131
+    std::vector<std::tuple<int, std::string, int> > outfitList;
1132
+    std::vector<std::tuple<int, std::string> > mountList;
1134 1133
     int outfitCount = msg->getU8();
1135 1134
     for(int i = 0; i < outfitCount; i++) {
1136 1135
         int outfitId = msg->getU16();
@@ -1142,13 +1141,15 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
1142 1141
 
1143 1142
     if(g_game.getFeature(Otc::GamePlayerMounts)) {
1144 1143
         int mountCount = msg->getU8();
1145
-        for(int i=0;i<mountCount;++i) {
1146
-            msg->getU16(); // mount type
1147
-            msg->getString(); // mount name
1144
+        for(int i = 0; i < mountCount; ++i) {
1145
+            int mountId = msg->getU16(); // mount type
1146
+            std::string mountName = msg->getString(); // mount name
1147
+            
1148
+            mountList.push_back(std::make_tuple(mountId, mountName));
1148 1149
         }
1149 1150
     }
1150 1151
 
1151
-    g_game.processOpenOutfitWindow(currentOutfit, outfitList);
1152
+    g_game.processOpenOutfitWindow(currentOutfit, outfitList, mountList);
1152 1153
 }
1153 1154
 
1154 1155
 void ProtocolGame::parseVipAdd(const InputMessagePtr& msg)
@@ -1188,7 +1189,7 @@ void ProtocolGame::parseAutomapFlag(const InputMessagePtr& msg)
1188 1189
 
1189 1190
 void ProtocolGame::parseQuestLog(const InputMessagePtr& msg)
1190 1191
 {
1191
-    std::vector<std::tuple<int, std::string, bool>> questList;
1192
+    std::vector<std::tuple<int, std::string, bool> > questList;
1192 1193
     int questsCount = msg->getU16();
1193 1194
     for(int i = 0; i < questsCount; i++) {
1194 1195
         int id = msg->getU16();
@@ -1344,8 +1345,10 @@ Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
1344 1345
         }
1345 1346
     }
1346 1347
 
1347
-    if(g_game.getFeature(Otc::GamePlayerMounts))
1348
-        msg->getU16(); // mount
1348
+    if(g_game.getFeature(Otc::GamePlayerMounts)) {
1349
+        int mount = msg->getU16(); // mount
1350
+        outfit.setMount(mount);
1351
+    }
1349 1352
 
1350 1353
     return outfit;
1351 1354
 }

+ 11
- 5
src/otclient/protocolgamesend.cpp View File

@@ -630,15 +630,21 @@ void ProtocolGame::sendChangeOutfit(const Outfit& outfit)
630 630
     msg->addU8(outfit.getLegs());
631 631
     msg->addU8(outfit.getFeet());
632 632
     msg->addU8(outfit.getAddons());
633
+    if(g_game.getFeature(Otc::GamePlayerMounts))
634
+        msg->addU16(outfit.getMount());
633 635
     send(msg);
634 636
 }
635 637
 
636
-void ProtocolGame::sendMount(bool mount)
638
+void ProtocolGame::sendMountStatus(bool mount)
637 639
 {
638
-    OutputMessagePtr msg(new OutputMessage);
639
-    msg->addU8(Proto::ClientMount);
640
-    msg->addU8(mount);
641
-    send(msg);
640
+    if(g_game.getFeature(Otc::GamePlayerMounts)) {
641
+        OutputMessagePtr msg(new OutputMessage);
642
+        msg->addU8(Proto::ClientMount);
643
+        msg->addU8(mount);
644
+        send(msg);
645
+    } else {
646
+        g_logger.error("ProtocolGame::sendMountStatus does not support the current protocol.");
647
+    }
642 648
 }
643 649
 
644 650
 void ProtocolGame::sendAddVip(const std::string& name)

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

@@ -120,7 +120,7 @@ TilePtr UIMap::getTile(const Point& mousePos)
120 120
 {
121 121
   /*
122 122
    * Known Issue: If you move a container widget into the map rect
123
-   * if you move an item onto itself it will allow this to execute
123
+   * and you move an item onto itself it will allow this to execute
124 124
    * still dropping the item on the ground.
125 125
    */
126 126
     if(!m_mapRect.contains(mousePos))

Loading…
Cancel
Save