diff --git a/.gitignore b/.gitignore index 5b6d4431..a633534b 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,8 @@ Thumbs.db .directory src/framework/graphics/dx/ modules/.project/modules.sublime-workspace +vc14/.vs/ +*.dll ################# ## Visual Studio diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e1ba3f5f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +from ubuntu:latest + +WORKDIR /app + +RUN apt-get update; apt-get install -y \ + build-essential \ + cmake \ + git-core \ + libboost-all-dev \ + libglew-dev \ + liblua5.1-0-dev \ + libopenal-dev \ + libphysfs-dev \ + libssl-dev \ + libvorbis-dev \ + zlib1g-dev + +RUN apt-get install -y \ + libncurses5-dev \ + mercurial; \ + hg clone -r stable-2.0 http://hg.icculus.org/icculus/physfs/; \ + cd physfs; \ + mkdir build && cd build && cmake .. && make && make install; \ + mv /usr/local/lib/libphysfs.a /usr/lib/x86_64-linux-gnu/. + +ADD . /app + +# Build application +RUN mkdir -p build && cd build && cmake .. && make -j$(grep -c ^process /proc/cpuinfo); + +CMD cd build; ./otclient diff --git a/README.md b/README.md index 6d9607f3..d36dcf65 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![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) \ +[![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) ### What is otclient? @@ -36,6 +36,15 @@ In short, if you need to compile OTClient, follow these tutorials: * [Compiling on Linux](https://github.com/edubart/otclient/wiki/Compiling-on-Linux) * [Compiling on OS X](https://github.com/edubart/otclient/wiki/Compiling-on-Mac-OS-X) +### Build and run with Docker + +To build and run the client: +``` +./build.sh +./run.sh +``` + +The build step should be run just when something on implementation changes. ### Need help? diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..35ce50fd --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker build -t edubart/otclient . diff --git a/init.lua b/init.lua index 64ddbf10..7386be0c 100644 --- a/init.lua +++ b/init.lua @@ -22,7 +22,7 @@ end g_resources.addSearchPath(g_resources.getWorkDir() .. "mods", true) -- setup directory for saving configurations -g_resources.setupUserWriteDir(g_app.getCompactName()) +g_resources.setupUserWriteDir(('%s/'):format(g_app.getCompactName())) -- search all packages g_resources.searchAndAddPackages('/', '.otpkg', true) @@ -52,4 +52,4 @@ local script = '/' .. g_app.getCompactName() .. 'rc.lua' if g_resources.fileExists(script) then dofile(script) -end \ No newline at end of file +end diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index a30f666a..c7e4001b 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -254,12 +254,21 @@ function CharacterList.create(characters, account, otui) end -- account - if account.premDays > 0 and account.premDays < 65535 then - accountStatusLabel:setText(tr("Premium Account (%s) days left", account.premDays)) - elseif account.premDays >= 65535 then - accountStatusLabel:setText(tr("Lifetime Premium Account")) - else - accountStatusLabel:setText(tr('Free Account')) + local status = '' + if account.status == AccountStatus.Frozen then + status = tr(' (Frozen)') + elseif account.status == AccountStatus.Suspended then + status = tr(' (Suspended)') + end + + if account.subStatus == SubscriptionStatus.Free then + accountStatusLabel:setText(('%s%s'):format(tr('Free Account'), status)) + elseif account.subStatus == SubscriptionStatus.Premium then + if account.premDays == 0 or account.premDays == 65535 then + accountStatusLabel:setText(('%s%s'):format(tr('Gratis Premium Account'), status)) + else + accountStatusLabel:setText(('%s%s'):format(tr('Premium Account (%s) days left', account.premDays), status)) + end end if account.premDays > 0 and account.premDays <= 7 then diff --git a/modules/corelib/keyboard.lua b/modules/corelib/keyboard.lua index 9485535d..000076f4 100644 --- a/modules/corelib/keyboard.lua +++ b/modules/corelib/keyboard.lua @@ -26,6 +26,11 @@ local function retranslateKeyComboDesc(keyComboDesc) if keyComboDesc == nil then error('Unable to translate key combo \'' .. keyComboDesc .. '\'') end + + if type(keyComboDesc) == 'number' then + keyComboDesc = tostring(keyComboDesc) + end + local keyCombo = {} for i,currentKeyDesc in ipairs(keyComboDesc:split('+')) do for keyCode, keyDesc in pairs(KeyCodeDescs) do diff --git a/modules/corelib/ui/tooltip.lua b/modules/corelib/ui/tooltip.lua index b1fecc15..d5c61159 100644 --- a/modules/corelib/ui/tooltip.lua +++ b/modules/corelib/ui/tooltip.lua @@ -10,13 +10,24 @@ local function moveToolTip(first) if not first and (not toolTipLabel:isVisible() or toolTipLabel:getOpacity() < 0.1) then return end local pos = g_window.getMousePosition() + local windowSize = g_window.getSize() + local labelSize = toolTipLabel:getSize() + + pos.x = pos.x + 1 pos.y = pos.y + 1 - local xdif = g_window.getSize().width - (pos.x + toolTipLabel:getWidth()) - if xdif < 10 then - pos.x = pos.x - toolTipLabel:getWidth() - 3 + + if windowSize.width - (pos.x + labelSize.width) < 10 then + pos.x = pos.x - labelSize.width - 3 else pos.x = pos.x + 10 end + + if windowSize.height - (pos.y + labelSize.height) < 10 then + pos.y = pos.y - labelSize.height - 3 + else + pos.y = pos.y + 10 + end + toolTipLabel:setPosition(pos) end diff --git a/modules/corelib/ui/uicombobox.lua b/modules/corelib/ui/uicombobox.lua index f6c94e9a..a9f54f4c 100644 --- a/modules/corelib/ui/uicombobox.lua +++ b/modules/corelib/ui/uicombobox.lua @@ -19,13 +19,14 @@ function UIComboBox:clearOptions() self:clearText() end -function UIComboBox:getOption(text) - if not self.options then return nil end +function UIComboBox:isOption(text) + if not self.options then return false end for i,v in ipairs(self.options) do if v.text == text then - return nil + return true end end + return false end function UIComboBox:setOption(text, dontSignal) diff --git a/modules/corelib/ui/uiminiwindow.lua b/modules/corelib/ui/uiminiwindow.lua index 1790e810..77c65c4a 100644 --- a/modules/corelib/ui/uiminiwindow.lua +++ b/modules/corelib/ui/uiminiwindow.lua @@ -3,6 +3,7 @@ UIMiniWindow = extends(UIWindow, "UIMiniWindow") function UIMiniWindow.create() local miniwindow = UIMiniWindow.internalCreate() + miniwindow.UIMiniWindowContainer = true return miniwindow end diff --git a/modules/corelib/ui/uiminiwindowcontainer.lua b/modules/corelib/ui/uiminiwindowcontainer.lua index a9584158..0bcae84e 100644 --- a/modules/corelib/ui/uiminiwindowcontainer.lua +++ b/modules/corelib/ui/uiminiwindowcontainer.lua @@ -83,7 +83,7 @@ function UIMiniWindowContainer:fitAll(noRemoveChild) end function UIMiniWindowContainer:onDrop(widget, mousePos) - if widget:getClassName() == 'UIMiniWindow' then + if widget.UIMiniWindowContainer then local oldParent = widget:getParent() if oldParent == self then return true diff --git a/modules/corelib/ui/uimovabletabbar.lua b/modules/corelib/ui/uimovabletabbar.lua index 1d398196..d4991cc0 100644 --- a/modules/corelib/ui/uimovabletabbar.lua +++ b/modules/corelib/ui/uimovabletabbar.lua @@ -385,6 +385,11 @@ function UIMoveableTabBar:selectTab(tab) tab:setOn(false) tab.blinking = false + if tab.blinkEvent then + removeEvent(tab.blinkEvent) + tab.blinkEvent = nil + end + local parent = tab:getParent() parent:focusChild(tab, MouseFocusReason) updateNavigation(self) diff --git a/modules/corelib/ui/uiscrollbar.lua b/modules/corelib/ui/uiscrollbar.lua index 387ba313..76c2d07c 100644 --- a/modules/corelib/ui/uiscrollbar.lua +++ b/modules/corelib/ui/uiscrollbar.lua @@ -126,8 +126,8 @@ end function UIScrollBar:onSetup() self.setupDone = true local sliderButton = self:getChildById('sliderButton') - g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:decrement() end, 300) - g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:increment() end, 300) + g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:onDecrement() end, 300) + g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:onIncrement() end, 300) g_mouse.bindPressMove(sliderButton, function(mousePos, mouseMoved) parseSliderPos(self, sliderButton, mousePos, mouseMoved) end) g_mouse.bindPress(sliderButton, function(mousePos, mouseButton) parseSliderPress(self, sliderButton, mousePos, mouseButton) end) @@ -158,6 +158,26 @@ function UIScrollBar:onStyleApply(styleName, styleNode) end end +function UIScrollBar:onDecrement() + if g_keyboard.isCtrlPressed() then + self:decrement(self.value) + elseif g_keyboard.isShiftPressed() then + self:decrement(10) + else + self:decrement() + end +end + +function UIScrollBar:onIncrement() + if g_keyboard.isCtrlPressed() then + self:increment(self.maximum) + elseif g_keyboard.isShiftPressed() then + self:increment(10) + else + self:increment() + end +end + function UIScrollBar:decrement(count) count = count or self.step self:setValue(self.value - count) @@ -264,4 +284,4 @@ function UIScrollBar:getStep() return self.step end function UIScrollBar:getOrientation() return self.orientation end function UIScrollBar:getShowValue() return self.showValue end function UIScrollBar:getSymbol() return self.symbol end -function UIScrollBar:getMouseScroll() return self.mouseScroll end \ No newline at end of file +function UIScrollBar:getMouseScroll() return self.mouseScroll end diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index 25c2e7a7..1a068286 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -52,6 +52,13 @@ SayModes = { [3] = { speakTypeDesc = 'yell', icon = '/images/game/console/yell' } } +ChannelEventFormats = { + [ChannelEvent.Join] = '%s joined the channel.', + [ChannelEvent.Leave] = '%s left the channel.', + [ChannelEvent.Invite] = '%s has been invited to the channel.', + [ChannelEvent.Exclude] = '%s has been removed from the channel.', +} + MAX_HISTORY = 500 MAX_LINES = 100 HELP_CHANNEL = 9 @@ -98,7 +105,8 @@ function init() onRuleViolationCancel = onRuleViolationCancel, onRuleViolationLock = onRuleViolationLock, onGameStart = online, - onGameEnd = offline + onGameEnd = offline, + onChannelEvent = onChannelEvent, }) consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel()) @@ -240,7 +248,8 @@ function terminate() onRuleViolationCancel = onRuleViolationCancel, onRuleViolationLock = onRuleViolationLock, onGameStart = online, - onGameEnd = offline + onGameEnd = offline, + onChannelEvent = onChannelEvent, }) if g_game.isOnline() then clear() end @@ -684,7 +693,7 @@ function addTabText(text, speaktype, tab, creatureName) child:setSelection(string.len(child:getText()), textPos) end end - + return true end @@ -857,14 +866,14 @@ function sendMessage(message, tab) message = chatCommandMessage channel = 0 end - + -- player red talk on channel chatCommandMessage = message:match("^%#[c|C] (.*)") if chatCommandMessage ~= nil then chatCommandSayMode = 'channelRed' message = chatCommandMessage end - + -- player broadcast chatCommandMessage = message:match("^%#[b|B] (.*)") if chatCommandMessage ~= nil then @@ -978,7 +987,7 @@ function navigateMessageHistory(step) end function applyMessagePrefixies(name, level, message) - if name then + if name and #name > 0 then if modules.client_options.getOption('showLevelsInConsole') and level > 0 then message = name .. ' [' .. level .. ']: ' .. message else @@ -1437,3 +1446,19 @@ function offline() end clear() end + +function onChannelEvent(channelId, name, type) + local fmt = ChannelEventFormats[type] + if not fmt then + print(('Unknown channel event type (%d).'):format(type)) + return + end + + local channel = channels[channelId] + if channel then + local tab = getTab(channel) + if tab then + addTabText(fmt:format(name), SpeakTypesSettings.channelOrange, tab) + end + end +end diff --git a/modules/game_skills/skills.lua b/modules/game_skills/skills.lua index 0fe7fee5..2f554aa4 100644 --- a/modules/game_skills/skills.lua +++ b/modules/game_skills/skills.lua @@ -120,7 +120,7 @@ function setSkillTooltip(id, value) widget:setTooltip(value) end -function setSkillPercent(id, percent, tooltip) +function setSkillPercent(id, percent, tooltip, color) local skill = skillsWindow:recursiveGetChildById(id) local widget = skill:getChildById('percent') if widget then @@ -129,6 +129,10 @@ function setSkillPercent(id, percent, tooltip) if tooltip then widget:setTooltip(tooltip) end + + if color then + widget:setBackgroundColor(color) + end end end @@ -333,10 +337,34 @@ function onStaminaChange(localPlayer, stamina) if minutes < 10 then minutes = '0' .. minutes end - local percent = math.floor(100 * stamina / (42 * 60)) -- max is 42 hours + local percent = math.floor(100 * stamina / (42 * 60)) -- max is 42 hours --TODO not in all client versions setSkillValue('stamina', hours .. ":" .. minutes) - setSkillPercent('stamina', percent, tr('You have %s percent', percent)) + + --TODO not all client versions have premium time + if stamina > 2400 and g_game.getClientVersion() >= 1038 and localPlayer:isPremium() then + local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' .. + tr("Now you will gain 50%% more experience") + setSkillPercent('stamina', percent, text, 'green') + elseif stamina > 2400 and g_game.getClientVersion() >= 1038 and not localPlayer:isPremium() then + local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' .. + tr("You will not gain 50%% more experience because you aren't premium player, now you receive only 1x experience points") + setSkillPercent('stamina', percent, text, '#89F013') + elseif stamina > 2400 and g_game.getClientVersion() < 1038 then + local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' .. + tr("If you are premium player, you will gain 50%% more experience") + setSkillPercent('stamina', percent, text, 'green') + elseif stamina <= 2400 and stamina > 840 then + setSkillPercent('stamina', percent, tr("You have %s hours and %s minutes left", hours, minutes), 'orange') + elseif stamina <= 840 and stamina > 0 then + local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" .. + tr("You gain only 50%% experience and you don't may gain loot from monsters") + setSkillPercent('stamina', percent, text, 'red') + elseif stamina == 0 then + local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" .. + tr("You don't may receive experience and loot from monsters") + setSkillPercent('stamina', percent, text, 'black') + end end function onOfflineTrainingChange(localPlayer, offlineTrainingTime) diff --git a/modules/game_textmessage/textmessage.otui b/modules/game_textmessage/textmessage.otui index 32cd2b62..85804f52 100644 --- a/modules/game_textmessage/textmessage.otui +++ b/modules/game_textmessage/textmessage.otui @@ -8,7 +8,7 @@ TextMessageLabel < UILabel Panel anchors.fill: gameMapPanel - anchors.bottom: gameBottomPanel.top + anchors.bottom: gameMapPanel.bottom focusable: false Panel diff --git a/modules/gamelib/const.lua b/modules/gamelib/const.lua index 415ab67a..29df1f1b 100644 --- a/modules/gamelib/const.lua +++ b/modules/gamelib/const.lua @@ -322,4 +322,22 @@ StoreState = { Timed = 3 } +AccountStatus = { + Ok = 0, + Frozen = 1, + Suspended = 2, +} + +SubscriptionStatus = { + Free = 0, + Premium = 1, +} + +ChannelEvent = { + Join = 0, + Leave = 1, + Invite = 2, + Exclude = 3, +} + -- @} diff --git a/modules/gamelib/protocollogin.lua b/modules/gamelib/protocollogin.lua index 9d871aa4..8a1cf636 100644 --- a/modules/gamelib/protocollogin.lua +++ b/modules/gamelib/protocollogin.lua @@ -240,7 +240,20 @@ function ProtocolLogin:parseCharacterList(msg) end local account = {} - account.premDays = msg:getU16() + if g_game.getProtocolVersion() > 1077 then + account.status = msg:getU8() + account.subStatus = msg:getU8() + + account.premDays = msg:getU32() + if account.premDays ~= 0 and account.premDays ~= 65535 then + account.premDays = math.floor((account.premDays - os.time()) / 86400) + end + else + account.status = AccountStatus.Ok + account.premDays = msg:getU16() + account.subStatus = account.premDays > 0 and SubscriptionStatus.Premium or SubscriptionStatus.Free + end + signalcall(self.onCharacterList, self, characters, account) end @@ -258,4 +271,4 @@ end function ProtocolLogin:onError(msg, code) local text = translateNetworkError(code, self:isConnecting(), msg) signalcall(self.onLoginError, self, text) -end \ No newline at end of file +end diff --git a/modules/gamelib/ui/uiminimap.lua b/modules/gamelib/ui/uiminimap.lua index 0ce93079..8f0eaa7c 100644 --- a/modules/gamelib/ui/uiminimap.lua +++ b/modules/gamelib/ui/uiminimap.lua @@ -72,11 +72,13 @@ end function UIMinimap:save() local settings = { flags={} } for _,flag in pairs(self.flags) do - table.insert(settings.flags, { - position = flag.pos, - icon = flag.icon, - description = flag.description, - }) + if not flag.temporary then + table.insert(settings.flags, { + position = flag.pos, + icon = flag.icon, + description = flag.description, + }) + end end settings.zoom = self:getZoom() g_settings.setNode('Minimap', settings) @@ -110,19 +112,25 @@ function UIMinimap:setCrossPosition(pos) end end -function UIMinimap:addFlag(pos, icon, description) +function UIMinimap:addFlag(pos, icon, description, temporary) if not pos or not icon then return end local flag = self:getFlag(pos, icon, description) if flag or not icon then return end + temporary = temporary or false flag = g_ui.createWidget('MinimapFlag') self:insertChild(1, flag) flag.pos = pos flag.description = description flag.icon = icon - flag:setIcon('/images/game/minimap/flag' .. icon) + flag.temporary = temporary + if type(tonumber(icon)) == 'number' then + flag:setIcon('/images/game/minimap/flag' .. icon) + else + flag:setIcon(resolvepath(icon, 1)) + end flag:setTooltip(description) flag.onMouseRelease = onFlagMouseRelease flag.onDestroy = function() table.removevalue(self.flags, flag) end diff --git a/run.sh b/run.sh new file mode 100755 index 00000000..288c22bd --- /dev/null +++ b/run.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +SE_enforcing=`getenforce` || true + +sudo setenforce Permissive || true + +# Enable any host to connect on X Org +xhost + + +docker run -ti --rm \ + -e DISPLAY \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + --device /dev/dri \ + edubart/otclient + +# Enable any host to connect on X Org +xhost - + +sudo setenforce $SE_enforcing || true diff --git a/src/client/animator.cpp b/src/client/animator.cpp index c81077ba..0382f291 100644 --- a/src/client/animator.cpp +++ b/src/client/animator.cpp @@ -123,6 +123,24 @@ int Animator::getPhase() return m_phase; } +int Animator::getPhaseAt(ticks_t time) +{ + int index = 0; + ticks_t total = 0; + + for(const auto &pair: m_phaseDurations) { + total += std::get<1>(pair); + + if (time < total) { + return index; + } + + ++index; + } + + return std::min(index, m_animationPhases - 1); +} + int Animator::getStartPhase() { if(m_startPhase > -1) @@ -157,7 +175,7 @@ int Animator::getLoopPhase() if(m_loopCount == 0) return 0; - + if(m_currentLoop < (m_loopCount - 1)) { m_currentLoop++; return 0; @@ -182,7 +200,7 @@ void Animator::calculateSynchronous() int totalDuration = 0; for(int i = 0; i < m_animationPhases; i++) totalDuration += getPhaseDuration(i); - + ticks_t ticks = g_clock.millis(); int elapsedTicks = (int)(ticks % totalDuration); int totalTime = 0; @@ -197,3 +215,13 @@ void Animator::calculateSynchronous() } m_lastPhaseTicks = ticks; } + +ticks_t Animator::getTotalDuration() +{ + ticks_t time = 0; + for (const auto &pair: m_phaseDurations) { + time += std::get<1>(pair); + } + + return time; +} diff --git a/src/client/animator.h b/src/client/animator.h index 93d0e1ef..2bf7f845 100644 --- a/src/client/animator.h +++ b/src/client/animator.h @@ -50,12 +50,15 @@ public: void setPhase(int phase); int getPhase(); + int getPhaseAt(ticks_t time); int getStartPhase(); int getAnimationPhases() { return m_animationPhases; } bool isAsync() { return m_async; } bool isComplete() { return m_isComplete; } + ticks_t getTotalDuration(); + void resetAnimation(); private: diff --git a/src/client/creature.cpp b/src/client/creature.cpp index 00d23d54..d29eac56 100644 --- a/src/client/creature.cpp +++ b/src/client/creature.cpp @@ -405,7 +405,7 @@ void Creature::updateJump() int nextT, i = 1; do { - nextT = stdext::round((-b + std::sqrt(std::max(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a)); + nextT = stdext::round((-b + std::sqrt(std::max(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a)); ++i; if(nextT < halfJumpDuration) diff --git a/src/client/effect.cpp b/src/client/effect.cpp index 0ea74a6a..60f254bd 100644 --- a/src/client/effect.cpp +++ b/src/client/effect.cpp @@ -22,6 +22,7 @@ #include "effect.h" #include "map.h" +#include "game.h" #include 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 return; int animationPhase = 0; - if(animate) - animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1); + if(animate) { + if(g_game.getFeature(Otc::GameEnhancedAnimations)) { + // This requires a separate getPhaseAt method as using getPhase would make all magic effects use the same phase regardless of their appearance time + animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer.ticksElapsed()); + } else { + // hack to fix some animation phases duration, currently there is no better solution + int ticks = EFFECT_TICKS_PER_FRAME; + if (m_id == 33) { + ticks <<= 2; + } + + animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / ticks), getAnimationPhases() - 1); + } + } int xPattern = offsetX % getNumPatternX(); if(xPattern < 0) @@ -47,15 +60,24 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int void Effect::onAppear() { m_animationTimer.restart(); - m_phaseDuration = EFFECT_TICKS_PER_FRAME; - // hack to fix some animation phases duration, currently there is no better solution - if(m_id == 33) - m_phaseDuration <<= 2; + int duration = 0; + if(g_game.getFeature(Otc::GameEnhancedAnimations)) { + duration = getThingType()->getAnimator()->getTotalDuration(); + } else { + duration = EFFECT_TICKS_PER_FRAME; + + // hack to fix some animation phases duration, currently there is no better solution + if(m_id == 33) { + duration <<= 2; + } + + duration *= getAnimationPhases(); + } // schedule removal auto self = asEffect(); - g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_phaseDuration * getAnimationPhases()); + g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, duration); } void Effect::setId(uint32 id) diff --git a/src/client/effect.h b/src/client/effect.h index 74e757cd..00a9cdfb 100644 --- a/src/client/effect.h +++ b/src/client/effect.h @@ -51,7 +51,6 @@ protected: private: Timer m_animationTimer; - uint m_phaseDuration; uint16 m_id; }; diff --git a/src/client/protocolgameparse.cpp b/src/client/protocolgameparse.cpp index 5bb49816..caf0fad5 100644 --- a/src/client/protocolgameparse.cpp +++ b/src/client/protocolgameparse.cpp @@ -1296,7 +1296,7 @@ void ProtocolGame::parsePremiumTrigger(const InputMessagePtr& msg) for(int i=0;igetU8()); } - + if(g_game.getClientVersion() <= 1096) { bool something = msg->getU8() == 1; } @@ -1903,9 +1903,11 @@ void ProtocolGame::parseQuestLine(const InputMessagePtr& msg) void ProtocolGame::parseChannelEvent(const InputMessagePtr& msg) { - msg->getU16(); // channel id - g_game.formatCreatureName(msg->getString()); // player name - msg->getU8(); // event type + uint16 channelId = msg->getU16(); + std::string name = g_game.formatCreatureName(msg->getString()); + uint8 type = msg->getU8(); + + g_lua.callGlobalField("g_game", "onChannelEvent", channelId, name, type); } void ProtocolGame::parseItemInfo(const InputMessagePtr& msg) diff --git a/src/framework/net/connection.h b/src/framework/net/connection.h index b9e56181..93a701ee 100644 --- a/src/framework/net/connection.h +++ b/src/framework/net/connection.h @@ -33,9 +33,10 @@ class Connection : public LuaObject typedef std::function ErrorCallback; typedef std::function RecvCallback; + static constexpr int32_t READ_TIMEOUT = 30; + static constexpr int32_t WRITE_TIMEOUT = 30; + enum { - READ_TIMEOUT = 30, - WRITE_TIMEOUT = 30, SEND_BUFFER_SIZE = 65536, RECV_BUFFER_SIZE = 65536 }; diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index cfa3e62d..10c29477 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -79,7 +79,7 @@ void Protocol::send(const OutputMessagePtr& outputMessage) if(m_checksumEnabled) outputMessage->writeChecksum(); - // wirte message size + // write message size outputMessage->writeMessageSize(); // send diff --git a/src/framework/platform/win32crashhandler.cpp b/src/framework/platform/win32crashhandler.cpp index 2fa9fbd1..5721d717 100644 --- a/src/framework/platform/win32crashhandler.cpp +++ b/src/framework/platform/win32crashhandler.cpp @@ -29,7 +29,19 @@ #include #include #include + +#ifdef _MSC_VER + +#pragma warning (push) +#pragma warning (disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared #include +#pragma warning (pop) + +#else + +#include + +#endif const char *getExceptionName(DWORD exceptionCode) { diff --git a/src/framework/sound/declarations.h b/src/framework/sound/declarations.h index 445643ba..ea99c3c2 100644 --- a/src/framework/sound/declarations.h +++ b/src/framework/sound/declarations.h @@ -27,8 +27,8 @@ #define AL_LIBTYPE_STATIC -#include -#include +#include +#include class SoundManager; class SoundSource; diff --git a/src/framework/stdext/compiler.h b/src/framework/stdext/compiler.h index 7a8f848f..3e27dc10 100644 --- a/src/framework/stdext/compiler.h +++ b/src/framework/stdext/compiler.h @@ -45,7 +45,16 @@ #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned #pragma warning(disable:4800) // 'A' : forcing value to bool 'true' or 'false' (performance warning) - #define BUILD_COMPILER "msvc12" + #if _MSC_VER == 1912 || _MSC_VER == 1911 || _MSC_VER == 1910 + #define BUILD_COMPILER "Visual Studio 2017" + #elif _MSC_VER == 1900 + #define BUILD_COMPILER "Visual Studio 2015" + #elif _MSC_VER == 1800 + #define BUILD_COMPILER "Visual Studio 2013" + #else + #define BUILD_COMPILER "Visual Studio" + #endif + #define __PRETTY_FUNCTION__ __FUNCDNAME__ #else #error "Compiler not supported." diff --git a/src/framework/stdext/demangle.cpp b/src/framework/stdext/demangle.cpp index 3866ed04..59def575 100644 --- a/src/framework/stdext/demangle.cpp +++ b/src/framework/stdext/demangle.cpp @@ -23,13 +23,21 @@ #include "demangle.h" #ifdef _MSC_VER + #include #include + +#pragma warning (push) +#pragma warning (disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared #include +#pragma warning (pop) + #else + #include #include #include + #endif namespace stdext { diff --git a/vc14/otclient.vcxproj b/vc14/otclient.vcxproj index 037f5073..37297092 100644 --- a/vc14/otclient.vcxproj +++ b/vc14/otclient.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,27 +22,28 @@ Win32Proj {17A8F78F-1FFB-4128-A3B3-59CC6C19D89A} otclient + 10.0.17134.0 Application true - v140 + v141 Application true - v140 + v141 Application false - v140 + v141 Application false - v140 + v141 @@ -74,8 +75,11 @@ $(VC_IncludePath);$(WindowsSDK_IncludePath);../src; + $(VC_SourcePath);$(ProjectDir)../src; + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);../src; - $(VC_IncludePath);$(WindowsSDK_IncludePath);../src; @@ -87,6 +91,7 @@ $(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) ProgramDatabase Disabled + AdvancedVectorExtensions MachineX86 @@ -97,6 +102,7 @@ $(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ProgramDatabase + AdvancedVectorExtensions true @@ -106,6 +112,10 @@ $(PREPROCESSOR_DEFS);%(PreprocessorDefinitions) MultiThreaded + AdvancedVectorExtensions + MaxSpeed + true + true MachineX86 @@ -120,6 +130,10 @@ MultiThreadedDLL ProgramDatabase Level4 + AdvancedVectorExtensions + MaxSpeed + true + true true