From c0611bfe2aed0d73d341e72e154280ec9a83f8cf Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 18 Mar 2012 10:34:39 -0300 Subject: [PATCH] restore some game functionallity * i'm gradually restoring game functionality with the new modules design, though still a lot to do * you can reload all scripts and modules using Ctrl+R shortcut while playing (finally! this is the reason of all this rework) * a bunch of fixes, but new regression too :P * fix performance issue that could lead freezes in the client in older machines * completely new game module with new design * fix crashs in map render * remove uigame.cpp (now every game input is via lua) * enable DEBUG macro by default, with it you are able to view any possible lua leak while running --- modules/client/client.lua | 7 + modules/client/client.otmod | 1 + modules/client_background/background.lua | 5 +- modules/client_background/background.otui | 4 +- modules/client_entergame/characterlist.lua | 24 +- modules/client_terminal/terminal.lua | 8 +- modules/client_topmenu/topmenu.lua | 14 +- modules/core_lib/core_lib.otmod | 6 +- modules/core_lib/globals.lua | 2 - modules/core_lib/keyboard.lua | 2 +- modules/core_lib/mouse.lua | 2 +- modules/core_lib/widgets/uitabbar.lua | 3 +- modules/core_styles/core_styles.otmod | 4 +- modules/core_styles/icons/exit.png | Bin 932 -> 0 bytes modules/core_styles/styles/buttons.otui | 2 +- modules/core_styles/styles/comboboxes.otui | 2 +- .../{messagebox.otui => messageboxes.otui} | 0 modules/core_styles/styles/progressbars.otui | 1 - modules/core_styles/styles/separators.otui | 2 +- modules/core_styles/styles/tabbars.otui | 2 +- modules/core_styles/styles/windows.otui | 21 -- modules/game/const.lua | 24 ++ modules/game/creature.lua | 38 +-- modules/game/game.otmod | 25 +- modules/game/gameinterface.lua | 295 ++++++++++++++++++ modules/game/gameinterface.otui | 53 ++++ .../game/{images => icons}/emblem_blue.png | Bin .../game/{images => icons}/emblem_green.png | Bin modules/game/{images => icons}/emblem_red.png | Bin .../game/{images => icons}/shield_blue.png | Bin .../shield_blue_not_shared.png | Bin .../{images => icons}/shield_blue_shared.png | Bin .../{images => icons}/shield_blue_white.png | Bin .../game/{images => icons}/shield_yellow.png | Bin .../shield_yellow_not_shared.png | Bin .../shield_yellow_shared.png | Bin .../{images => icons}/shield_yellow_white.png | Bin .../game/{images => icons}/skull_black.png | Bin .../game/{images => icons}/skull_green.png | Bin .../game/{images => icons}/skull_orange.png | Bin modules/game/{images => icons}/skull_red.png | Bin .../game/{images => icons}/skull_white.png | Bin .../game/{images => icons}/skull_yellow.png | Bin .../images/bottompanel.png | Bin .../icons => game/images}/logout.png | Bin .../images/mappanel.png | Bin .../images/miniwindow.png | Bin .../images/sidepanel.png | Bin modules/game/styles/countwindow.otui | 41 +++ .../styles/creatures.otui | 0 .../{core_styles => game}/styles/items.otui | 0 modules/game/styles/miniwindow.otui | 20 ++ .../game_interface => game}/uiminiwindow.lua | 0 modules/game/widgets/uicountwindow.lua | 2 + modules/game/widgets/uigamemap.lua | 64 ++++ .../widgets}/uiitem.lua | 7 +- .../widgets}/uiminiwindowcontainer.lua | 0 .../game_console/channelswindow.otui | 2 +- modules/{old => }/game_console/console.lua | 185 ++++++----- modules/{old => }/game_console/console.otmod | 11 +- modules/{old => }/game_console/console.otui | 13 +- .../game_textmessage/textmessage.lua | 51 +-- .../game_textmessage/textmessage.otmod | 11 +- .../game_textmessage/textmessage.otui | 0 modules/{ => old}/game/game.lua | 0 modules/old/game/game.otmod | 17 + modules/{ => old}/game/game.otui | 0 modules/{ => old}/game/map.lua | 0 modules/{ => old}/game/movewindow.otui | 2 +- modules/{ => old}/game/player.lua | 0 modules/{ => old}/game/thing.lua | 0 modules/old/game_hotkeys/hotkeys_manager.lua | 2 +- modules/old/game_hotkeys/hotkeys_manager.otui | 2 +- modules/old/game_interface/gameinterface.otui | 8 +- modules/otclientrc.lua | 13 +- src/framework/CMakeLists.txt | 21 +- src/framework/application.cpp | 5 +- src/framework/luafunctions.cpp | 2 + src/framework/ui/uilineedit.cpp | 61 ++-- src/framework/ui/uilineedit.h | 3 + src/framework/ui/uimanager.cpp | 5 + src/framework/ui/uiwidget.cpp | 10 +- src/framework/ui/uiwidgettext.cpp | 8 + src/otclient/CMakeLists.txt | 1 + src/otclient/core/container.cpp | 23 ++ .../{ui/uigame.h => core/container.h} | 13 +- src/otclient/core/declarations.h | 2 + src/otclient/core/game.cpp | 1 - src/otclient/core/game.h | 2 + src/otclient/core/mapview.cpp | 8 +- src/otclient/core/mapview.h | 2 - src/otclient/core/player.cpp | 23 ++ src/otclient/core/player.h | 4 + src/otclient/core/thing.cpp | 8 + src/otclient/core/thing.h | 1 + src/otclient/luafunctions.cpp | 1 + src/otclient/ui/uigame.cpp | 117 ------- src/otclient/ui/uimap.cpp | 6 +- src/otclient/ui/uimap.h | 1 + 99 files changed, 938 insertions(+), 388 deletions(-) delete mode 100644 modules/core_styles/icons/exit.png rename modules/core_styles/styles/{messagebox.otui => messageboxes.otui} (100%) create mode 100644 modules/game/const.lua create mode 100644 modules/game/gameinterface.lua create mode 100644 modules/game/gameinterface.otui rename modules/game/{images => icons}/emblem_blue.png (100%) rename modules/game/{images => icons}/emblem_green.png (100%) rename modules/game/{images => icons}/emblem_red.png (100%) rename modules/game/{images => icons}/shield_blue.png (100%) rename modules/game/{images => icons}/shield_blue_not_shared.png (100%) rename modules/game/{images => icons}/shield_blue_shared.png (100%) rename modules/game/{images => icons}/shield_blue_white.png (100%) rename modules/game/{images => icons}/shield_yellow.png (100%) rename modules/game/{images => icons}/shield_yellow_not_shared.png (100%) rename modules/game/{images => icons}/shield_yellow_shared.png (100%) rename modules/game/{images => icons}/shield_yellow_white.png (100%) rename modules/game/{images => icons}/skull_black.png (100%) rename modules/game/{images => icons}/skull_green.png (100%) rename modules/game/{images => icons}/skull_orange.png (100%) rename modules/game/{images => icons}/skull_red.png (100%) rename modules/game/{images => icons}/skull_white.png (100%) rename modules/game/{images => icons}/skull_yellow.png (100%) rename modules/{old/game_interface => game}/images/bottompanel.png (100%) rename modules/{core_styles/icons => game/images}/logout.png (100%) rename modules/{old/game_interface => game}/images/mappanel.png (100%) rename modules/{old/game_interface => game}/images/miniwindow.png (100%) rename modules/{old/game_interface => game}/images/sidepanel.png (100%) create mode 100644 modules/game/styles/countwindow.otui rename modules/{core_styles => game}/styles/creatures.otui (100%) rename modules/{core_styles => game}/styles/items.otui (100%) create mode 100644 modules/game/styles/miniwindow.otui rename modules/{old/game_interface => game}/uiminiwindow.lua (100%) create mode 100644 modules/game/widgets/uicountwindow.lua create mode 100644 modules/game/widgets/uigamemap.lua rename modules/{old/game_interface => game/widgets}/uiitem.lua (88%) rename modules/{old/game_interface => game/widgets}/uiminiwindowcontainer.lua (100%) rename modules/{old => }/game_console/channelswindow.otui (96%) rename modules/{old => }/game_console/console.lua (85%) rename modules/{old => }/game_console/console.otmod (56%) rename modules/{old => }/game_console/console.otui (94%) rename modules/{old => }/game_textmessage/textmessage.lua (70%) rename modules/{old => }/game_textmessage/textmessage.otmod (57%) rename modules/{old => }/game_textmessage/textmessage.otui (100%) rename modules/{ => old}/game/game.lua (100%) create mode 100644 modules/old/game/game.otmod rename modules/{ => old}/game/game.otui (100%) rename modules/{ => old}/game/map.lua (100%) rename modules/{ => old}/game/movewindow.otui (96%) rename modules/{ => old}/game/player.lua (100%) rename modules/{ => old}/game/thing.lua (100%) create mode 100644 src/otclient/core/container.cpp rename src/otclient/{ui/uigame.h => core/container.h} (83%) create mode 100644 src/otclient/core/player.cpp delete mode 100644 src/otclient/ui/uigame.cpp diff --git a/modules/client/client.lua b/modules/client/client.lua index 36288807..ca7725a8 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -1,5 +1,12 @@ Client = {} +function Client.reloadScripts() + dofile 'otclientrc.lua' + reloadModules() + TextMessage.displayEventAdvance('All modules and scripts were reloaded.') + print('All modules and scripts were reloaded.') +end + function Client.init() g_window.setMinimumSize({ width = 600, height = 480 }) diff --git a/modules/client/client.otmod b/modules/client/client.otmod index 893587d0..a3a8ea28 100644 --- a/modules/client/client.otmod +++ b/modules/client/client.otmod @@ -14,6 +14,7 @@ Module - client_terminal - client_modulemanager - client_entergame + - game @onLoad: | dofile 'client' diff --git a/modules/client_background/background.lua b/modules/client_background/background.lua index 420418a9..1c41201b 100644 --- a/modules/client_background/background.lua +++ b/modules/client_background/background.lua @@ -11,7 +11,10 @@ function Background.init() local clientVersionLabel = background:getChildById('clientVersionLabel') clientVersionLabel:setText('OTClient ' .. g_app.getVersion() .. '\n' .. 'Built on ' .. g_app.getBuildDate()) - Effects.fadeIn(clientVersionLabel, 1500) + + if not g_game.isOnline() then + Effects.fadeIn(clientVersionLabel, 1500) + end connect(g_game, { onGameStart = Background.hide }) connect(g_game, { onGameEnd = Background.show }) diff --git a/modules/client_background/background.otui b/modules/client_background/background.otui index 17ecdee6..210d788e 100644 --- a/modules/client_background/background.otui +++ b/modules/client_background/background.otui @@ -11,12 +11,12 @@ Panel focusable: false UILabel - background-color: #00000099 id: clientVersionLabel + background-color: #00000099 anchors.right: parent.right anchors.bottom: parent.bottom text-offset: 4 2 height: 32 width: 120 color: #ffffff - font: verdana-11px-monochrome \ No newline at end of file + font: verdana-11px-monochrome diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index 33412f64..a5762102 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -52,7 +52,6 @@ local function tryLogin(charInfo, tries) Settings.set('lastUsedCharacter', charInfo.characterName) end - function onGameLoginError(message) CharacterList.destroyLoadBox() local errorBox = displayErrorBox("Login Error", "Login error: " .. message) @@ -67,6 +66,10 @@ end -- public functions function CharacterList.init() + charactersWindow = displayUI('characterlist.otui') + charactersWindow:hide() + characterList = charactersWindow:getChildById('characterList') + charactersWindow.onKeyPress = onCharactersWindowKeyPress connect(g_game, { onLoginError = onGameLoginError }) connect(g_game, { onConnectionError = onGameConnectionError }) connect(g_game, { onGameStart = CharacterList.destroyLoadBox }) @@ -74,11 +77,13 @@ function CharacterList.init() end function CharacterList.terminate() + disconnect(g_game, { onLoginError = onGameLoginError }) + disconnect(g_game, { onConnectionError = onGameConnectionError }) + disconnect(g_game, { onGameStart = CharacterList.destroyLoadBox }) + disconnect(g_game, { onGameEnd = CharacterList.show }) characterList = nil - if charactersWindow then - charactersWindow:destroy() - charactersWindow = nil - end + charactersWindow:destroy() + charactersWindow = nil if loadBox then g_game.cancelLogin() loadBox:destroy() @@ -88,14 +93,9 @@ function CharacterList.terminate() end function CharacterList.create(characters, premDays) - if charactersWindow then - charactersWindow:destroy() - end - - charactersWindow = displayUI('characterlist.otui') - characterList = charactersWindow:getChildById('characterList') + CharacterList.show() + characterList:destroyChildren() local accountStatusLabel = charactersWindow:getChildById('accountStatusLabel') - connect(charactersWindow, {onKeyPress = onCharactersWindowKeyPress }) local focusLabel for i,characterInfo in ipairs(characters) do diff --git a/modules/client_terminal/terminal.lua b/modules/client_terminal/terminal.lua index 9dccd91e..d41d1e56 100644 --- a/modules/client_terminal/terminal.lua +++ b/modules/client_terminal/terminal.lua @@ -184,12 +184,8 @@ function Terminal.executeCommand(command) -- detect and convert commands with simple syntax local realCommand - if commandEnv[command] then - if type(commandEnv[command]) == "function" then - realCommand = command .. '()' - else - realCommand = 'print(' .. command .. ')' - end + if string.sub(command, 1, 1) == '=' then + realCommand = 'print(' .. string.sub(command,2) .. ')' else realCommand = command end diff --git a/modules/client_topmenu/topmenu.lua b/modules/client_topmenu/topmenu.lua index 3ae4502f..5fa5576a 100644 --- a/modules/client_topmenu/topmenu.lua +++ b/modules/client_topmenu/topmenu.lua @@ -30,25 +30,27 @@ end -- public functions function TopMenu.init() + connect(g_game, { onGameStart = TopMenu.showGameButtons, + onGameEnd = TopMenu.hideGameButtons }) + topMenu = displayUI('topmenu.otui') + leftButtonsPanel = topMenu:getChildById('leftButtonsPanel') rightButtonsPanel = topMenu:getChildById('rightButtonsPanel') gameButtonsPanel = topMenu:getChildById('gameButtonsPanel') - - connect(g_game, { onGameStart = TopMenu.showGameButtons, - onGameEnd = TopMenu.hideGameButtons }) end function TopMenu.terminate() + disconnect(g_game, { onGameStart = TopMenu.showGameButtons, + onGameEnd = TopMenu.hideGameButtons }) + leftButtonsPanel = nil rightButtonsPanel = nil gameButtonsPanel = nil + topMenu:destroy() topMenu = nil - disconnect(g_game, { onGameStart = TopMenu.showGameButtons, - onGameEnd = TopMenu.hideGameButtons }) - TopMenu = nil end diff --git a/modules/core_lib/core_lib.otmod b/modules/core_lib/core_lib.otmod index 9992a42a..c572c817 100644 --- a/modules/core_lib/core_lib.otmod +++ b/modules/core_lib/core_lib.otmod @@ -10,10 +10,12 @@ Module dofile 'ext/table' dofile 'ext/string' dofile 'ext/os' + dofile 'math/point' dofile 'math/size' dofile 'math/color' dofile 'math/rect' + dofile 'const' dofile 'util' dofile 'globals' @@ -35,8 +37,4 @@ Module dofile 'widgets/uitabbar' dofile 'widgets/uipopupmenu' dofile 'widgets/uiwindow' - --dofile 'widgets/uiminiwindow' - --dofile 'widgets/uiminiwindowcontainer' dofile 'widgets/uimessagebox' - - diff --git a/modules/core_lib/globals.lua b/modules/core_lib/globals.lua index 2e98cfac..592fe6ed 100644 --- a/modules/core_lib/globals.lua +++ b/modules/core_lib/globals.lua @@ -68,5 +68,3 @@ end function reloadModules() g_modules.reloadModules() end - - diff --git a/modules/core_lib/keyboard.lua b/modules/core_lib/keyboard.lua index ded616c7..5434e1e7 100644 --- a/modules/core_lib/keyboard.lua +++ b/modules/core_lib/keyboard.lua @@ -70,8 +70,8 @@ local function onWidgetKeyDown(widget, keyCode, keyboardModifiers) end local function onWidgetKeyPress(widget, keyCode, keyboardModifiers, autoRepeatTicks) - local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers) if keyCode == KeyUnknown then return false end + local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers) local comboConf = widget.boundKeyPressCombos[keyComboDesc] if comboConf and (autoRepeatTicks >= comboConf.autoRepeatDelay or autoRepeatTicks == 0) and comboConf.callback then comboConf.callback() diff --git a/modules/core_lib/mouse.lua b/modules/core_lib/mouse.lua index 57a3123d..8d5bda90 100644 --- a/modules/core_lib/mouse.lua +++ b/modules/core_lib/mouse.lua @@ -1,7 +1,7 @@ Mouse = {} function Mouse.setTargetCursor() - g_window.setMouseCursor('/core_styles/icons/targetcursor.png', {x=9,y=9}) + g_window.setMouseCursor('/core_styles/cursors/targetcursor.png', {x=9,y=9}) end function Mouse.restoreCursor() diff --git a/modules/core_lib/widgets/uitabbar.lua b/modules/core_lib/widgets/uitabbar.lua index 243a1ada..4f1709ab 100644 --- a/modules/core_lib/widgets/uitabbar.lua +++ b/modules/core_lib/widgets/uitabbar.lua @@ -36,7 +36,8 @@ function UITabBar:addTab(text, panel) tab.tabBar = self tab:setText(text) tab:setWidth(tab:getTextSize().width + tab:getPaddingLeft() + tab:getPaddingRight()) - connect(tab, { onClick = onTabClick }) + tab.onClick = onTabClick + tab.onDestroy = function() tab.tabPanel:destroy() end table.insert(self.tabs, tab) if #self.tabs == 1 then diff --git a/modules/core_styles/core_styles.otmod b/modules/core_styles/core_styles.otmod index 63c16445..b27e4d91 100644 --- a/modules/core_styles/core_styles.otmod +++ b/modules/core_styles/core_styles.otmod @@ -23,9 +23,7 @@ Module importStyle 'styles/tabbars.otui' importStyle 'styles/windows.otui' importStyle 'styles/listboxes.otui' - importStyle 'styles/items.otui' - importStyle 'styles/creatures.otui' importStyle 'styles/popupmenus.otui' importStyle 'styles/comboboxes.otui' importStyle 'styles/spinboxes.otui' - importStyle 'styles/messagebox.otui' + importStyle 'styles/messageboxes.otui' diff --git a/modules/core_styles/icons/exit.png b/modules/core_styles/icons/exit.png deleted file mode 100644 index 7af7112d57845518e609f89075e3fa66287e2dac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 932 zcmV;V16%xwP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipq) z1{fKcyj&9i0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~0008} zNklL`m$Oh8W4q9Wg-I!*E;=yo-e4Oh1nWe{z8|JZ-pjl9b`fi(UG%`=3*Q3=zMSt7 z$@S|@?%gA~dlvxv1_8{g`R2aTY_fLwGJiaNjQVqTm)Ysl*fVGN8{!oKB>#mKf?<;I z?E70dpWeTZJ$n}8y1aMws(2X$OK+b)Up#s60Il_F{#&!Y&u^QX$if(kEMvXX5r>C| z-x#fb+K-}ez0(nSnv$m}>z$5>q9`Et{s@ zy}iAU0Hn3s)mp7(tsNl5Cj>!Oj>pUZS-Og1G~)Kfi#7;?zLc_UwH{P_zvURSBemYC zcwWoSW&_ulb`S*pJC`n5Ycw-JY*szwJEu@fOH`^ppWnVChQt2xVq$iRQa6k-I8w%r z>u!W$xc|e)AKI6PDOtbIBu-GJy#hco98zc(uU12sC0UlCr6dePvR{5? zG?i%O&ri_G!3uB{T#0iL?e2z!R@=3udR<8yOKhw>uWs_`_U^-n;TN$Lz9&#h&JBzb zAO)S=iv1`GUBA*jy0X%89XY7E{sxZPa2;n*Z!}u2?{)X1DEu-hh2silfYPo+NQisA zx>RawF$j*CvK(mTwpW|Y{wlB^MQ!PMUDxxDnS8Pp_j+yRig}Di&Y!k%@?>V84R0z( zU`j5mG@JeSGhtl?$8XvG!NEb>ch%NZh?|YIwM;nko`~<>e~U@)2}h*n%8Oh8bs*bo zd-jMAj)c5`6F>f=-3Y68T3ICOy+HY^Con~c7-!r#wQOrXY1Ie6vOuMrw@MoroLjb& zoOC>ea$%9tw2E*X)YIr!vfrOF%k$S2{yzvQ5mI8xlD`0*>3JESv@9wB0000 1 then + widget.parsed = true + local moveWindow = createWidget('CountWindow', rootWidget) + local spinbox = moveWindow:getChildById('spinbox') + spinbox:setMaximum(count) + spinbox:setMinimum(1) + spinbox:setCurrentIndex(count) + + local okButton = moveWindow:getChildById('buttonOk') + okButton.onClick = function() + g_game.move(widget.currentDragThing, tile:getPosition(), spinbox:getCurrentIndex()) + okButton:getParent():destroy() + widget.currentDragThing = nil + end + moveWindow.onEnter = okButton.onClick + else + g_game.move(widget.currentDragThing, tile:getPosition(), 1) + end + + return true +end + +function UIGameMap:onMouseRelease(mousePosition, mouseButton) + local tile = self:getTile(mousePosition) + if tile and GameInterface.processMouseAction(mousePosition, mouseButton, nil, tile:getTopLookThing(), tile:getTopUseThing(), tile:getTopCreature(), tile:getTopMultiUseThing()) then return true end + return false +end diff --git a/modules/old/game_interface/uiitem.lua b/modules/game/widgets/uiitem.lua similarity index 88% rename from modules/old/game_interface/uiitem.lua rename to modules/game/widgets/uiitem.lua index 42ee50a3..481f1d43 100644 --- a/modules/old/game_interface/uiitem.lua +++ b/modules/game/widgets/uiitem.lua @@ -33,14 +33,17 @@ function UIItem:onDrop(widget, mousePos) local count = widget.currentDragThing:getCount() if widget.currentDragThing:isStackable() and count > 1 then widget.parsed = true - local moveWindow = displayUI('/game/movewindow.otui') + local countWindow = createWidget('CountWindow', rootWidget) local spinbox = moveWindow:getChildById('spinbox') spinbox:setMaximum(count) spinbox:setMinimum(1) spinbox:setCurrentIndex(count) local okButton = moveWindow:getChildById('buttonOk') - okButton.onClick = function() g_game.move(widget.currentDragThing, pos, spinbox:getCurrentIndex()) okButton:getParent():destroy() widget.currentDragThing = nil end + okButton.onClick = function() + g_game.move(widget.currentDragThing, pos, spinbox:getCurrentIndex()) okButton:getParent():destroy() + widget.currentDragThing = nil + end moveWindow.onEnter = okButton.onClick else g_game.move(widget.currentDragThing, pos, 1) diff --git a/modules/old/game_interface/uiminiwindowcontainer.lua b/modules/game/widgets/uiminiwindowcontainer.lua similarity index 100% rename from modules/old/game_interface/uiminiwindowcontainer.lua rename to modules/game/widgets/uiminiwindowcontainer.lua diff --git a/modules/old/game_console/channelswindow.otui b/modules/game_console/channelswindow.otui similarity index 96% rename from modules/old/game_console/channelswindow.otui rename to modules/game_console/channelswindow.otui index daeebade..e118f42a 100644 --- a/modules/old/game_console/channelswindow.otui +++ b/modules/game_console/channelswindow.otui @@ -53,4 +53,4 @@ MainWindow width: 64 anchors.right: parent.right anchors.bottom: parent.bottom - @onClick: self:getParent():destroy() \ No newline at end of file + @onClick: self:getParent():destroy() diff --git a/modules/old/game_console/console.lua b/modules/game_console/console.lua similarity index 85% rename from modules/old/game_console/console.lua rename to modules/game_console/console.lua index 9a04eb19..eeaadd25 100644 --- a/modules/old/game_console/console.lua +++ b/modules/game_console/console.lua @@ -76,9 +76,83 @@ function applyMessagePrefixies(name, level, message) return message end + +-- hooked events +local function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos) + speaktype = SpeakTypes[speaktype] + if speaktype.hideInConsole then return end + + message = applyMessagePrefixies(name, level, message) + + if speaktype.private then + Console.addPrivateText(message, speaktype, name, false) + else + local channel = channels[channelId] + + if channel then + Console.addText(message, speaktype, channel) + else + -- server sent a message on a channel that we are not aware of, must leave it + g_game.leaveChannel(channelId) + end + end +end + +local function onOpenChannel(channelId, channelName) + Console.addChannel(channelName, channelId) +end + +local function onOpenPrivateChannel(receiver) + local privateTab = Console.getTab(receiver) + if privateTab == nil then + Console.addTab(receiver, true) + end +end + +local function doChannelListSubmit(channelsWindow) + local channelListPanel = channelsWindow:getChildById('channelList') + local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText() + if openPrivateChannelWith ~= '' then + g_game.openPrivateChannel(openPrivateChannelWith) + else + local selectedChannelLabel = channelListPanel:getFocusedChild() + if not selectedChannelLabel then return end + g_game.joinChannel(selectedChannelLabel.channelId) + end + channelsWindow:destroy() +end + +local function onChannelList(channelList) + local channelsWindow = displayUI('channelswindow.otui') + local channelListPanel = channelsWindow:getChildById('channelList') + channelsWindow.onEnter = function() doChannelListSubmit(channelsWindow) end + Keyboard.bindKeyPress('Down', function() channelListPanel:focusNextChild(KeyboardFocusReason) end, channelsWindow) + Keyboard.bindKeyPress('Up', function() channelListPanel:focusPreviousChild(KeyboardFocusReason) end, channelsWindow) + + for k,v in pairs(channelList) do + local channelId = v[1] + local channelName = v[2] + + if channelId ~= 0 and #channelName > 0 then + local label = createWidget('ChannelListLabel', channelListPanel) + label.channelId = channelId + label:setText(channelName) + + label:setPhantom(false) + label.onDoubleClick = function() doChannelListSubmit(channelsWindow) end + end + end +end + + -- public functions -function Console.create() - consolePanel = displayUI('console.otui', g_game.gameBottomPanel) +function Console.init() + connect(g_game, { onCreatureSpeak = onCreatureSpeak, + onChannelList = onChannelList, + onOpenChannel = onOpenChannel, + onOpenPrivateChannel = onOpenPrivateChannel}) + + consolePanel = displayUI('console.otui', GameInterface.getBottomPanel()) consoleLineEdit = consolePanel:getChildById('consoleLineEdit') consoleBuffer = consolePanel:getChildById('consoleBuffer') consoleTabBar = consolePanel:getChildById('consoleTabBar') @@ -88,25 +162,42 @@ function Console.create() Console.addChannel('Default', 0) Console.addTab('Server Log', false) - Keyboard.bindKeyDown('Shift+Up', function() navigateMessageHistory(1) end, consolePanel) - Keyboard.bindKeyDown('Shift+Down', function() navigateMessageHistory(-1) end, consolePanel) - Keyboard.bindKeyDown('Tab', function() consoleTabBar:selectNextTab() end, consolePanel) - Keyboard.bindKeyDown('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel) + Keyboard.bindKeyPress('Shift+Up', function() navigateMessageHistory(1) end, consolePanel) + Keyboard.bindKeyPress('Shift+Down', function() navigateMessageHistory(-1) end, consolePanel) + Keyboard.bindKeyPress('Tab', function() consoleTabBar:selectNextTab() end, consolePanel) + Keyboard.bindKeyPress('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel) Keyboard.bindKeyDown('Enter', Console.sendCurrentMessage, consolePanel) -- apply buttom functions after loaded - connect(consolePanel:getChildById('nextChannelButton'), { onClick = function() consoleTabBar:selectNextTab() end } ) - connect(consolePanel:getChildById('prevChannelButton'), { onClick = function() consoleTabBar:selectPrevTab() end } ) - connect(consoleTabBar, { onTabChange = Console.onTabChange }) + consolePanel:getChildById('nextChannelButton').onClick = function() consoleTabBar:selectNextTab() end + consolePanel:getChildById('prevChannelButton').onClick = function() consoleTabBar:selectPrevTab() end + consoleTabBar.onTabChange = Console.onTabChange -- tibia like hotkeys Keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels) Keyboard.bindKeyDown('Ctrl+E', Console.removeCurrentTab) end -function Console.destroy() +function Console.terminate() + disconnect(g_game, { onCreatureSpeak = onCreatureSpeak, + onChannelList = onChannelList, + onOpenChannel = onOpenChannel, + onOpenPrivateChannel = onOpenPrivateChannel }) + + for channelid, channelname in ipairs(channels) do + g_game.leaveChannel(channelid) + end + + Keyboard.unbindKeyDown('Ctrl+O') + Keyboard.unbindKeyDown('Ctrl+E') + consolePanel:destroy() consolePanel = nil + consoleLineEdit = nil + consoleBuffer = nil + consoleTabBar = nil + + Console = nil end function Console.setLineEditText(text) @@ -117,7 +208,7 @@ function Console.addTab(name, focus) local tab = consoleTabBar:addTab(name) if focus then consoleTabBar:selectTab(tab) - else + elseif name ~= 'Server Log' then consoleTabBar:blinkTab(tab) end return tab @@ -299,75 +390,3 @@ function Console.sayModeChange(sayMode) buttom:setIcon(SayModes[sayMode].icon) buttom.sayMode = sayMode end - --- hooked events -local function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos) - speaktype = SpeakTypes[speaktype] - if speaktype.hideInConsole then return end - - message = applyMessagePrefixies(name, level, message) - - if speaktype.private then - Console.addPrivateText(message, speaktype, name, false) - else - local channel = channels[channelId] - - if channel then - Console.addText(message, speaktype, channel) - else - -- server sent a message on a channel that we are not aware of, must leave it - g_game.leaveChannel(channelId) - end - end -end - -local function onOpenChannel(channelId, channelName) - Console.addChannel(channelName, channelId) -end - -local function onOpenPrivateChannel(receiver) - local privateTab = Console.getTab(receiver) - if privateTab == nil then - Console.addTab(receiver, true) - end -end - -local function doChannelListSubmit(channelsWindow) - local channelListPanel = channelsWindow:getChildById('channelList') - local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText() - if openPrivateChannelWith ~= '' then - g_game.openPrivateChannel(openPrivateChannelWith) - else - local selectedChannelLabel = channelListPanel:getFocusedChild() - if not selectedChannelLabel then return end - g_game.joinChannel(selectedChannelLabel.channelId) - end - channelsWindow:destroy() -end - -local function onChannelList(channelList) - local channelsWindow = displayUI('channelswindow.otui') - local channelListPanel = channelsWindow:getChildById('channelList') - connect(channelsWindow, { onEnter = function () doChannelListSubmit(channelsWindow) end } ) - - for k,v in pairs(channelList) do - local channelId = v[1] - local channelName = v[2] - - if channelId ~= 0 and #channelName > 0 then - local label = createWidget('ChannelListLabel', channelListPanel) - label.channelId = channelId - label:setText(channelName) - - label:setPhantom(false) - connect(label, { onDoubleClick = function () doChannelListSubmit(channelsWindow) end } ) - end - end -end - -connect(g_game, { onGameStart = Console.create, - onGameEnd = Console.destroy, - onCreatureSpeak = onCreatureSpeak, - onChannelList = onChannelList, - onOpenChannel = onOpenChannel, - onOpenPrivateChannel = onOpenPrivateChannel}) \ No newline at end of file diff --git a/modules/old/game_console/console.otmod b/modules/game_console/console.otmod similarity index 56% rename from modules/old/game_console/console.otmod rename to modules/game_console/console.otmod index 0d802b99..09cb1d28 100644 --- a/modules/old/game_console/console.otmod +++ b/modules/game_console/console.otmod @@ -3,5 +3,14 @@ Module description: Manage chat window author: OTClient team website: https://github.com/edubart/otclient - onLoad: | + reloadable: true + + dependecies: + - game + + @onLoad: | dofile 'console' + Console.init() + + @onUnload: | + Console.terminate() diff --git a/modules/old/game_console/console.otui b/modules/game_console/console.otui similarity index 94% rename from modules/old/game_console/console.otui rename to modules/game_console/console.otui index 1ce659f2..dd9d095c 100644 --- a/modules/old/game_console/console.otui +++ b/modules/game_console/console.otui @@ -14,7 +14,7 @@ Panel id: consolePanel anchors.fill: parent - ConsoleButton + TabButton id: prevChannelButton icon: /core_styles/icons/leftarrow.png anchors.left: parent.left @@ -30,7 +30,7 @@ Panel anchors.right: next.left margin-left: 5 - ConsoleButton + TabButton id: nextChannelButton icon: /core_styles/icons/rightarrow.png anchors.right: next.left @@ -38,7 +38,7 @@ Panel margin-right: 5 margin-top: 6 - ConsoleButton + TabButton id: closeChannelButton tooltip: Close this channel (Ctrl+E) icon: /core_styles/icons/closechannel.png @@ -49,7 +49,7 @@ Panel margin-top: 6 @onClick: Console.removeCurrentTab() - ConsoleButton + TabButton id: channelsButton tooltip: Open new channel (Ctrl+O) icon: /core_styles/icons/channels.png @@ -71,7 +71,7 @@ Panel margin-top: 4 focusable: false - ConsoleButton + TabButton id: sayModeButton icon: /core_styles/icons/say.png tooltip: Adjust volume @@ -91,5 +91,4 @@ Panel margin-right: 6 margin-left: 6 margin-bottom: 6 - always-active: true - focusable: false \ No newline at end of file + shift-navigation: true diff --git a/modules/old/game_textmessage/textmessage.lua b/modules/game_textmessage/textmessage.lua similarity index 70% rename from modules/old/game_textmessage/textmessage.lua rename to modules/game_textmessage/textmessage.lua index d028914a..4fc39084 100644 --- a/modules/old/game_textmessage/textmessage.lua +++ b/modules/game_textmessage/textmessage.lua @@ -17,7 +17,7 @@ local MessageTypes = { } local centerTextMessagePanel -local centerLabel +local bottomStatusLabel -- private functions local function displayMessage(msgtype, msg, time) @@ -30,17 +30,17 @@ local function displayMessage(msgtype, msg, time) end if msgtype.labelId then - local label = g_game.gameMapPanel:recursiveGetChildById(msgtype.labelId) + local label = GameInterface.getMapPanel():recursiveGetChildById(msgtype.labelId) - label:setVisible(true) label:setText(msg) label:setColor(msgtype.color) - label:resizeToText() if msgtype.wrap then label:setWidth(label:getParent():getWidth()) label:wrapText() label:setHeight(label:getTextSize().height) + else + label:resizeToText() end if not time then @@ -49,6 +49,7 @@ local function displayMessage(msgtype, msg, time) time = time * 1000 end removeEvent(label.hideEvent) + addEvent(function() label:setVisible(true) end) label.hideEvent = scheduleEvent(function() label:setVisible(false) end, time) end end @@ -64,10 +65,14 @@ local function createTextMessageLabel(id, parent) end -- public functions +function TextMessage.init() + connect(g_game, { onDeath = TextMessage.displayDeadMessage, + onTextMessage = TextMessage.display, + onGameStart = TextMessage.clearMessages }) -function TextMessage.create() - centerTextMessagePanel = createWidget('Panel', g_game.gameMapPanel) + centerTextMessagePanel = createWidget('Panel', GameInterface.getMapPanel()) centerTextMessagePanel:setId('centerTextMessagePanel') + local layout = UIVerticalLayout.create(centerTextMessagePanel) layout:setFitChildren(true) centerTextMessagePanel:setLayout(layout) @@ -78,13 +83,31 @@ function TextMessage.create() createTextMessageLabel('centerAdvance', centerTextMessagePanel) createTextMessageLabel('centerInfo', centerTextMessagePanel) - bottomStatusLabel = createTextMessageLabel('bottomStatus', g_game.gameMapPanel) + bottomStatusLabel = createTextMessageLabel('bottomStatus', GameInterface.getMapPanel()) bottomStatusLabel:setHeight(16) bottomStatusLabel:addAnchor(AnchorBottom, 'parent', AnchorBottom) bottomStatusLabel:addAnchor(AnchorLeft, 'parent', AnchorLeft) bottomStatusLabel:addAnchor(AnchorRight, 'parent', AnchorRight) end +function TextMessage.terminate() + disconnect(g_game, { onDeath = TextMessage.displayDeadMessage, + onTextMessage = TextMessage.display, + onGameStart = TextMessage.clearMessages }) + centerTextMessagePanel:destroy() + centerTextMessagePanel = nil + bottomStatusLabel:destroy() + bottomStatusLabel = nil + TextMessage = nil +end + +function TextMessage.clearMessages() + GameInterface.getMapPanel():recursiveGetChildById('centerWarning'):hide() + GameInterface.getMapPanel():recursiveGetChildById('centerAdvance'):hide() + GameInterface.getMapPanel():recursiveGetChildById('centerInfo'):hide() + GameInterface.getMapPanel():recursiveGetChildById('bottomStatus'):hide() +end + function TextMessage.displayStatus(msg, time) displayMessage(MessageTypes.warning, msg) end @@ -100,18 +123,8 @@ function TextMessage.display(msgtypedesc, msg) end end --- hooked events -local function onGameDeath() - local advanceLabel = g_game.gameMapPanel:recursiveGetChildById('centerAdvance') +function TextMessage.displayDeadMessage() + local advanceLabel = GameInterface.getMapPanel():recursiveGetChildById('centerAdvance') if advanceLabel:isVisible() then return end TextMessage.displayEventAdvance('You are dead.') end - -local function onGameTextMessage(msgtypedesc, msg) - TextMessage.display(msgtypedesc, msg) -end - -connect(g_game, { onGameStart = TextMessage.create, - onGameEnd = TextMessage.destroy, - onDeath = onGameDeath, - onTextMessage = onGameTextMessage }) diff --git a/modules/old/game_textmessage/textmessage.otmod b/modules/game_textmessage/textmessage.otmod similarity index 57% rename from modules/old/game_textmessage/textmessage.otmod rename to modules/game_textmessage/textmessage.otmod index 7d285664..8ebf958f 100644 --- a/modules/old/game_textmessage/textmessage.otmod +++ b/modules/game_textmessage/textmessage.otmod @@ -3,5 +3,14 @@ Module description: Manage game text messages author: OTClient team website: https://github.com/edubart/otclient - onLoad: | + reloadable: true + + dependecies: + - game + + @onLoad: | dofile 'textmessage' + TextMessage.init() + + @onUnload: | + TextMessage.terminate() diff --git a/modules/old/game_textmessage/textmessage.otui b/modules/game_textmessage/textmessage.otui similarity index 100% rename from modules/old/game_textmessage/textmessage.otui rename to modules/game_textmessage/textmessage.otui diff --git a/modules/game/game.lua b/modules/old/game/game.lua similarity index 100% rename from modules/game/game.lua rename to modules/old/game/game.lua diff --git a/modules/old/game/game.otmod b/modules/old/game/game.otmod new file mode 100644 index 00000000..5dcf5858 --- /dev/null +++ b/modules/old/game/game.otmod @@ -0,0 +1,17 @@ +Module + name: game + description: Create the game interface, where the ingame stuff starts + author: OTClient team + website: https://github.com/edubart/otclient + reloadable: true + + dependencies: + - game_tibiafiles + //- game_shaders + + onLoad: | + dofile 'game' + dofile 'thing' + dofile 'creature' + dofile 'player' + dofile 'map' diff --git a/modules/game/game.otui b/modules/old/game/game.otui similarity index 100% rename from modules/game/game.otui rename to modules/old/game/game.otui diff --git a/modules/game/map.lua b/modules/old/game/map.lua similarity index 100% rename from modules/game/map.lua rename to modules/old/game/map.lua diff --git a/modules/game/movewindow.otui b/modules/old/game/movewindow.otui similarity index 96% rename from modules/game/movewindow.otui rename to modules/old/game/movewindow.otui index 9e0438f8..85fcc27c 100644 --- a/modules/game/movewindow.otui +++ b/modules/old/game/movewindow.otui @@ -1,4 +1,4 @@ -MainWindow +CountWindow < MainWindow text: Move Item size: 196 112 @onEscape: self:destroy() diff --git a/modules/game/player.lua b/modules/old/game/player.lua similarity index 100% rename from modules/game/player.lua rename to modules/old/game/player.lua diff --git a/modules/game/thing.lua b/modules/old/game/thing.lua similarity index 100% rename from modules/game/thing.lua rename to modules/old/game/thing.lua diff --git a/modules/old/game_hotkeys/hotkeys_manager.lua b/modules/old/game_hotkeys/hotkeys_manager.lua index 2371096f..6a1b0e67 100644 --- a/modules/old/game_hotkeys/hotkeys_manager.lua +++ b/modules/old/game_hotkeys/hotkeys_manager.lua @@ -455,4 +455,4 @@ function HotkeysManager.hotkeyCapture(widget, keyCode, keyboardModifiers) hotkeysWindow:getChildById('assignWindow'):getChildById('addButton'):enable() return true -end \ No newline at end of file +end diff --git a/modules/old/game_hotkeys/hotkeys_manager.otui b/modules/old/game_hotkeys/hotkeys_manager.otui index 7b3b6369..52ba6325 100644 --- a/modules/old/game_hotkeys/hotkeys_manager.otui +++ b/modules/old/game_hotkeys/hotkeys_manager.otui @@ -156,4 +156,4 @@ MainWindow width: 64 anchors.right: parent.right anchors.bottom: parent.bottom - @onClick: HotkeysManager.hide() \ No newline at end of file + @onClick: HotkeysManager.hide() diff --git a/modules/old/game_interface/gameinterface.otui b/modules/old/game_interface/gameinterface.otui index 1bfb7f9e..96b12a5f 100644 --- a/modules/old/game_interface/gameinterface.otui +++ b/modules/old/game_interface/gameinterface.otui @@ -1,14 +1,14 @@ GameSidePanel < UIMiniWindowContainer - image-source: /core_styles/styles/images/sidepanel.png + image-source: images/sidepanel.png image-border: 4 GameBottomPanel < Panel - image-source: /core_styles/styles/images/bottompanel.png + image-source: images/bottompanel.png image-border: 4 GameMapPanel < UIMap padding: 4 - image-source: /core_styles/styles/images/mappanel.png + image-source: images/mappanel.png image-border: 4 UIGame @@ -16,7 +16,7 @@ UIGame anchors.fill: parent anchors.top: topMenu.bottom - InterfacePanel + GameSidePanel id: gameRightPanel width: 190 layout: verticalBox diff --git a/modules/otclientrc.lua b/modules/otclientrc.lua index 83b7ac0c..5eacb642 100644 --- a/modules/otclientrc.lua +++ b/modules/otclientrc.lua @@ -1,5 +1,6 @@ --- this file use loaded after everything is loaded and initialized +-- this file is loaded after all modules are loaded and initialized -- you can place any custom user code here +-- you Keyboard.bindKeyDown('F1', function() g_game.talk('exura gran') end) Keyboard.bindKeyDown('F2', function() g_game.talk('exori mort') end) @@ -7,12 +8,4 @@ Keyboard.bindKeyDown('F3', function() g_game.talk('exori frigo') end) Keyboard.bindKeyDown('F4', function() g_game.talk('exevo vis hur') end) Keyboard.bindKeyDown('F5', function() g_game.talk('utani gran hur') end) Keyboard.bindKeyDown('F6', function() g_game.talk('exani tera') end) - -local function reload() - dofile('otclientrc.lua') - TextMessage.displayEventAdvance('Script otclientrc.lua reloaded.') - print('Script otclient.rc lua reloaded') -end -Keyboard.bindKeyDown('Ctrl+R', reload) - -rcloaded = true +Keyboard.bindKeyDown('Ctrl+R', Client.reloadScripts) diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 910baed9..0dc08ef8 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -50,15 +50,6 @@ IF(CMAKE_COMPILER_IS_GNUCXX) SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -static-libgcc -static-libstdc++ -Wl,--as-needed") ENDIF(CMAKE_COMPILER_IS_GNUCXX) -IF(CMAKE_BUILD_TYPE STREQUAL "Debug") - ADD_DEFINITIONS(-DDEBUG) -ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") - -IF(CMAKE_BUILD_TYPE STREQUAL "Release") - # NDEBUG disable asserts - ADD_DEFINITIONS(-DNDEBUG) -ENDIF(CMAKE_BUILD_TYPE STREQUAL "Release") - MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) IF(USE_OPENGL_ES2) MESSAGE(STATUS "Renderer: OpenGL ES 2.0") @@ -66,6 +57,18 @@ ELSE(USE_OPENGL_ES2) MESSAGE(STATUS "Renderer: OpenGL") ENDIF(USE_OPENGL_ES2) +IF(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + ADD_DEFINITIONS(-DDEBUG) + MESSAGE(STATUS "Debug information: ON") +ELSE() + MESSAGE(STATUS "Debug information: OFF") +ENDIF() + +IF(CMAKE_BUILD_TYPE STREQUAL "Release") + # NDEBUG disable asserts + ADD_DEFINITIONS(-DNDEBUG) +ENDIF(CMAKE_BUILD_TYPE STREQUAL "Release") + IF(CRASH_HANDLER) ADD_DEFINITIONS(-DCRASH_HANDLER) MESSAGE(STATUS "Crash handler: ON") diff --git a/src/framework/application.cpp b/src/framework/application.cpp index 9eba169b..7295c94d 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -219,10 +219,7 @@ void Application::poll() void Application::close() { - g_lua.getGlobalField("g_app", "onClose"); - if(!g_lua.isNil()) - g_lua.protectedCall(); - else + if(!g_lua.callGlobalField("g_app", "onClose")) exit(); } diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 1952d865..7511e3d8 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -362,6 +362,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("setTextHidden", &UILineEdit::setTextHidden); g_lua.bindClassMemberFunction("setAlwaysActive", &UILineEdit::setAlwaysActive); g_lua.bindClassMemberFunction("setValidCharacters", &UILineEdit::setValidCharacters); + g_lua.bindClassMemberFunction("setShiftNavigation", &UILineEdit::setShiftNavigation); g_lua.bindClassMemberFunction("moveCursor", &UILineEdit::moveCursor); g_lua.bindClassMemberFunction("appendText", &UILineEdit::appendText); g_lua.bindClassMemberFunction("removeCharacter", &UILineEdit::removeCharacter); @@ -372,6 +373,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("isCursorEnabled", &UILineEdit::isCursorEnabled); g_lua.bindClassMemberFunction("isAlwaysActive", &UILineEdit::isAlwaysActive); g_lua.bindClassMemberFunction("isTextHidden", &UILineEdit::isTextHidden); + g_lua.bindClassMemberFunction("isShiftNavigation", &UILineEdit::isShiftNavigation); // UIFrameCounter g_lua.registerClass(); diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 035096bd..c87bbbd1 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -35,6 +35,7 @@ UILineEdit::UILineEdit() m_textHorizontalMargin = 0; m_textHidden = false; m_alwaysActive = false; + m_shiftNavigation = false; blinkCursor(); } @@ -407,8 +408,8 @@ void UILineEdit::onStyleApply(const std::string& styleName, const OTMLNodePtr& s setTextHorizontalMargin(node->value()); else if(node->tag() == "always-active") setAlwaysActive(node->value()); - //else if(node->tag() == "disable-arrow-navitation") - // setArrowNavigation(node->value()); + else if(node->tag() == "shift-navigation") + setShiftNavigation(node->value()); } } @@ -434,28 +435,46 @@ bool UILineEdit::onKeyPress(uchar keyCode, int keyboardModifiers, int autoRepeat if(UIWidget::onKeyPress(keyCode, keyboardModifiers, autoRepeatTicks)) return true; - if(keyCode == Fw::KeyDelete) // erase right character - removeCharacter(true); - else if(keyCode == Fw::KeyBackspace) // erase left character { - removeCharacter(false); - else if(keyCode == Fw::KeyRight) // move cursor right - moveCursor(true); - else if(keyCode == Fw::KeyLeft) // move cursor left - moveCursor(false); - else if(keyCode == Fw::KeyHome) // move cursor to first character - setCursorPos(0); - else if(keyCode == Fw::KeyEnd) // move cursor to last character - setCursorPos(m_text.length()); - else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier) - appendText(g_window.getClipboardText()); - else if(keyCode == Fw::KeyTab) { - if(!m_alwaysActive) { + if(keyboardModifiers == Fw::KeyboardNoModifier) { + if(keyCode == Fw::KeyDelete) { // erase right character + removeCharacter(true); + return true; + } else if(keyCode == Fw::KeyBackspace) { // erase left character { + removeCharacter(false); + return true; + } else if(keyCode == Fw::KeyRight && !m_shiftNavigation) { // move cursor right + moveCursor(true); + return true; + } else if(keyCode == Fw::KeyLeft && !m_shiftNavigation) { // move cursor left + moveCursor(false); + return true; + } else if(keyCode == Fw::KeyHome) { // move cursor to first character + setCursorPos(0); + return true; + } else if(keyCode == Fw::KeyEnd) { // move cursor to last character + setCursorPos(m_text.length()); + return true; + } else if(keyCode == Fw::KeyTab && !m_shiftNavigation) { if(UIWidgetPtr parent = getParent()) parent->focusNextChild(Fw::KeyboardFocusReason); + return true; } - } else - return false; - return true; + } else if(keyboardModifiers == Fw::KeyboardCtrlModifier) { + if(keyCode == Fw::KeyV) { + appendText(g_window.getClipboardText()); + return true; + } + } else if(keyboardModifiers == Fw::KeyboardShiftModifier) { + if(keyCode == Fw::KeyRight && m_shiftNavigation) { // move cursor right + moveCursor(true); + return true; + } else if(keyCode == Fw::KeyLeft && m_shiftNavigation) { // move cursor left + moveCursor(false); + return true; + } + } + + return false; } bool UILineEdit::onKeyText(const std::string& keyText) diff --git a/src/framework/ui/uilineedit.h b/src/framework/ui/uilineedit.h index 319b9317..4922e710 100644 --- a/src/framework/ui/uilineedit.h +++ b/src/framework/ui/uilineedit.h @@ -42,6 +42,7 @@ public: void setTextHidden(bool hidden); void setAlwaysActive(bool enable); void setValidCharacters(const std::string validCharacters) { m_validCharacters = validCharacters; } + void setShiftNavigation(bool enable) { m_shiftNavigation = enable; } void moveCursor(bool right); void appendText(std::string text); @@ -55,6 +56,7 @@ public: bool isCursorEnabled() { return m_cursorPos != -1; } bool isAlwaysActive() { return m_alwaysActive; } bool isTextHidden() { return m_textHidden; } + bool isShiftNavigation() { return m_shiftNavigation; } protected: virtual void onTextChange(const std::string& text, const std::string& oldText); @@ -77,6 +79,7 @@ private: int m_textHorizontalMargin; bool m_textHidden; bool m_alwaysActive; + bool m_shiftNavigation; std::string m_validCharacters; std::vector m_glyphsCoords; diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index 9dbc48b6..70215d7b 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -319,7 +319,12 @@ UIWidgetPtr UIManager::loadUI(const std::string& file, const UIWidgetPtr& parent return nullptr; } } +/* +UIWidgetPtr UIManager::loadWidgetFromStyle() +{ +} +*/ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent) { OTMLNodePtr originalStyleNode = getStyle(widgetNode->tag()); diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 2044f269..29b14773 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -206,7 +206,7 @@ void UIWidget::removeChild(UIWidgetPtr child) g_ui.onWidgetDisappear(child); } else - logError("Attempt to remove an unknown child from a UIWidget"); + logError("attempt to remove an unknown child from a UIWidget"); } @@ -637,11 +637,12 @@ void UIWidget::destroy() // remove itself from parent if(UIWidgetPtr parent = getParent()) { - if(parent->hasChild(asUIWidget())) - parent->removeChild(asUIWidget()); + assert(parent->hasChild(asUIWidget())); + parent->removeChild(asUIWidget()); } destroyChildren(); + m_focusedChild = nullptr; callLuaField("onDestroy"); @@ -649,12 +650,13 @@ void UIWidget::destroy() #ifdef DEBUG auto self = asUIWidget(); + g_lua.collectGarbage(); if(self != g_ui.getRootWidget()) { g_eventDispatcher.scheduleEvent([self] { g_lua.collectGarbage(); if(self->getUseCount() != 1) logWarning("widget '", self->getId(), "' destroyed but still have ", self->getUseCount()-1, " reference(s) left"); - }, 100); + }, 500); } #endif } diff --git a/src/framework/ui/uiwidgettext.cpp b/src/framework/ui/uiwidgettext.cpp index 1089368d..cb371179 100644 --- a/src/framework/ui/uiwidgettext.cpp +++ b/src/framework/ui/uiwidgettext.cpp @@ -51,6 +51,9 @@ void UIWidget::drawText(const Rect& screenCoords) if(m_text.length() == 0 || m_color.a() == 0) return; +#if 0 + //TODO: creating framebuffers on the fly was slowing down the render + // we should use vertex arrys instead of this method Size boxSize = screenCoords.size(); if(boxSize != m_textCachedBoxSize || m_textMustRecache) { if(!m_textFramebuffer) @@ -73,6 +76,11 @@ void UIWidget::drawText(const Rect& screenCoords) g_painter.setColor(m_color); m_textFramebuffer->draw(screenCoords); +#else + Rect textRect = screenCoords; + textRect.translate(m_textOffset); + m_font->renderText(m_text, textRect, m_textAlign, m_color); +#endif } void UIWidget::onTextChange(const std::string& text, const std::string& oldText) diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index d6148735..976a6b78 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -31,6 +31,7 @@ SET(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/thingstype.cpp ${CMAKE_CURRENT_LIST_DIR}/core/spritemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/core/item.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/container.cpp ${CMAKE_CURRENT_LIST_DIR}/core/tile.cpp ${CMAKE_CURRENT_LIST_DIR}/core/thing.cpp ${CMAKE_CURRENT_LIST_DIR}/core/creature.cpp diff --git a/src/otclient/core/container.cpp b/src/otclient/core/container.cpp new file mode 100644 index 00000000..df12527a --- /dev/null +++ b/src/otclient/core/container.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "container.h" diff --git a/src/otclient/ui/uigame.h b/src/otclient/core/container.h similarity index 83% rename from src/otclient/ui/uigame.h rename to src/otclient/core/container.h index 5ae1e7ba..f29a5b42 100644 --- a/src/otclient/ui/uigame.h +++ b/src/otclient/core/container.h @@ -20,17 +20,16 @@ * THE SOFTWARE. */ -#ifndef UIGAME_H -#define UIGAME_H +#ifndef CONTAINER_H +#define CONTAINER_H #include "declarations.h" -#include -class UIGame : public UIWidget +class Container { -protected: - bool onKeyPress(uchar keyCode, int keyboardModifiers, int autoRepeatTicks); - bool onKeyText(const std::string& keyText); +public: + Container(); + }; #endif diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index 78c46fd5..15ccb338 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -31,6 +31,7 @@ class MapView; class Tile; class Thing; class Item; +class Container; class Creature; class Monster; class Npc; @@ -45,6 +46,7 @@ typedef std::shared_ptr MapViewPtr; typedef std::shared_ptr TilePtr; typedef std::shared_ptr ThingPtr; typedef std::shared_ptr ItemPtr; +typedef std::shared_ptr ContainerPtr; typedef std::shared_ptr CreaturePtr; typedef std::shared_ptr MonsterPtr; typedef std::shared_ptr NpcPtr; diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 7b1c15cd..d49bd4fb 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -764,7 +764,6 @@ void Game::setSafeFight(bool on) m_protocolGame->sendChangeFightModes(m_fightMode, m_chaseMode, m_safeFight); } - void Game::inspectNpcTrade(const ItemPtr& item) { if(!canPerformGameAction() || !item) diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 2b0aa59d..850bac1e 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -216,6 +216,7 @@ public: bool isAttacking() { return !!m_attackingCreature; } bool isFollowing() { return !!m_followingCreature; } + ContainerPtr getContainer(int index) { return m_containers[index]; } CreaturePtr getAttackingCreature() { return m_attackingCreature; } CreaturePtr getFollowingCreature() { return m_followingCreature; } int getServerBeat() { return m_serverBeat; } @@ -231,6 +232,7 @@ private: CreaturePtr m_attackingCreature; CreaturePtr m_followingCreature; ProtocolGamePtr m_protocolGame; + std::map m_containers; bool m_dead; int m_serverBeat; Otc::FightModes m_fightMode; diff --git a/src/otclient/core/mapview.cpp b/src/otclient/core/mapview.cpp index f59897bb..189b7ead 100644 --- a/src/otclient/core/mapview.cpp +++ b/src/otclient/core/mapview.cpp @@ -36,12 +36,17 @@ MapView::MapView() { + m_viewRange = NEAR_VIEW; + m_lockedFirstVisibleFloor = -1; + m_cachedFirstVisibleFloor = 0; + m_cachedLastVisibleFloor = 7; + m_customCameraPosition.z = 7; + Size frameBufferSize(std::min(g_graphics.getMaxTextureSize(), (int)DEFAULT_FRAMBUFFER_WIDTH), std::min(g_graphics.getMaxTextureSize(), (int)DEFAULT_FRAMBUFFER_HEIGHT)); m_framebuffer = FrameBufferPtr(new FrameBuffer(frameBufferSize)); m_framebuffer->setClearColor(Fw::black); - m_lockedFirstVisibleFloor = -1; setVisibleDimension(Size(15, 11)); m_shaderProgram = PainterShaderProgramPtr(new PainterShaderProgram); @@ -374,7 +379,6 @@ void MapView::unlockFirstVisibleFloor() void MapView::followCreature(const CreaturePtr& creature) { m_followingCreature = creature; - m_customCameraPosition = Position(); requestVisibleTilesCacheUpdate(); } diff --git a/src/otclient/core/mapview.h b/src/otclient/core/mapview.h index 53e893cd..e23dc356 100644 --- a/src/otclient/core/mapview.h +++ b/src/otclient/core/mapview.h @@ -93,7 +93,6 @@ public: MapViewPtr asMapView() { return std::static_pointer_cast(shared_from_this()); } private: - int m_drawFlags; int m_lockedFirstVisibleFloor; int m_cachedFirstVisibleFloor; int m_cachedLastVisibleFloor; @@ -102,7 +101,6 @@ private: Size m_visibleDimension; Point m_virtualCenterOffset; Position m_customCameraPosition; - Position m_framebufferCenterPosition; Boolean m_mustUpdateVisibleTilesCache; Boolean m_mustDrawVisibleTilesCache; Boolean m_mustCleanFramebuffer; diff --git a/src/otclient/core/player.cpp b/src/otclient/core/player.cpp new file mode 100644 index 00000000..237e5355 --- /dev/null +++ b/src/otclient/core/player.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "player.h" diff --git a/src/otclient/core/player.h b/src/otclient/core/player.h index 461c4069..83c93b1a 100644 --- a/src/otclient/core/player.h +++ b/src/otclient/core/player.h @@ -31,6 +31,10 @@ public: Player() { } virtual ~Player() { } + bool isPartyMember() { return (m_shield != 0); } + bool isPartyLeader() { return (m_shield & Otc::ShieldYellow); } + bool isPartySharedExperienceActive() { return false; } + PlayerPtr asPlayer() { return std::static_pointer_cast(shared_from_this()); } }; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 66aa5151..a557b499 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -26,6 +26,7 @@ #include #include "map.h" #include "tile.h" +#include "game.h" Thing::Thing() { @@ -53,6 +54,13 @@ const TilePtr& Thing::getTile() return g_map.getTile(m_position); } +ContainerPtr Thing::getParentContainer() +{ + if(m_position.x == 0xFFFF && m_position.y & 0x40) + return g_game.getContainer(m_position.z); + return nullptr; +} + int Thing::getStackpos() { if(m_position.x == 65535 && asItem()) // is inside a container diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 1b270009..8b197c7d 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -49,6 +49,7 @@ public: Position getPosition() { return m_position; } int getStackPriority(); const TilePtr& getTile(); + ContainerPtr getParentContainer(); int getStackpos(); ThingPtr asThing() { return std::static_pointer_cast(shared_from_this()); } diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 7b487d02..1d27729c 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -305,6 +305,7 @@ void OTClient::registerLuaFunctions() g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return UIMapPtr(new UIMap); } ); + g_lua.bindClassMemberFunction("followCreature", &UIMap::followCreature); g_lua.bindClassMemberFunction("getTile", &UIMap::getTile); g_lua.bindClassMemberFunction("zoomIn", &UIMap::zoomIn); g_lua.bindClassMemberFunction("zoomOut", &UIMap::zoomOut); diff --git a/src/otclient/ui/uigame.cpp b/src/otclient/ui/uigame.cpp deleted file mode 100644 index bf001a40..00000000 --- a/src/otclient/ui/uigame.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "uigame.h" -#include -#include -#include - -bool UIGame::onKeyPress(uchar keyCode, int keyboardModifiers, int autoRepeatTicks) -{ - if(UIWidget::onKeyPress(keyCode, keyboardModifiers, autoRepeatTicks)) - return true; - - UILineEditPtr chatLineEdit = std::dynamic_pointer_cast(getParent()->recursiveGetChildById("consoleLineEdit")); - - //TODO: move this whole shit to lua - if(keyboardModifiers == Fw::KeyboardNoModifier) { - if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) { - g_game.walk(Otc::North); - return true; - } else if(keyCode == Fw::KeyRight || keyCode == Fw::KeyNumpad6) { - g_game.walk(Otc::East); - return true; - } else if(keyCode == Fw::KeyDown || keyCode == Fw::KeyNumpad2) { - g_game.walk(Otc::South); - return true; - } else if(keyCode == Fw::KeyLeft || keyCode == Fw::KeyNumpad4) { - g_game.walk(Otc::West); - return true; - } else if(keyCode == Fw::KeyNumpad9) { - g_game.walk(Otc::NorthEast); - return true; - } else if(keyCode == Fw::KeyNumpad3) { - g_game.walk(Otc::SouthEast); - return true; - } else if(keyCode == Fw::KeyNumpad1) { - g_game.walk(Otc::SouthWest); - return true; - } else if(keyCode == Fw::KeyNumpad7) { - g_game.walk(Otc::NorthWest); - return true; - } else if(keyCode == Fw::KeyDelete) { - chatLineEdit->removeCharacter(true); - return true; - } else if(keyCode == Fw::KeyBackspace) { - chatLineEdit->removeCharacter(false); - return true; - } else if(keyCode == Fw::KeyRight) { - chatLineEdit->moveCursor(true); - return true; - } else if(keyCode == Fw::KeyLeft) { - chatLineEdit->moveCursor(false); - return true; - } else if(keyCode == Fw::KeyHome) { - chatLineEdit->setCursorPos(0); - return true; - } else if(keyCode == Fw::KeyEnd) { - chatLineEdit->setCursorPos(chatLineEdit->getText().length()); - return true; - } - } else if(keyboardModifiers == Fw::KeyboardCtrlModifier) { - if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) { - g_game.turn(Otc::North); - return true; - } else if(keyCode == Fw::KeyRight || keyCode == Fw::KeyNumpad6) { - g_game.turn(Otc::East); - return true; - } else if(keyCode == Fw::KeyDown || keyCode == Fw::KeyNumpad2) { - g_game.turn(Otc::South); - return true; - } else if(keyCode == Fw::KeyLeft || keyCode == Fw::KeyNumpad4) { - g_game.turn(Otc::West); - return true; - } else if(keyCode == Fw::KeyV) { - chatLineEdit->appendText(g_window.getClipboardText()); - } - } else if(keyboardModifiers == Fw::KeyboardShiftModifier) { - if(keyCode == Fw::KeyRight || keyCode == Fw::KeyNumpad6) { - chatLineEdit->moveCursor(true); - return true; - } else if(keyCode == Fw::KeyLeft || keyCode == Fw::KeyNumpad4) { - chatLineEdit->moveCursor(false); - return true; - } - } - - return false; -} - -bool UIGame::onKeyText(const std::string& keyText) -{ - if(UIWidget::onKeyText(keyText)) - return true; - - UILineEditPtr chatLineEdit = std::dynamic_pointer_cast(getParent()->recursiveGetChildById("consoleLineEdit")); - chatLineEdit->appendText(keyText); - return true; -} diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 411ec563..b7816d05 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -33,7 +33,6 @@ UIMap::UIMap() m_dragable = true; m_mapView = MapViewPtr(new MapView); g_map.addMapView(m_mapView); - m_mapView->followCreature(g_game.getLocalPlayer()); } UIMap::~UIMap() @@ -96,6 +95,11 @@ void UIMap::zoomOut() m_mapRect.moveCenter(m_rect.center()); } +void UIMap::followCreature(const CreaturePtr& creature) +{ + m_mapView->followCreature(creature); +} + void UIMap::setCameraPosition(const Position& pos) { m_mapView->setCameraPosition(pos); diff --git a/src/otclient/ui/uimap.h b/src/otclient/ui/uimap.h index 41452cc9..074976c2 100644 --- a/src/otclient/ui/uimap.h +++ b/src/otclient/ui/uimap.h @@ -37,6 +37,7 @@ public: void zoomIn(); void zoomOut(); + void followCreature(const CreaturePtr& creature); void setCameraPosition(const Position& pos); TilePtr getTile(const Point& mousePos);