Many changes

* IMPORTANT: dat/spr should now be placed in /data/things/
* Rename game_tibiafiles to game_things
* Make battle list algorithm much faster
* Split UITabBar into UITabBar and UIMoveableTabBar
* Fix other minor issues
This commit is contained in:
Eduardo Bart 2013-01-21 19:36:53 -02:00
parent 0729e35b50
commit 71cccac3da
27 changed files with 467 additions and 524 deletions

View File

@ -24,7 +24,7 @@ TabButton < UIButton
image-source: /images/ui/tabbutton_rounded
image-color: white
image-clip: 0 0 20 20
image-border: 2
image-border: 1
icon-color: white
color: #aaaaaa

View File

@ -48,7 +48,7 @@ ButtonBox < UICheckBox
image-source: /images/ui/tabbutton_rounded
image-color: white
image-clip: 0 0 20 20
image-border: 2
image-border: 3
$hover !disabled:
image-clip: 0 20 20 20

View File

@ -1,12 +1,12 @@
TabBar < UITabBar
MoveableTabBar < UIMoveableTabBar
size: 80 20
TabBarPanel < Panel
TabBarButton < UIButton
MoveableTabBarPanel < Panel
MoveableTabBarButton < UIButton
size: 20 20
image-source: /images/ui/tabbutton_square
image-color: white
image-clip: 0 0 20 20
image-border: 2
image-border: 3
icon-color: white
color: #aaaaaa
anchors.top: parent.top
@ -28,6 +28,45 @@ TabBarButton < UIButton
$on !checked:
color: #F55E5E
TabBar < UITabBar
size: 80 20
Panel
id: buttonsPanel
anchors.fill: parent
TabBarPanel < Panel
TabBarButton < UIButton
size: 20 20
image-source: /images/ui/tabbutton_square
image-color: white
image-clip: 0 0 20 20
image-border: 3
icon-color: white
color: #aaaaaa
anchors.top: parent.top
padding: 5
$first:
anchors.left: parent.left
$!first:
anchors.left: prev.right
margin-left: 5
$hover !checked:
image-clip: 0 20 20 20
color: white
$disabled:
image-color: #ffffff66
icon-color: #888888
$checked:
image-clip: 0 40 20 20
color: #80c7f8
$on !checked:
color: #F55E5E
TabBarRounded < TabBar
TabBarRoundedPanel < TabBarPanel
TabBarRoundedButton < TabBarButton
@ -35,7 +74,6 @@ TabBarRoundedButton < TabBarButton
TabBarVertical < UITabBar
width: 96
ScrollableFlatPanel
id: buttonsPanel
anchors.top: parent.top
@ -43,7 +81,6 @@ TabBarVertical < UITabBar
anchors.right: scrollBar.left
anchors.bottom: parent.bottom
vertical-scrollbar: scrollBar
VerticalScrollBar
id: scrollBar
anchors.top: parent.top
@ -51,12 +88,9 @@ TabBarVertical < UITabBar
anchors.right: parent.right
step: 16
pixels-scroll: true
$!on:
width: 0
TabBarVerticalPanel < Panel
TabBarVerticalButton < UIButton
size: 48 48
color: #aaaaaa
@ -66,24 +100,18 @@ TabBarVerticalButton < UIButton
icon-align: top
icon-offset-y: 2
icon-color: #888888
$first:
anchors.top: parent.top
$!first:
anchors.top: prev.bottom
margin-top: 5
$hover !checked:
color: white
icon-color: #cccccc
$disabled:
icon-color: #333333
$checked:
icon-color: #ffffff
color: #80c7f8
$on !checked:
color: #F55E5E

2
data/things/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -30,7 +30,8 @@ local function tryLogin(charInfo, tries)
CharacterList.destroyLoadBox()
g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
local locale = modules.client_locales.getCurrentLocale().name
g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, locale)
loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...'))
connect(loadBox, { onCancel = function()
@ -82,6 +83,7 @@ local function resendWait()
if selected then
local charInfo = { worldHost = selected.worldHost,
worldPort = selected.worldPort,
worldName = selected.worldName,
characterName = selected.characterName }
tryLogin(charInfo)
end
@ -119,9 +121,19 @@ function onGameConnectionError(message, code)
end
end
function onGameUpdateNeeded(signature)
CharacterList.destroyLoadBox()
errorBox = displayErrorBox(tr("Update needed"), tr('Enter with your account again to update your client.'))
errorBox.onOk = function()
errorBox = nil
CharacterList.showAgain()
end
end
-- public functions
function CharacterList.init()
connect(g_game, { onLoginError = onGameLoginError })
connect(g_game, { onUpdateNeeded = onGameUpdateNeeded })
connect(g_game, { onConnectionError = onGameConnectionError })
connect(g_game, { onGameStart = CharacterList.destroyLoadBox })
connect(g_game, { onLoginWait = onLoginWait })
@ -134,6 +146,7 @@ end
function CharacterList.terminate()
disconnect(g_game, { onLoginError = onGameLoginError })
disconnect(g_game, { onUpdateNeeded = onGameUpdateNeeded })
disconnect(g_game, { onConnectionError = onGameConnectionError })
disconnect(g_game, { onGameStart = CharacterList.destroyLoadBox })
disconnect(g_game, { onLoginWait = onLoginWait })
@ -208,6 +221,7 @@ function CharacterList.create(characters, account, otui)
-- these are used by login
widget.characterName = characterInfo.name
widget.worldName = characterInfo.worldName
widget.worldHost = characterInfo.worldIp
widget.worldPort = characterInfo.worldPort
@ -281,6 +295,7 @@ function CharacterList.doLogin()
if selected then
local charInfo = { worldHost = selected.worldHost,
worldPort = selected.worldPort,
worldName = selected.worldName,
characterName = selected.characterName }
charactersWindow:hide()
tryLogin(charInfo)

View File

@ -58,6 +58,17 @@ local function onChangeProtocol(combobox, option)
protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.toString(clients))
end
local function onUpdateNeeded(protocol, signature)
loadBox:destroy()
loadBox = nil
if updateFunc then
local continueFunc = EnterGame.show
local cancelFunc = EnterGame.show
updateFunc(signature, continueFunc, cancelFunc)
end
end
-- public functions
function EnterGame.init()
enterGame = g_ui.displayUI('entergame')
@ -118,6 +129,7 @@ end
function EnterGame.terminate()
g_keyboard.unbindKeyDown('Ctrl+G')
removeEvent(autoLoginEvent)
enterGame:destroy()
enterGame = nil
enterGameButton:destroy()
@ -183,6 +195,7 @@ function EnterGame.doLogin()
protocolLogin.onError = onError
protocolLogin.onMotd = onMotd
protocolLogin.onCharacterList = onCharacterList
protocolLogin.onUpdateNeeded = onUpdateNeeded
loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to login server...'))
connect(loadBox, { onCancel = function(msgbox)
@ -197,8 +210,9 @@ function EnterGame.doLogin()
g_game.setClientVersion(clientVersions[#clientVersions])
end
if modules.game_tibiafiles.isLoaded() then
protocolLogin:login(G.host, G.port, G.account, G.password)
if modules.game_things.isLoaded() then
local locale = modules.client_locales.getCurrentLocale().name
protocolLogin:login(G.host, G.port, G.account, G.password, locale)
else
loadBox:destroy()
loadBox = nil
@ -264,3 +278,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
if not windowHeight then windowHeight = 200 end
enterGame:setHeight(windowHeight)
end
function EnterGame.setServerInfo(message)
local label = enterGame:getChildById('serverInfoLabel')
label:setText(message)
end

View File

@ -12,7 +12,7 @@ EnterGameWindow
anchors.top: parent.top
text-auto-resize: true
TextEdit
PasswordTextEdit
id: accountNameTextEdit
anchors.left: parent.left
anchors.right: parent.right
@ -86,7 +86,7 @@ EnterGameWindow
CheckBox
id: rememberPasswordBox
!text: tr('Remember password')
!tooltip: tr('Remember account and password when starts otclient')
!tooltip: tr('Remember account and password when starts client')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
@ -97,7 +97,7 @@ EnterGameWindow
id: autoLoginBox
enabled: false
!text: tr('Auto login')
!tooltip: tr('Open charlist automatically when starting otclient')
!tooltip: tr('Open charlist automatically when starting client')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
@ -109,3 +109,10 @@ EnterGameWindow
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: EnterGame.doLogin()
Label
id: serverInfoLabel
font: verdana-11px-rounded
anchors.bottom: parent.bottom
anchors.left: parent.left
color: green

View File

@ -5,12 +5,10 @@ local defaultLocaleName = 'en'
local installedLocales
local currentLocale
LocaleExtendedId = 1
function sendLocale(localeName)
local protocolGame = g_game.getProtocolGame()
if protocolGame then
protocolGame:sendExtendedOpcode(LocaleExtendedId, localeName)
protocolGame:sendExtendedOpcode(ExtendedIds.Locale, localeName)
return true
end
return false
@ -66,7 +64,7 @@ function init()
connect(g_app, {onRun = createWindow})
end
ProtocolGame.registerExtendedOpcode(LocaleExtendedId, onExtendedLocales)
ProtocolGame.registerExtendedOpcode(ExtendedIds.Locale, onExtendedLocales)
connect(g_game, { onGameStart = onGameStart })
end
@ -74,7 +72,7 @@ function terminate()
installedLocales = nil
currentLocale = nil
ProtocolGame.unregisterExtendedOpcode(LocaleExtendedId)
ProtocolGame.unregisterExtendedOpcode(ExtendedIds.Locale)
disconnect(g_game, { onGameStart = onGameStart })
end

View File

@ -1,317 +1,3 @@
-- generated by ./tools/gen_needed_translations.sh
modules.client_locales.neededTranslations = {
"1a) Offensive Name",
"1b) Invalid Name Format",
"1c) Unsuitable Name",
"1d) Name Inciting Rule Violation",
"2a) Offensive Statement",
"2b) Spamming",
"2c) Illegal Advertising",
"2d) Off-Topic Public Statement",
"2e) Non-English Public Statement",
"2f) Inciting Rule Violation",
"3a) Bug Abuse",
"3b) Game Weakness Abuse",
"3c) Using Unofficial Software to Play",
"3d) Hacking",
"3e) Multi-Clienting",
"3f) Account Trading or Sharing",
"4a) Threatening Gamemaster",
"4b) Pretending to Have Influence on Rule Enforcement",
"4c) False Report to Gamemaster",
"Accept",
"Account name",
"Account Status:\nFree Account",
"Account Status:\nPremium Account (%s) days left",
"Action:",
"Add",
"Add new VIP",
"Addon 1",
"Addon 2",
"Addon 3",
"Add to VIP list",
"Adjust volume",
"Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!",
"All modules and scripts were reloaded.",
"Allow auto chase override",
"Amount:",
"Amount",
"Anonymous",
"Are you sure you want to logout?",
"Attack",
"Author",
"Autoload",
"Autoload priority",
"Auto login",
"Auto login selected character on next charlist load",
"Axe Fighting",
"Balance:",
"Banishment",
"Banishment + Final Warning",
"Battle",
"Browse",
"Bug report sent.",
"Button Assign",
"Buy",
"Buy Now",
"Buy Offers",
"Buy with backpack",
"Cancel",
"Cannot login while already in game.",
"Cap",
"Capacity",
"Center",
"Channels",
"Character List",
"Classic control",
"Clear current message window",
"Clear object",
"Client needs update.",
"Close",
"Close this channel",
"Club Fighting",
"Combat Controls",
"Comment:",
"Connecting to game server...",
"Connecting to login server...",
"Copy message",
"Copy name",
"Copy Name",
"Create New Offer",
"Create Offer",
"Current hotkeys:",
"Current hotkey to add: %s",
"Current Offers",
"Default",
"Description",
"Destructive Behaviour",
"Detail",
"Details",
"Disable Shared Experience",
"Distance Fighting",
"Edit hotkey text:",
"Edit List",
"Edit Text",
"Enable music",
"Enable Shared Experience",
"Enable vertical synchronization",
"Enter Game",
"Enter one name per line.",
"Error",
"Error",
"Excessive Unjustified Player Killing",
"Exclude from private chat",
"Exit",
"Experience",
"Filter list to match your level",
"Filter list to match your vocation",
"Fishing",
"Fist Fighting",
"Follow",
"Fullscreen",
"Game framerate limit: %s",
"General",
"Graphics",
"Graphics Engine:",
"Head",
"Health Info",
"Health Information",
"Hide monsters",
"Hide non-skull players",
"Hide Npcs",
"Hide party members",
"Hide players",
"Hit Points",
"Hold right mouse button to navigate\nScroll mouse middle button to zoom",
"Hotkeys",
"If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character.",
"Ignore capacity",
"Ignore equipped",
"Interface framerate limit: %s",
"Inventory",
"Invite to Party",
"Invite to private chat",
"IP Address Banishment",
"Item Offers",
"It is empty.\n",
"Join %s\'s Party",
"Leave Party",
"Level",
"Limits FPS to 60",
"List of items that you're able to buy",
"List of items that you're able to sell",
"Load",
"Location",
"Logging out...",
"Login",
"Login Error",
"Login Error",
"Logout",
"Look",
"Magic Level",
"Make sure that your client uses\nthe correct game protocol version",
"Mana",
"Manage hotkeys:",
"Market",
"Market Offers",
"Message of the day",
"Message to ",
"Message to %s",
"Minimap",
"Module Manager",
"Module name",
"Move Stackable Item",
"Move up",
"My Offers",
"Name:",
"Name",
"Name Report",
"Name Report + Banishment",
"Name Report + Banishment + Final Warning",
"No",
"No item selected.",
"No Mount",
"No Outfit",
"No statement has been selected.",
"Notation",
"NPC Trade",
"Offer History",
"Offers",
"Offer Type:",
"Ok",
"Okay",
"on %s.\n",
"Open",
"Open a private message channel:",
"Open charlist automatically when starting otclient",
"Open in new window",
"Open new channel",
"Options",
"Particles Manager",
"Pass Leadership to %s",
"Password",
"Pause",
"Piece Price:",
"Please enter a character name:",
"Please, press the key you wish to add onto your hotkeys manager",
"Please Select",
"Please use this dialog to only report bugs. Do not report rule violations here!",
"Please wait",
"Port",
"Preview",
"Price:",
"Primary",
"Protocol",
"Quantity:",
"Quest Log",
"Randomize",
"Randomize characters outfit",
"Reason:",
"Refresh",
"Reject",
"Reload",
"Reload All",
"Remember account and password when starts otclient",
"Remember password",
"Remove",
"Remove %s",
"Report Bug",
"Revoke %s\'s Invitation",
"Rotate",
"Rule Violation",
"Search:",
"Search",
"Secondary",
"Select object",
"Select Outfit",
"Sell",
"Sell Now",
"Sell Offers",
"Send",
"Send automatically",
"Server",
"Server Log",
"Set Outfit",
"Shielding",
"Show all items",
"Show Depot Only",
"Show event messages in console",
"Show frame rate",
"Show info messages in console",
"Show left panel",
"Show levels in console",
"Show private messages in console",
"Show private messages on screen",
"Show status messages in console",
"Show Text",
"Show timestamps in console",
"Show your depot items only",
"Skills",
"Soul",
"Soul Points",
"Stamina",
"Start",
"Statement:",
"Statement Report",
"Statistics",
"Stop Attack",
"Stop Follow",
"%s: (use object)",
"%s: (use object on target)",
"%s: (use object on yourself)",
"%s: (use object with crosshair)",
"Sword Fighting",
"Terminal",
"There is no way.",
"Total Price:",
"Trade",
"Trade with ...",
"Trying to reconnect in %s seconds.",
"Unable to load dat file, please place a valid dat in '%s'",
"Unable to load spr file, please place a valid spr in '%s'",
"Unable to logout.",
"Unload",
"Use",
"Use on target",
"Use on yourself",
"Use with ...",
"Version",
"VIP list",
"VIP List",
"Voc.",
"Waiting List",
"Website",
"Weight:",
"With crosshair",
"Yes",
"You are bleeding",
"You are burning",
"You are cursed",
"You are dazzled",
"You are dead.",
"You are dead",
"You are drowing",
"You are drunk",
"You are electrified",
"You are freezing",
"You are hasted",
"You are hungry",
"You are paralysed",
"You are poisoned",
"You are protected by a magic shield",
"You are strengthened",
"You are within a protection zone",
"You can enter new text.",
"You have %s percent",
"You have %s percent to go",
"You may not logout during a fight",
"You may not logout or enter a protection zone",
"You must enter a comment.",
"You must enter an account name and password.",
"You must enter a valid server address and port.",
"You must select a character to login!",
"Your Capacity:",
"You read the following, written by \n%s\n",
"You read the following, written on %s.\n",
"Your Money:",
}

View File

@ -0,0 +1,246 @@
-- @docclass
UIMoveableTabBar = extends(UIWidget)
-- private functions
local function onTabClick(tab)
tab.tabBar:selectTab(tab)
end
local function updateMargins(tabBar, ignored)
if #tabBar.tabs == 0 then return end
local currentMargin = 0
for i = 1, #tabBar.tabs do
if tabBar.tabs[i] ~= ignored then
if i == 1 then
tabBar.tabs[i]:setMarginLeft(0)
else
tabBar.tabs[i]:setMarginLeft(tabBar.tabSpacing * (i - 1) + currentMargin)
end
end
currentMargin = currentMargin + tabBar.tabs[i]:getWidth()
end
end
local function onTabMousePress(tab, mousePos, mouseButton)
if mouseButton == MouseRightButton then
if tab.menuCallback then tab.menuCallback(tab, mousePos, mouseButton) end
return true
end
end
local function onTabDragEnter(tab)
tab:raise()
tab.tabBar.selected = tab
return true
end
local function onTabDragLeave(tab)
updateMargins(tab.tabBar)
tab.tabBar.selected = nil
return true
end
local function onTabDragMove(tab, mousePos, mouseMoved)
if tab == tab.tabBar.selected then
local newMargin = tab:getMarginLeft() + mouseMoved.x
if newMargin >= -tab.tabBar.tabSpacing and newMargin < tab.tabBar:getWidth() - tab:getWidth() then
tab:setMarginLeft(newMargin)
end
local tabs = tab.tabBar.tabs
local lastMargin = -tab.tabBar.tabSpacing
for i = 1, #tabs do
local nextMargin = tabs[i + 1] and (tabs[i + 1] == tab and (tabs[i]:getMarginLeft() + tabs[i]:getWidth() + tab.tabBar.tabSpacing) or tabs[i + 1]:getMarginLeft()) or tab.tabBar:getWidth()
if (tab:getMarginLeft()+(tabs[i]:getWidth()/2)) >= lastMargin and (tab:getMarginLeft()+(tabs[i]:getWidth()/2)) < nextMargin then
if tabs[i] ~= tab then
local newIndex = table.find(tab.tabBar.tabs, tab.tabBar.tabs[i])
table.remove(tab.tabBar.tabs, table.find(tab.tabBar.tabs, tab))
table.insert(tab.tabBar.tabs, newIndex, tab)
updateMargins(tab.tabBar, tab)
break
else
updateMargins(tab.tabBar, tab)
break
end
end
lastMargin = tab.tabBar.tabs[i]:getMarginLeft() == 0 and -tab.tabBar.tabSpacing or tab.tabBar.tabs[i]:getMarginLeft()
end
end
end
local function tabBlink(tab)
if not tab.blinking then return end
tab:setOn(not tab:isOn())
tab.blinkEvent = scheduleEvent(function() tabBlink(tab) end, 500)
end
-- public functions
function UIMoveableTabBar.create()
local tabbar = UIMoveableTabBar.internalCreate()
tabbar:setFocusable(false)
tabbar.tabs = {}
tabbar.selected = nil -- dragged tab
tabbar.tabSpacing = 5
tabbar.tabsMoveable = false
return tabbar
end
function UIMoveableTabBar:setContentWidget(widget)
self.contentWidget = widget
if #self.tabs > 0 then
self.contentWidget:addChild(self.tabs[1].tabPanel)
end
end
function UIMoveableTabBar:setTabSpacing(tabSpacing)
self.tabSpacing = tabSpacing
updateMargins(self)
end
function UIMoveableTabBar:addTab(text, panel, menuCallback)
if panel == nil then
panel = g_ui.createWidget(self:getStyleName() .. 'Panel')
panel:setId('tabPanel')
end
local tab = g_ui.createWidget(self:getStyleName() .. 'Button', self)
panel.isTab = true
tab.tabPanel = panel
tab.tabBar = self
tab:setId('tab')
tab:setDraggable(self.tabsMoveable)
tab:setText(text)
tab:setWidth(tab:getTextSize().width + tab:getPaddingLeft() + tab:getPaddingRight())
tab.menuCallback = menuCallback or nil
tab.onClick = onTabClick
tab.onMousePress = onTabMousePress
tab.onDragEnter = onTabDragEnter
tab.onDragLeave = onTabDragLeave
tab.onDragMove = onTabDragMove
tab.onDestroy = function() tab.tabPanel:destroy() end
table.insert(self.tabs, tab)
if #self.tabs == 1 then
self:selectTab(tab)
tab:setMarginLeft(0)
else
local newMargin = self.tabSpacing * (#self.tabs - 1)
for i = 1, #self.tabs - 1 do
newMargin = newMargin + self.tabs[i]:getWidth()
end
tab:setMarginLeft(newMargin)
end
return tab
end
-- Additional function to move the tab by lua
function UIMoveableTabBar:moveTab(tab, units)
local index = table.find(self.tabs, tab)
if index == nil then return end
local focus = false
if self.currentTab == tab then
self:selectPrevTab()
focus = true
end
table.remove(self.tabs, index)
local newIndex = math.min(#self.tabs+1, math.max(index + units, 1))
table.insert(self.tabs, newIndex, tab)
if focus then self:selectTab(tab) end
updateMargins(self)
return newIndex
end
function UIMoveableTabBar:onStyleApply(styleName, styleNode)
if styleNode['moveable'] then
self.tabsMoveable = styleNode['moveable']
end
end
function UIMoveableTabBar:removeTab(tab)
local index = table.find(self.tabs, tab)
if index == nil then return end
if self.currentTab == tab then
self:selectPrevTab()
end
table.remove(self.tabs, index)
if tab.blinkEvent then
removeEvent(tab.blinkEvent)
end
tab:destroy()
updateMargins(self)
end
function UIMoveableTabBar:getTab(text)
for k,tab in pairs(self.tabs) do
if tab:getText():lower() == text:lower() then
return tab
end
end
end
function UIMoveableTabBar:selectTab(tab)
if self.currentTab == tab then return end
if self.contentWidget then
local selectedWidget = self.contentWidget:getLastChild()
if selectedWidget and selectedWidget.isTab then
self.contentWidget:removeChild(selectedWidget)
end
self.contentWidget:addChild(tab.tabPanel)
tab.tabPanel:fill('parent')
end
if self.currentTab then
self.currentTab:setChecked(false)
end
signalcall(self.onTabChange, self, tab)
self.currentTab = tab
tab:setChecked(true)
tab:setOn(false)
tab.blinking = false
local parent = tab:getParent()
parent:focusChild(tab, MouseFocusReason)
end
function UIMoveableTabBar:selectNextTab()
if self.currentTab == nil then return end
local index = table.find(self.tabs, self.currentTab)
if index == nil then return end
local nextTab = self.tabs[index + 1] or self.tabs[1]
if not nextTab then return end
self:selectTab(nextTab)
end
function UIMoveableTabBar:selectPrevTab()
if self.currentTab == nil then return end
local index = table.find(self.tabs, self.currentTab)
if index == nil then return end
local prevTab = self.tabs[index - 1] or self.tabs[#self.tabs]
if not prevTab then return end
self:selectTab(prevTab)
end
function UIMoveableTabBar:blinkTab(tab)
if tab:isChecked() or tab.blinking then return end
tab.blinking = true
tabBlink(tab)
end
function UIMoveableTabBar:getTabPanel(tab)
return tab.tabPanel
end
function UIMoveableTabBar:getCurrentTabPanel()
if self.currentTab then
return self.currentTab.tabPanel
end
end
function UIMoveableTabBar:getCurrentTab()
return self.currentTab
end

View File

@ -6,86 +6,24 @@ local function onTabClick(tab)
tab.tabBar:selectTab(tab)
end
local function updateMargins(tabBar, ignored)
if #tabBar.tabs == 0 then return end
local currentMargin = 0
for i = 1, #tabBar.tabs do
if tabBar.tabs[i] ~= ignored then
if i == 1 then
tabBar.tabs[i]:setMarginLeft(0)
else
tabBar.tabs[i]:setMarginLeft(tabBar.tabSpacing * (i - 1) + currentMargin)
local function onTabMouseRelease(tab, mousePos, mouseButton)
if mouseButton == MouseRightButton and tab:containsPoint(mousePos) then
signalcall(tab.tabBar.onTabLeftClick, tab.tabBar, tab)
end
end
currentMargin = currentMargin + tabBar.tabs[i]:getWidth()
end
end
local function onTabMousePress(tab, mousePos, mouseButton)
if mouseButton == MouseRightButton then
if tab.menuCallback then tab.menuCallback(tab, mousePos, mouseButton) end
return true
end
end
local function onTabDragEnter(tab)
tab:raise()
tab.tabBar.selected = tab
return true
end
local function onTabDragLeave(tab)
updateMargins(tab.tabBar)
tab.tabBar.selected = nil
return true
end
local function onTabDragMove(tab, mousePos, mouseMoved)
if tab == tab.tabBar.selected then
local newMargin = tab:getMarginLeft() + mouseMoved.x
if newMargin >= -tab.tabBar.tabSpacing and newMargin < tab.tabBar:getWidth() - tab:getWidth() then
tab:setMarginLeft(newMargin)
end
local tabs = tab.tabBar.tabs
local lastMargin = -tab.tabBar.tabSpacing
for i = 1, #tabs do
local nextMargin = tabs[i + 1] and (tabs[i + 1] == tab and (tabs[i]:getMarginLeft() + tabs[i]:getWidth() + tab.tabBar.tabSpacing) or tabs[i + 1]:getMarginLeft()) or tab.tabBar:getWidth()
if (tab:getMarginLeft()+(tabs[i]:getWidth()/2)) >= lastMargin and (tab:getMarginLeft()+(tabs[i]:getWidth()/2)) < nextMargin then
if tabs[i] ~= tab then
local newIndex = table.find(tab.tabBar.tabs, tab.tabBar.tabs[i])
table.remove(tab.tabBar.tabs, table.find(tab.tabBar.tabs, tab))
table.insert(tab.tabBar.tabs, newIndex, tab)
updateMargins(tab.tabBar, tab)
break
else
updateMargins(tab.tabBar, tab)
break
end
end
lastMargin = tab.tabBar.tabs[i]:getMarginLeft() == 0 and -tab.tabBar.tabSpacing or tab.tabBar.tabs[i]:getMarginLeft()
end
end
end
local function tabBlink(tab)
if not tab.blinking then return end
tab:setOn(not tab:isOn())
tab.blinkEvent = scheduleEvent(function() tabBlink(tab) end, 500)
end
-- public functions
function UITabBar.create()
local tabbar = UITabBar.internalCreate()
tabbar:setFocusable(false)
tabbar.tabs = {}
tabbar.selected = nil -- dragged tab
tabbar.tabSpacing = 5
tabbar.tabsMoveable = false
return tabbar
end
function UITabBar:onSetup()
self.buttonsPanel = self:getChildById('buttonsPanel')
end
function UITabBar:setContentWidget(widget)
self.contentWidget = widget
if #self.tabs > 0 then
@ -93,74 +31,35 @@ function UITabBar:setContentWidget(widget)
end
end
function UITabBar:setTabSpacing(tabSpacing)
self.tabSpacing = tabSpacing
updateMargins(self)
end
function UITabBar:addTab(text, panel, menuCallback)
function UITabBar:addTab(text, panel, icon)
if panel == nil then
panel = g_ui.createWidget(self:getStyleName() .. 'Panel')
panel:setId('tabPanel')
end
local tab = g_ui.createWidget(self:getStyleName() .. 'Button', self)
local tab = g_ui.createWidget(self:getStyleName() .. 'Button', self.buttonsPanel)
panel.isTab = true
tab.tabPanel = panel
tab.tabBar = self
tab:setId('tab')
tab:setDraggable(self.tabsMoveable)
tab:setText(text)
tab:setWidth(tab:getTextSize().width + tab:getPaddingLeft() + tab:getPaddingRight())
tab.menuCallback = menuCallback or nil
tab.onClick = onTabClick
tab.onMousePress = onTabMousePress
tab.onDragEnter = onTabDragEnter
tab.onDragLeave = onTabDragLeave
tab.onDragMove = onTabDragMove
tab.onMouseRelease = onTabMouseRelease
tab.onDestroy = function() tab.tabPanel:destroy() end
table.insert(self.tabs, tab)
if #self.tabs == 1 then
self:selectTab(tab)
tab:setMarginLeft(0)
else
local newMargin = self.tabSpacing * (#self.tabs - 1)
for i = 1, #self.tabs - 1 do
newMargin = newMargin + self.tabs[i]:getWidth()
end
tab:setMarginLeft(newMargin)
end
local tabStyle = {}
tabStyle['icon-source'] = icon
tab:mergeStyle(tabStyle)
return tab
end
-- Additional function to move the tab by lua
function UITabBar:moveTab(tab, units)
local index = table.find(self.tabs, tab)
if index == nil then return end
local focus = false
if self.currentTab == tab then
self:selectPrevTab()
focus = true
end
table.remove(self.tabs, index)
local newIndex = math.min(#self.tabs+1, math.max(index + units, 1))
table.insert(self.tabs, newIndex, tab)
if focus then self:selectTab(tab) end
updateMargins(self)
return newIndex
end
function UITabBar:onStyleApply(styleName, styleNode)
if styleNode['moveable'] then
self.tabsMoveable = styleNode['moveable']
end
end
function UITabBar:removeTab(tab)
local index = table.find(self.tabs, tab)
if index == nil then return end
@ -168,11 +67,7 @@ function UITabBar:removeTab(tab)
self:selectPrevTab()
end
table.remove(self.tabs, index)
if tab.blinkEvent then
removeEvent(tab.blinkEvent)
end
tab:destroy()
updateMargins(self)
end
function UITabBar:getTab(text)
@ -201,7 +96,6 @@ function UITabBar:selectTab(tab)
self.currentTab = tab
tab:setChecked(true)
tab:setOn(false)
tab.blinking = false
local parent = tab:getParent()
parent:focusChild(tab, MouseFocusReason)
@ -225,12 +119,6 @@ function UITabBar:selectPrevTab()
self:selectTab(prevTab)
end
function UITabBar:blinkTab(tab)
if tab:isChecked() or tab.blinking then return end
tab.blinking = true
tabBlink(tab)
end
function UITabBar:getTabPanel(tab)
return tab.tabPanel
end

View File

@ -97,29 +97,25 @@ function onMiniWindowClose()
end
function checkCreatures()
removeAllCreatures()
local spectators = {}
local player = g_game.getLocalPlayer()
if g_game.isOnline() then
creatures = g_map.getSpectators(player:getPosition(), false)
for i, creature in ipairs(creatures) do
if creature ~= player and doCreatureFitFilters(creature) then
if not hasCreature(creature) then
addCreature(creature)
table.insert(spectators, creature)
end
end
end
local toRemove = {}
for i, b in pairs(battleButtonsByCreaturesList) do
if (not table.contains(creatures, b.creature)) or (not doCreatureFitFilters(b.creature)) then
table.insert(toRemove, b.creature)
end
end
for i, creature in pairs(toRemove) do
removeCreature(creature)
end
for i, v in pairs(spectators) do
addCreature(v)
end
end
function doCreatureFitFilters(creature)
local localPlayer = g_game.getLocalPlayer()
if creature == localPlayer then
@ -129,11 +125,7 @@ function doCreatureFitFilters(creature)
local pos = creature:getPosition()
if not pos then return false end
if pos.z ~= localPlayer:getPosition().z or not localPlayer:hasSight(pos) then
return false
end
if not creature:canBeSeen() then return false end
if pos.z ~= localPlayer:getPosition().z or not creature:canBeSeen() then return false end
local hidePlayers = hidePlayersButton:isChecked()
local hideNPCs = hideNPCsButton:isChecked()
@ -165,24 +157,32 @@ end
function onCreaturePositionChange(creature, newPos, oldPos)
if creature:isLocalPlayer() then
if oldPos and newPos and newPos.z ~= oldPos.z then
checkCreatures()
else
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
addCreature(creatureButton.creature)
end
end
else
local has = hasCreature(creature)
local fit = doCreatureFitFilters(creature)
if has and not fit then
removeCreature(creature)
elseif not has and fit then
elseif fit then
addCreature(creature)
end
end
end
function onCreatureOutfitChange(creature, outfit, oldOutfit)
if not creature:canBeSeen() then
removeCreature(creature)
elseif doCreatureFitFilters(creature) then
removeCreature(creature)
if hasCreature(creature) then
if doCreatureFitFilters(creature) then
addCreature(creature)
else
removeCreature(creature)
end
end
end
@ -223,6 +223,9 @@ function addCreature(creature)
else
battleButton:setLifeBarPercent(creature:getHealthPercent())
end
local localPlayer = g_game.getLocalPlayer()
battleButton:setVisible(localPlayer:hasSight(creature:getPosition()) and creature:canBeSeen())
end
function removeAllCreatures()

View File

@ -18,8 +18,8 @@ ConsolePhantomLabel < UILabel
selection-color: #111416
selection-background-color: #999999
ConsoleTabBar < TabBar
ConsoleTabBarPanel < TabBarPanel
ConsoleTabBar < MoveableTabBar
ConsoleTabBarPanel < MoveableTabBarPanel
id: consoleTab
ScrollablePanel
@ -69,7 +69,7 @@ ConsoleTabBarPanel < TabBarPanel
step: 14
pixels-scroll: true
ConsoleTabBarButton < TabBarButton
ConsoleTabBarButton < MoveableTabBarButton
height: 28
padding: 15

View File

@ -64,11 +64,6 @@ function bindKeys()
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyDown('Up', function() smartWalk(North) end, gameRootPanel)
g_keyboard.bindKeyDown('Right', function() smartWalk(East) end, gameRootPanel)
g_keyboard.bindKeyDown('Down', function() smartWalk(South) end, gameRootPanel)
g_keyboard.bindKeyDown('Left', function() smartWalk(West) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
@ -91,8 +86,8 @@ function bindKeys()
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+.', toggleAspectRatio, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+N', function() gameMapPanel:setDrawTexts(not gameMapPanel:isDrawingTexts()) end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+.', toggleAlternativeView, gameRootPanel)
end
function terminate()
@ -324,6 +319,7 @@ function onTradeWith(clickedWidget, mousePosition)
end
function startUseWith(thing)
if not thing then return end
selectedType = 'use'
selectedThing = thing
mouseGrabberWidget:grabMouse()
@ -497,6 +493,7 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
return true
else
g_game.use(useThing)
return true
end
return true
elseif creatureThing and keyboardModifiers == KeyboardAltModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
@ -643,3 +640,38 @@ function onLeftPanelVisibilityChange(leftPanel, visible)
end
end
end
function toggleAlternativeView()
if gameMapPanel:isKeepAspectRatioEnabled() then
gameMapPanel:setKeepAspectRatio(false)
gameMapPanel:setZoom(14)
gameMapPanel:fill('parent')
gameRootPanel:fill('parent')
gameLeftPanel:setImageColor('alpha')
gameRightPanel:setImageColor('alpha')
gameLeftPanel:setMarginTop(36)
gameRightPanel:setMarginTop(36)
gameLeftPanel:setOn(true)
gameLeftPanel:setVisible(true)
gameRightPanel:setOn(true)
gameBottomPanel:setImageColor('#00000099')
modules.client_topmenu.getTopMenu():setImageColor('#ffffff66')
g_game.changeMapAwareRange(24, 20)
else
gameMapPanel:setKeepAspectRatio(true)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
gameMapPanel:addAnchor(AnchorLeft, 'gameLeftPanel', AnchorRight)
gameMapPanel:addAnchor(AnchorRight, 'gameRightPanel', AnchorLeft)
gameMapPanel:addAnchor(AnchorBottom, 'gameBottomPanel', AnchorTop)
gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom)
gameLeftPanel:setOn(false)
gameLeftPanel:setVisible(false)
gameLeftPanel:setImageColor('white')
gameRightPanel:setImageColor('white')
gameLeftPanel:setMarginTop(0)
gameRightPanel:setMarginTop(0)
gameBottomPanel:setImageColor('white')
modules.client_topmenu.getTopMenu():setImageColor('white')
g_game.changeMapAwareRange(18, 14)
end
end

View File

@ -1,4 +1,4 @@
filename = 'Tibia'
filename = nil
loaded = false
function init()
@ -19,8 +19,15 @@ end
function load()
local version = g_game.getProtocolVersion()
local datPath = resolvepath(version .. '/' .. filename .. '.dat')
local sprPath = resolvepath(version .. '/' .. filename .. '.spr')
local datPath, sprPath
if filename then
datPath = resolvepath('/things/' .. filename)
sprPath = resolvepath('/things/' .. filename)
else
datPath = resolvepath('/things/' .. version .. '/Tibia')
sprPath = resolvepath('/things/' .. version .. '/Tibia')
end
local errorMessage = ''
if not g_things.loadDat(datPath) then

View File

@ -0,0 +1,8 @@
Module
name: game_things
description: Contains things spr and dat
reloadable: false
sandboxed: true
scripts: [things]
@onLoad: init()
@onUnload: terminate()

View File

@ -1,8 +0,0 @@
Module
name: game_tibiafiles
description: Contains tibia spr and dat
reloadable: false
sandboxed: true
scripts: [tibiafiles]
@onLoad: init()
@onUnload: terminate()

View File

@ -10,7 +10,7 @@ function init()
g_keyboard.bindKeyDown('Ctrl+P', toggle)
vipButton = modules.client_topmenu.addRightGameToggleButton('vipListButton', tr('VIP list') .. ' (Ctrl+P)', '/images/topbuttons/viplist', toggle)
vipButton = modules.client_topmenu.addRightGameToggleButton('vipListButton', tr('VIP List') .. ' (Ctrl+P)', '/images/topbuttons/viplist', toggle)
vipButton:setOn(true)
vipWindow = g_ui.loadUI('viplist', modules.game_interface.getRightPanel())

View File

@ -191,4 +191,10 @@ VipState = {
Pending = 2
}
ExtendedIds = {
Activate = 0,
Locale = 1,
Ping = 2
}
-- @}

View File

@ -14,9 +14,11 @@ function g_game.chooseRsa(host)
g_game.setCustomOs(OsTypes.Linux)
end
else
g_game.setRsa(OTSERV_RSA)
if currentRsa == CIPSOFT_RSA then
g_game.setCustomOs(-1)
end
g_game.setRsa(OTSERV_RSA)
end
end
function g_game.setRsa(rsa)

View File

@ -5,7 +5,7 @@ Module
website: www.otclient.info
dependencies:
- game_tibiafiles
- game_things
@onLoad: |
dofile 'const'

View File

@ -28,6 +28,7 @@ end
function ProtocolLogin:sendLoginPacket()
local msg = OutputMessage.create()
msg:addU8(ClientOpcodes.ClientEnterAccount)
msg:addU16(g_game.getOs())

View File

@ -166,7 +166,7 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
}
if(house && item->isMoveable()) {
g_logger.warning(stdext::format("Movable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
g_logger.warning(stdext::format("Moveable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
item.reset();
}

View File

@ -79,13 +79,13 @@ void MinimapBlock::update()
void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile)
{
if(!(m_tiles[getTileIndex(x,y)] == tile)) {
m_tiles[getTileIndex(x,y)] = tile;
if(tile.color != 0)
m_shouldDraw = true;
if(m_tiles[getTileIndex(x,y)].color != tile.color)
m_mustUpdate = true;
}
m_tiles[getTileIndex(x,y)] = tile;
}
void Minimap::init()

View File

@ -107,6 +107,8 @@ public:
void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation);
void sendRequestItemInfo(int itemId, int subType, int index);
void sendAnswerModalDialog(int dialog, int button, int choice);
// otclient only
void sendChangeMapAwareRange(int xrange, int yrange);
protected: