Browse Source

Merge branch 'master' into codetriage-badge

Konrad Kuśnierz 1 year ago
parent
commit
c1369a7c92
No account linked to committer's email address

+ 2
- 0
.gitignore View File

@@ -39,6 +39,8 @@ Thumbs.db
39 39
 .directory
40 40
 src/framework/graphics/dx/
41 41
 modules/.project/modules.sublime-workspace
42
+vc14/.vs/
43
+*.dll
42 44
 
43 45
 #################
44 46
 ## Visual Studio

+ 31
- 0
Dockerfile View File

@@ -0,0 +1,31 @@
1
+from ubuntu:latest
2
+
3
+WORKDIR /app
4
+
5
+RUN apt-get update; apt-get install -y \
6
+  build-essential \
7
+  cmake \
8
+  git-core \
9
+  libboost-all-dev \
10
+  libglew-dev \
11
+  liblua5.1-0-dev \
12
+  libopenal-dev \
13
+  libphysfs-dev \
14
+  libssl-dev \
15
+  libvorbis-dev \
16
+  zlib1g-dev
17
+
18
+RUN apt-get install -y \
19
+  libncurses5-dev \
20
+  mercurial; \
21
+  hg clone -r stable-2.0 http://hg.icculus.org/icculus/physfs/; \
22
+    cd physfs; \
23
+    mkdir build && cd build && cmake .. && make && make install; \
24
+    mv /usr/local/lib/libphysfs.a /usr/lib/x86_64-linux-gnu/.
25
+
26
+ADD . /app
27
+
28
+# Build application
29
+RUN mkdir -p build && cd build && cmake .. && make -j$(grep -c ^process /proc/cpuinfo); 
30
+
31
+CMD cd build; ./otclient 

+ 10
- 1
README.md View File

@@ -1,4 +1,4 @@
1
-[![Build Status](https://secure.travis-ci.org/edubart/otclient.svg?branch=master)](http://travis-ci.org/edubart/otclient) [![Join the chat at https://gitter.im/edubart/otclient](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Open Source Helpers](https://www.codetriage.com/edubart/otclient/badges/users.svg)](https://www.codetriage.com/edubart/otclient) \
1
+[![Build Status](https://secure.travis-ci.org/edubart/otclient.svg?branch=master)](http://travis-ci.org/edubart/otclient) [![Join the chat at https://gitter.im/edubart/otclient](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Open Source Helpers](https://www.codetriage.com/edubart/otclient/badges/users.svg)](https://www.codetriage.com/edubart/otclient)
2 2
 
3 3
 ### What is otclient?
4 4
 
@@ -36,6 +36,15 @@ In short, if you need to compile OTClient, follow these tutorials:
36 36
 * [Compiling on Linux](https://github.com/edubart/otclient/wiki/Compiling-on-Linux)
37 37
 * [Compiling on OS X](https://github.com/edubart/otclient/wiki/Compiling-on-Mac-OS-X)
38 38
 
39
+### Build and run with Docker
40
+
41
+To build and run the client:
42
+```
43
+./build.sh
44
+./run.sh
45
+```
46
+
47
+The build step should be run just when something on implementation changes.
39 48
 
40 49
 ### Need help?
41 50
 

+ 3
- 0
build.sh View File

@@ -0,0 +1,3 @@
1
+#!/usr/bin/env bash
2
+
3
+docker build -t edubart/otclient .

+ 2
- 2
init.lua View File

@@ -22,7 +22,7 @@ end
22 22
 g_resources.addSearchPath(g_resources.getWorkDir() .. "mods", true)
23 23
 
24 24
 -- setup directory for saving configurations
25
-g_resources.setupUserWriteDir(g_app.getCompactName())
25
+g_resources.setupUserWriteDir(('%s/'):format(g_app.getCompactName()))
26 26
 
27 27
 -- search all packages
28 28
 g_resources.searchAndAddPackages('/', '.otpkg', true)
@@ -52,4 +52,4 @@ local script = '/' .. g_app.getCompactName() .. 'rc.lua'
52 52
 
53 53
 if g_resources.fileExists(script) then
54 54
   dofile(script)
55
-end
55
+end

+ 15
- 6
modules/client_entergame/characterlist.lua View File

@@ -254,12 +254,21 @@ function CharacterList.create(characters, account, otui)
254 254
   end
255 255
 
256 256
   -- account
257
-  if account.premDays > 0 and account.premDays < 65535 then
258
-    accountStatusLabel:setText(tr("Premium Account (%s) days left", account.premDays))
259
-  elseif account.premDays >= 65535 then
260
-    accountStatusLabel:setText(tr("Lifetime Premium Account"))
261
-  else
262
-    accountStatusLabel:setText(tr('Free Account'))
257
+  local status = ''
258
+  if account.status == AccountStatus.Frozen then
259
+    status = tr(' (Frozen)')
260
+  elseif account.status == AccountStatus.Suspended then
261
+    status = tr(' (Suspended)')
262
+  end
263
+
264
+  if account.subStatus == SubscriptionStatus.Free then
265
+    accountStatusLabel:setText(('%s%s'):format(tr('Free Account'), status))
266
+  elseif account.subStatus == SubscriptionStatus.Premium then
267
+    if account.premDays == 0 or account.premDays == 65535 then
268
+      accountStatusLabel:setText(('%s%s'):format(tr('Gratis Premium Account'), status))
269
+    else
270
+      accountStatusLabel:setText(('%s%s'):format(tr('Premium Account (%s) days left', account.premDays), status))
271
+    end
263 272
   end
264 273
 
265 274
   if account.premDays > 0 and account.premDays <= 7 then

+ 5
- 0
modules/corelib/keyboard.lua View File

@@ -26,6 +26,11 @@ local function retranslateKeyComboDesc(keyComboDesc)
26 26
   if keyComboDesc == nil then
27 27
     error('Unable to translate key combo \'' .. keyComboDesc .. '\'')
28 28
   end
29
+
30
+  if type(keyComboDesc) == 'number' then
31
+    keyComboDesc = tostring(keyComboDesc)
32
+  end
33
+
29 34
   local keyCombo = {}
30 35
   for i,currentKeyDesc in ipairs(keyComboDesc:split('+')) do
31 36
     for keyCode, keyDesc in pairs(KeyCodeDescs) do

+ 14
- 3
modules/corelib/ui/tooltip.lua View File

@@ -10,13 +10,24 @@ local function moveToolTip(first)
10 10
   if not first and (not toolTipLabel:isVisible() or toolTipLabel:getOpacity() < 0.1) then return end
11 11
 
12 12
   local pos = g_window.getMousePosition()
13
+  local windowSize = g_window.getSize()
14
+  local labelSize = toolTipLabel:getSize()
15
+
16
+  pos.x = pos.x + 1
13 17
   pos.y = pos.y + 1
14
-  local xdif = g_window.getSize().width - (pos.x + toolTipLabel:getWidth())
15
-  if xdif < 10 then
16
-    pos.x = pos.x - toolTipLabel:getWidth() - 3
18
+
19
+  if windowSize.width - (pos.x + labelSize.width) < 10 then
20
+    pos.x = pos.x - labelSize.width - 3
17 21
   else
18 22
     pos.x = pos.x + 10
19 23
   end
24
+
25
+  if windowSize.height - (pos.y + labelSize.height) < 10 then
26
+    pos.y = pos.y - labelSize.height - 3
27
+  else
28
+    pos.y = pos.y + 10
29
+  end
30
+
20 31
   toolTipLabel:setPosition(pos)
21 32
 end
22 33
 

+ 4
- 3
modules/corelib/ui/uicombobox.lua View File

@@ -19,13 +19,14 @@ function UIComboBox:clearOptions()
19 19
   self:clearText()
20 20
 end
21 21
 
22
-function UIComboBox:getOption(text)
23
-  if not self.options then return nil end
22
+function UIComboBox:isOption(text)
23
+  if not self.options then return false end
24 24
   for i,v in ipairs(self.options) do
25 25
     if v.text == text then
26
-      return nil
26
+      return true
27 27
     end
28 28
   end
29
+  return false
29 30
 end
30 31
 
31 32
 function UIComboBox:setOption(text, dontSignal)

+ 1
- 0
modules/corelib/ui/uiminiwindow.lua View File

@@ -3,6 +3,7 @@ UIMiniWindow = extends(UIWindow, "UIMiniWindow")
3 3
 
4 4
 function UIMiniWindow.create()
5 5
   local miniwindow = UIMiniWindow.internalCreate()
6
+  miniwindow.UIMiniWindowContainer = true
6 7
   return miniwindow
7 8
 end
8 9
 

+ 1
- 1
modules/corelib/ui/uiminiwindowcontainer.lua View File

@@ -83,7 +83,7 @@ function UIMiniWindowContainer:fitAll(noRemoveChild)
83 83
 end
84 84
 
85 85
 function UIMiniWindowContainer:onDrop(widget, mousePos)
86
-  if widget:getClassName() == 'UIMiniWindow' then
86
+  if widget.UIMiniWindowContainer then
87 87
     local oldParent = widget:getParent()
88 88
     if oldParent == self then
89 89
       return true

+ 5
- 0
modules/corelib/ui/uimovabletabbar.lua View File

@@ -385,6 +385,11 @@ function UIMoveableTabBar:selectTab(tab)
385 385
   tab:setOn(false)
386 386
   tab.blinking = false
387 387
 
388
+  if tab.blinkEvent then
389
+    removeEvent(tab.blinkEvent)
390
+    tab.blinkEvent = nil
391
+  end
392
+
388 393
   local parent = tab:getParent()
389 394
   parent:focusChild(tab, MouseFocusReason)
390 395
   updateNavigation(self)

+ 23
- 3
modules/corelib/ui/uiscrollbar.lua View File

@@ -126,8 +126,8 @@ end
126 126
 function UIScrollBar:onSetup()
127 127
   self.setupDone = true
128 128
   local sliderButton = self:getChildById('sliderButton')
129
-  g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:decrement() end, 300)
130
-  g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:increment() end, 300)
129
+  g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:onDecrement() end, 300)
130
+  g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:onIncrement() end, 300)
131 131
   g_mouse.bindPressMove(sliderButton, function(mousePos, mouseMoved) parseSliderPos(self, sliderButton, mousePos, mouseMoved) end)
132 132
   g_mouse.bindPress(sliderButton, function(mousePos, mouseButton) parseSliderPress(self, sliderButton, mousePos, mouseButton) end)
133 133
 
@@ -158,6 +158,26 @@ function UIScrollBar:onStyleApply(styleName, styleNode)
158 158
   end
159 159
 end
160 160
 
161
+function UIScrollBar:onDecrement()
162
+  if g_keyboard.isCtrlPressed() then
163
+    self:decrement(self.value)
164
+  elseif g_keyboard.isShiftPressed() then
165
+    self:decrement(10)
166
+  else
167
+    self:decrement()
168
+  end
169
+end
170
+
171
+function UIScrollBar:onIncrement()
172
+  if g_keyboard.isCtrlPressed() then
173
+    self:increment(self.maximum)
174
+  elseif g_keyboard.isShiftPressed() then
175
+    self:increment(10)
176
+  else
177
+    self:increment()
178
+  end
179
+end
180
+
161 181
 function UIScrollBar:decrement(count)
162 182
   count = count or self.step
163 183
   self:setValue(self.value - count)
@@ -264,4 +284,4 @@ function UIScrollBar:getStep() return self.step end
264 284
 function UIScrollBar:getOrientation() return self.orientation end
265 285
 function UIScrollBar:getShowValue() return self.showValue end
266 286
 function UIScrollBar:getSymbol() return self.symbol end
267
-function UIScrollBar:getMouseScroll() return self.mouseScroll end
287
+function UIScrollBar:getMouseScroll() return self.mouseScroll end

+ 31
- 6
modules/game_console/console.lua View File

@@ -52,6 +52,13 @@ SayModes = {
52 52
   [3] = { speakTypeDesc = 'yell', icon = '/images/game/console/yell' }
53 53
 }
54 54
 
55
+ChannelEventFormats = {
56
+  [ChannelEvent.Join] = '%s joined the channel.',
57
+  [ChannelEvent.Leave] = '%s left the channel.',
58
+  [ChannelEvent.Invite] = '%s has been invited to the channel.',
59
+  [ChannelEvent.Exclude] = '%s has been removed from the channel.',
60
+}
61
+
55 62
 MAX_HISTORY = 500
56 63
 MAX_LINES = 100
57 64
 HELP_CHANNEL = 9
@@ -98,7 +105,8 @@ function init()
98 105
     onRuleViolationCancel = onRuleViolationCancel,
99 106
     onRuleViolationLock = onRuleViolationLock,
100 107
     onGameStart = online,
101
-    onGameEnd = offline
108
+    onGameEnd = offline,
109
+    onChannelEvent = onChannelEvent,
102 110
   })
103 111
 
104 112
   consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel())
@@ -240,7 +248,8 @@ function terminate()
240 248
     onRuleViolationCancel = onRuleViolationCancel,
241 249
     onRuleViolationLock = onRuleViolationLock,
242 250
     onGameStart = online,
243
-    onGameEnd = offline
251
+    onGameEnd = offline,
252
+    onChannelEvent = onChannelEvent,
244 253
   })
245 254
 
246 255
   if g_game.isOnline() then clear() end
@@ -684,7 +693,7 @@ function addTabText(text, speaktype, tab, creatureName)
684 693
         child:setSelection(string.len(child:getText()), textPos)
685 694
       end
686 695
     end
687
-    
696
+
688 697
     return true
689 698
   end
690 699
 
@@ -857,14 +866,14 @@ function sendMessage(message, tab)
857 866
     message = chatCommandMessage
858 867
     channel = 0
859 868
   end
860
-  
869
+
861 870
   -- player red talk on channel
862 871
   chatCommandMessage = message:match("^%#[c|C] (.*)")
863 872
   if chatCommandMessage ~= nil then
864 873
     chatCommandSayMode = 'channelRed'
865 874
     message = chatCommandMessage
866 875
   end
867
-  
876
+
868 877
   -- player broadcast
869 878
   chatCommandMessage = message:match("^%#[b|B] (.*)")
870 879
   if chatCommandMessage ~= nil then
@@ -978,7 +987,7 @@ function navigateMessageHistory(step)
978 987
 end
979 988
 
980 989
 function applyMessagePrefixies(name, level, message)
981
-  if name then
990
+  if name and #name > 0 then
982 991
     if modules.client_options.getOption('showLevelsInConsole') and level > 0 then
983 992
       message = name .. ' [' .. level .. ']: ' .. message
984 993
     else
@@ -1437,3 +1446,19 @@ function offline()
1437 1446
   end
1438 1447
   clear()
1439 1448
 end
1449
+
1450
+function onChannelEvent(channelId, name, type)
1451
+  local fmt = ChannelEventFormats[type]
1452
+  if not fmt then
1453
+    print(('Unknown channel event type (%d).'):format(type))
1454
+    return
1455
+  end
1456
+
1457
+  local channel = channels[channelId]
1458
+  if channel then
1459
+    local tab = getTab(channel)
1460
+    if tab then
1461
+      addTabText(fmt:format(name), SpeakTypesSettings.channelOrange, tab)
1462
+    end
1463
+  end
1464
+end

+ 31
- 3
modules/game_skills/skills.lua View File

@@ -120,7 +120,7 @@ function setSkillTooltip(id, value)
120 120
   widget:setTooltip(value)
121 121
 end
122 122
 
123
-function setSkillPercent(id, percent, tooltip)
123
+function setSkillPercent(id, percent, tooltip, color)
124 124
   local skill = skillsWindow:recursiveGetChildById(id)
125 125
   local widget = skill:getChildById('percent')
126 126
   if widget then
@@ -129,6 +129,10 @@ function setSkillPercent(id, percent, tooltip)
129 129
     if tooltip then
130 130
       widget:setTooltip(tooltip)
131 131
     end
132
+
133
+    if color then
134
+    	widget:setBackgroundColor(color)
135
+    end
132 136
   end
133 137
 end
134 138
 
@@ -333,10 +337,34 @@ function onStaminaChange(localPlayer, stamina)
333 337
   if minutes < 10 then
334 338
     minutes = '0' .. minutes
335 339
   end
336
-  local percent = math.floor(100 * stamina / (42 * 60)) -- max is 42 hours
340
+  local percent = math.floor(100 * stamina / (42 * 60)) -- max is 42 hours --TODO not in all client versions
337 341
 
338 342
   setSkillValue('stamina', hours .. ":" .. minutes)
339
-  setSkillPercent('stamina', percent, tr('You have %s percent', percent))
343
+
344
+  --TODO not all client versions have premium time
345
+  if stamina > 2400 and g_game.getClientVersion() >= 1038 and localPlayer:isPremium() then
346
+  	local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
347
+		tr("Now you will gain 50%% more experience")
348
+		setSkillPercent('stamina', percent, text, 'green')
349
+	elseif stamina > 2400 and g_game.getClientVersion() >= 1038 and not localPlayer:isPremium() then
350
+		local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
351
+		tr("You will not gain 50%% more experience because you aren't premium player, now you receive only 1x experience points")
352
+		setSkillPercent('stamina', percent, text, '#89F013')
353
+	elseif stamina > 2400 and g_game.getClientVersion() < 1038 then
354
+		local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
355
+		tr("If you are premium player, you will gain 50%% more experience")
356
+		setSkillPercent('stamina', percent, text, 'green')
357
+	elseif stamina <= 2400 and stamina > 840 then
358
+		setSkillPercent('stamina', percent, tr("You have %s hours and %s minutes left", hours, minutes), 'orange')
359
+	elseif stamina <= 840 and stamina > 0 then
360
+		local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" ..
361
+		tr("You gain only 50%% experience and you don't may gain loot from monsters")
362
+		setSkillPercent('stamina', percent, text, 'red')
363
+	elseif stamina == 0 then
364
+		local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" ..
365
+		tr("You don't may receive experience and loot from monsters")
366
+		setSkillPercent('stamina', percent, text, 'black')
367
+	end
340 368
 end
341 369
 
342 370
 function onOfflineTrainingChange(localPlayer, offlineTrainingTime)

+ 1
- 1
modules/game_textmessage/textmessage.otui View File

@@ -8,7 +8,7 @@ TextMessageLabel < UILabel
8 8
 
9 9
 Panel
10 10
   anchors.fill: gameMapPanel
11
-  anchors.bottom: gameBottomPanel.top
11
+  anchors.bottom: gameMapPanel.bottom
12 12
   focusable: false
13 13
 
14 14
   Panel

+ 18
- 0
modules/gamelib/const.lua View File

@@ -322,4 +322,22 @@ StoreState = {
322 322
   Timed = 3
323 323
 }
324 324
 
325
+AccountStatus = {
326
+  Ok = 0,
327
+  Frozen = 1,
328
+  Suspended = 2,
329
+}
330
+
331
+SubscriptionStatus = {
332
+  Free = 0,
333
+  Premium = 1,
334
+}
335
+
336
+ChannelEvent = {
337
+  Join = 0,
338
+  Leave = 1,
339
+  Invite = 2,
340
+  Exclude = 3,
341
+}
342
+
325 343
 -- @}

+ 15
- 2
modules/gamelib/protocollogin.lua View File

@@ -240,7 +240,20 @@ function ProtocolLogin:parseCharacterList(msg)
240 240
   end
241 241
 
242 242
   local account = {}
243
-  account.premDays = msg:getU16()
243
+  if g_game.getProtocolVersion() > 1077 then
244
+    account.status = msg:getU8()
245
+    account.subStatus = msg:getU8()
246
+
247
+    account.premDays = msg:getU32()
248
+    if account.premDays ~= 0 and account.premDays ~= 65535 then
249
+      account.premDays = math.floor((account.premDays - os.time()) / 86400)
250
+    end
251
+  else
252
+    account.status = AccountStatus.Ok
253
+    account.premDays = msg:getU16()
254
+    account.subStatus = account.premDays > 0 and SubscriptionStatus.Premium or SubscriptionStatus.Free
255
+  end
256
+
244 257
   signalcall(self.onCharacterList, self, characters, account)
245 258
 end
246 259
 
@@ -258,4 +271,4 @@ end
258 271
 function ProtocolLogin:onError(msg, code)
259 272
   local text = translateNetworkError(code, self:isConnecting(), msg)
260 273
   signalcall(self.onLoginError, self, text)
261
-end
274
+end

+ 15
- 7
modules/gamelib/ui/uiminimap.lua View File

@@ -72,11 +72,13 @@ end
72 72
 function UIMinimap:save()
73 73
   local settings = { flags={} }
74 74
   for _,flag in pairs(self.flags) do
75
-    table.insert(settings.flags, {
76
-      position = flag.pos,
77
-      icon = flag.icon,
78
-      description = flag.description,
79
-    })
75
+    if not flag.temporary then
76
+      table.insert(settings.flags, {
77
+        position = flag.pos,
78
+        icon = flag.icon,
79
+        description = flag.description,
80
+      })
81
+    end
80 82
   end
81 83
   settings.zoom = self:getZoom()
82 84
   g_settings.setNode('Minimap', settings)
@@ -110,19 +112,25 @@ function UIMinimap:setCrossPosition(pos)
110 112
   end
111 113
 end
112 114
 
113
-function UIMinimap:addFlag(pos, icon, description)
115
+function UIMinimap:addFlag(pos, icon, description, temporary)
114 116
   if not pos or not icon then return end
115 117
   local flag = self:getFlag(pos, icon, description)
116 118
   if flag or not icon then
117 119
     return
118 120
   end
121
+  temporary = temporary or false
119 122
 
120 123
   flag = g_ui.createWidget('MinimapFlag')
121 124
   self:insertChild(1, flag)
122 125
   flag.pos = pos
123 126
   flag.description = description
124 127
   flag.icon = icon
125
-  flag:setIcon('/images/game/minimap/flag' .. icon)
128
+  flag.temporary = temporary
129
+  if type(tonumber(icon)) == 'number' then
130
+    flag:setIcon('/images/game/minimap/flag' .. icon)
131
+  else
132
+    flag:setIcon(resolvepath(icon, 1))
133
+  end
126 134
   flag:setTooltip(description)
127 135
   flag.onMouseRelease = onFlagMouseRelease
128 136
   flag.onDestroy = function() table.removevalue(self.flags, flag) end

+ 19
- 0
run.sh View File

@@ -0,0 +1,19 @@
1
+#!/usr/bin/env bash
2
+
3
+SE_enforcing=`getenforce` || true
4
+
5
+sudo setenforce Permissive || true
6
+
7
+# Enable any host to connect on X Org
8
+xhost +
9
+
10
+docker run -ti --rm \
11
+       -e DISPLAY \
12
+       -v /tmp/.X11-unix:/tmp/.X11-unix \
13
+       --device /dev/dri \
14
+       edubart/otclient 
15
+
16
+# Enable any host to connect on X Org
17
+xhost -
18
+
19
+sudo setenforce $SE_enforcing || true

+ 30
- 2
src/client/animator.cpp View File

@@ -123,6 +123,24 @@ int Animator::getPhase()
123 123
     return m_phase;
124 124
 }
125 125
 
126
+int Animator::getPhaseAt(ticks_t time)
127
+{
128
+    int index = 0;
129
+    ticks_t total = 0;
130
+
131
+    for(const auto &pair: m_phaseDurations) {
132
+        total += std::get<1>(pair);
133
+
134
+        if (time < total) {
135
+            return index;
136
+        }
137
+
138
+        ++index;
139
+    }
140
+
141
+    return std::min<int>(index, m_animationPhases - 1);
142
+}
143
+
126 144
 int Animator::getStartPhase()
127 145
 {
128 146
     if(m_startPhase > -1)
@@ -157,7 +175,7 @@ int Animator::getLoopPhase()
157 175
 
158 176
     if(m_loopCount == 0)
159 177
         return 0;
160
-        
178
+
161 179
     if(m_currentLoop < (m_loopCount - 1)) {
162 180
         m_currentLoop++;
163 181
         return 0;
@@ -182,7 +200,7 @@ void Animator::calculateSynchronous()
182 200
     int totalDuration = 0;
183 201
     for(int i = 0; i < m_animationPhases; i++)
184 202
         totalDuration += getPhaseDuration(i);
185
-    
203
+
186 204
     ticks_t ticks = g_clock.millis();
187 205
     int elapsedTicks = (int)(ticks % totalDuration);
188 206
     int totalTime = 0;
@@ -197,3 +215,13 @@ void Animator::calculateSynchronous()
197 215
     }
198 216
     m_lastPhaseTicks = ticks;
199 217
 }
218
+
219
+ticks_t Animator::getTotalDuration()
220
+{
221
+    ticks_t time = 0;
222
+    for (const auto &pair: m_phaseDurations) {
223
+        time += std::get<1>(pair);
224
+    }
225
+
226
+    return time;
227
+}

+ 3
- 0
src/client/animator.h View File

@@ -50,12 +50,15 @@ public:
50 50
 
51 51
     void setPhase(int phase);
52 52
     int getPhase();
53
+    int getPhaseAt(ticks_t time);
53 54
 
54 55
     int getStartPhase();
55 56
     int getAnimationPhases() { return m_animationPhases; }
56 57
     bool isAsync() { return m_async; }
57 58
     bool isComplete() { return m_isComplete; }
58 59
 
60
+    ticks_t getTotalDuration();
61
+
59 62
     void resetAnimation();
60 63
 
61 64
 private:

+ 1
- 1
src/client/creature.cpp View File

@@ -405,7 +405,7 @@ void Creature::updateJump()
405 405
 
406 406
         int nextT, i = 1;
407 407
         do {
408
-            nextT = stdext::round((-b + std::sqrt(std::max<int>(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a));
408
+            nextT = stdext::round((-b + std::sqrt(std::max<double>(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a));
409 409
             ++i;
410 410
 
411 411
             if(nextT < halfJumpDuration)

+ 29
- 7
src/client/effect.cpp View File

@@ -22,6 +22,7 @@
22 22
 
23 23
 #include "effect.h"
24 24
 #include "map.h"
25
+#include "game.h"
25 26
 #include <framework/core/eventdispatcher.h>
26 27
 
27 28
 void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int offsetX, int offsetY, LightView *lightView)
@@ -30,8 +31,20 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int
30 31
         return;
31 32
 
32 33
     int animationPhase = 0;
33
-    if(animate)
34
-        animationPhase = std::min<int>((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1);
34
+    if(animate) {
35
+        if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
36
+            // This requires a separate getPhaseAt method as using getPhase would make all magic effects use the same phase regardless of their appearance time
37
+            animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer.ticksElapsed());
38
+        } else {
39
+            // hack to fix some animation phases duration, currently there is no better solution
40
+            int ticks = EFFECT_TICKS_PER_FRAME;
41
+            if (m_id == 33) {
42
+                ticks <<= 2;
43
+            }
44
+
45
+            animationPhase = std::min<int>((int)(m_animationTimer.ticksElapsed() / ticks), getAnimationPhases() - 1);
46
+        }
47
+    }
35 48
 
36 49
     int xPattern = offsetX % getNumPatternX();
37 50
     if(xPattern < 0)
@@ -47,15 +60,24 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int
47 60
 void Effect::onAppear()
48 61
 {
49 62
     m_animationTimer.restart();
50
-    m_phaseDuration = EFFECT_TICKS_PER_FRAME;
51 63
 
52
-    // hack to fix some animation phases duration, currently there is no better solution
53
-    if(m_id == 33)
54
-        m_phaseDuration <<= 2;
64
+    int duration = 0;
65
+    if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
66
+        duration = getThingType()->getAnimator()->getTotalDuration();
67
+    } else {
68
+        duration = EFFECT_TICKS_PER_FRAME;
69
+
70
+        // hack to fix some animation phases duration, currently there is no better solution
71
+        if(m_id == 33) {
72
+            duration <<= 2;
73
+        }
74
+
75
+        duration *= getAnimationPhases();
76
+    }
55 77
 
56 78
     // schedule removal
57 79
     auto self = asEffect();
58
-    g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_phaseDuration * getAnimationPhases());
80
+    g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, duration);
59 81
 }
60 82
 
61 83
 void Effect::setId(uint32 id)

+ 0
- 1
src/client/effect.h View File

@@ -51,7 +51,6 @@ protected:
51 51
 
52 52
 private:
53 53
     Timer m_animationTimer;
54
-    uint m_phaseDuration;
55 54
     uint16 m_id;
56 55
 };
57 56
 

+ 6
- 4
src/client/protocolgameparse.cpp View File

@@ -1296,7 +1296,7 @@ void ProtocolGame::parsePremiumTrigger(const InputMessagePtr& msg)
1296 1296
     for(int i=0;i<triggerCount;++i) {
1297 1297
         triggers.push_back(msg->getU8());
1298 1298
     }
1299
-    
1299
+
1300 1300
     if(g_game.getClientVersion() <= 1096) {
1301 1301
         bool something = msg->getU8() == 1;
1302 1302
     }
@@ -1903,9 +1903,11 @@ void ProtocolGame::parseQuestLine(const InputMessagePtr& msg)
1903 1903
 
1904 1904
 void ProtocolGame::parseChannelEvent(const InputMessagePtr& msg)
1905 1905
 {
1906
-    msg->getU16(); // channel id
1907
-    g_game.formatCreatureName(msg->getString()); // player name
1908
-    msg->getU8(); // event type
1906
+    uint16 channelId = msg->getU16();
1907
+    std::string name = g_game.formatCreatureName(msg->getString());
1908
+    uint8 type = msg->getU8();
1909
+
1910
+    g_lua.callGlobalField("g_game", "onChannelEvent", channelId, name, type);
1909 1911
 }
1910 1912
 
1911 1913
 void ProtocolGame::parseItemInfo(const InputMessagePtr& msg)

+ 3
- 2
src/framework/net/connection.h View File

@@ -33,9 +33,10 @@ class Connection : public LuaObject
33 33
     typedef std::function<void(const boost::system::error_code&)> ErrorCallback;
34 34
     typedef std::function<void(uint8*, uint16)> RecvCallback;
35 35
 
36
+    static constexpr int32_t READ_TIMEOUT = 30;
37
+    static constexpr int32_t WRITE_TIMEOUT = 30;
38
+
36 39
     enum {
37
-        READ_TIMEOUT = 30,
38
-        WRITE_TIMEOUT = 30,
39 40
         SEND_BUFFER_SIZE = 65536,
40 41
         RECV_BUFFER_SIZE = 65536
41 42
     };

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

@@ -79,7 +79,7 @@ void Protocol::send(const OutputMessagePtr& outputMessage)
79 79
     if(m_checksumEnabled)
80 80
         outputMessage->writeChecksum();
81 81
 
82
-    // wirte message size
82
+    // write message size
83 83
     outputMessage->writeMessageSize();
84 84
 
85 85
     // send

+ 12
- 0
src/framework/platform/win32crashhandler.cpp View File

@@ -29,8 +29,20 @@
29 29
 #include <winsock2.h>
30 30
 #include <windows.h>
31 31
 #include <process.h>
32
+
33
+#ifdef _MSC_VER
34
+
35
+#pragma warning (push)
36
+#pragma warning (disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared
37
+#include <imagehlp.h>
38
+#pragma warning (pop)
39
+
40
+#else
41
+
32 42
 #include <imagehlp.h>
33 43
 
44
+#endif
45
+
34 46
 const char *getExceptionName(DWORD exceptionCode)
35 47
 {
36 48
     switch (exceptionCode) {

+ 2
- 2
src/framework/sound/declarations.h View File

@@ -27,8 +27,8 @@
27 27
 
28 28
 #define AL_LIBTYPE_STATIC
29 29
 
30
-#include <al.h>
31
-#include <alc.h>
30
+#include <AL/al.h>
31
+#include <AL/alc.h>
32 32
 
33 33
 class SoundManager;
34 34
 class SoundSource;

+ 10
- 1
src/framework/stdext/compiler.h View File

@@ -45,7 +45,16 @@
45 45
     #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
46 46
     #pragma warning(disable:4800) // 'A' : forcing value to bool 'true' or 'false' (performance warning)
47 47
 
48
-    #define BUILD_COMPILER "msvc12"
48
+    #if _MSC_VER == 1912 || _MSC_VER == 1911 || _MSC_VER == 1910
49
+    #define BUILD_COMPILER "Visual Studio 2017"
50
+    #elif _MSC_VER == 1900
51
+    #define BUILD_COMPILER "Visual Studio 2015"
52
+    #elif _MSC_VER == 1800
53
+    #define BUILD_COMPILER "Visual Studio 2013"
54
+    #else
55
+    #define BUILD_COMPILER "Visual Studio"
56
+    #endif
57
+
49 58
     #define __PRETTY_FUNCTION__ __FUNCDNAME__
50 59
 #else
51 60
     #error "Compiler not supported."

+ 8
- 0
src/framework/stdext/demangle.cpp View File

@@ -23,13 +23,21 @@
23 23
 #include "demangle.h"
24 24
 
25 25
 #ifdef _MSC_VER
26
+
26 27
 #include <winsock2.h>
27 28
 #include <windows.h>
29
+
30
+#pragma warning (push)
31
+#pragma warning (disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared
28 32
 #include <dbghelp.h>
33
+#pragma warning (pop)
34
+
29 35
 #else
36
+
30 37
 #include <cxxabi.h>
31 38
 #include <cstring>
32 39
 #include <cstdlib>
40
+
33 41
 #endif
34 42
 
35 43
 namespace stdext {

+ 20
- 6
vc14/otclient.vcxproj View File

@@ -1,5 +1,5 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3
   <ItemGroup Label="ProjectConfigurations">
4 4
     <ProjectConfiguration Include="Debug|Win32">
5 5
       <Configuration>Debug</Configuration>
@@ -22,27 +22,28 @@
22 22
     <Keyword>Win32Proj</Keyword>
23 23
     <ProjectGuid>{17A8F78F-1FFB-4128-A3B3-59CC6C19D89A}</ProjectGuid>
24 24
     <RootNamespace>otclient</RootNamespace>
25
+    <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
25 26
   </PropertyGroup>
26 27
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
27 28
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
28 29
     <ConfigurationType>Application</ConfigurationType>
29 30
     <UseDebugLibraries>true</UseDebugLibraries>
30
-    <PlatformToolset>v140</PlatformToolset>
31
+    <PlatformToolset>v141</PlatformToolset>
31 32
   </PropertyGroup>
32 33
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
33 34
     <ConfigurationType>Application</ConfigurationType>
34 35
     <UseDebugLibraries>true</UseDebugLibraries>
35
-    <PlatformToolset>v140</PlatformToolset>
36
+    <PlatformToolset>v141</PlatformToolset>
36 37
   </PropertyGroup>
37 38
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
38 39
     <ConfigurationType>Application</ConfigurationType>
39 40
     <UseDebugLibraries>false</UseDebugLibraries>
40
-    <PlatformToolset>v140</PlatformToolset>
41
+    <PlatformToolset>v141</PlatformToolset>
41 42
   </PropertyGroup>
42 43
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
43 44
     <ConfigurationType>Application</ConfigurationType>
44 45
     <UseDebugLibraries>false</UseDebugLibraries>
45
-    <PlatformToolset>v140</PlatformToolset>
46
+    <PlatformToolset>v141</PlatformToolset>
46 47
   </PropertyGroup>
47 48
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
48 49
   <ImportGroup Label="ExtensionSettings">
@@ -74,8 +75,11 @@
74 75
   <PropertyGroup Label="UserMacros" />
75 76
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
76 77
     <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../src;</IncludePath>
78
+    <SourcePath>$(VC_SourcePath);$(ProjectDir)../src;</SourcePath>
79
+  </PropertyGroup>
80
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
81
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../src;</IncludePath>
77 82
   </PropertyGroup>
78
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
79 83
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
80 84
     <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../src;</IncludePath>
81 85
   </PropertyGroup>
@@ -87,6 +91,7 @@
87 91
       <PreprocessorDefinitions>$(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
88 92
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
89 93
       <Optimization>Disabled</Optimization>
94
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
90 95
     </ClCompile>
91 96
     <Link>
92 97
       <TargetMachine>MachineX86</TargetMachine>
@@ -97,6 +102,7 @@
97 102
     <ClCompile>
98 103
       <PreprocessorDefinitions>$(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
99 104
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
105
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
100 106
     </ClCompile>
101 107
     <Link>
102 108
       <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -106,6 +112,10 @@
106 112
     <ClCompile>
107 113
       <PreprocessorDefinitions>$(PREPROCESSOR_DEFS);%(PreprocessorDefinitions)</PreprocessorDefinitions>
108 114
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
115
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
116
+      <Optimization>MaxSpeed</Optimization>
117
+      <IntrinsicFunctions>true</IntrinsicFunctions>
118
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
109 119
     </ClCompile>
110 120
     <Link>
111 121
       <TargetMachine>MachineX86</TargetMachine>
@@ -120,6 +130,10 @@
120 130
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
121 131
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
122 132
       <WarningLevel>Level4</WarningLevel>
133
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
134
+      <Optimization>MaxSpeed</Optimization>
135
+      <IntrinsicFunctions>true</IntrinsicFunctions>
136
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
123 137
     </ClCompile>
124 138
     <Link>
125 139
       <GenerateDebugInformation>true</GenerateDebugInformation>

Loading…
Cancel
Save