BEAWARE all game functionality is disabled with this commit for a while

* rework client modules
* hide main window when loading
* remake top menu functions
* rework modules autoload
* improve path resolving for otml and lua
* move core_widgets to core_lib
* fix tooltip issues
* split some styles
* add bit32 lua library
* fix assert issues
* fix compilation on linux 32 systems
* rework gcc compile options
* renable and fix some warnings
* remove unused constants
* speedup sprite cache
* move UIGame to lua (not funcional yet)
* fix a lot of issues in x11 window
* fix crash handler
* add some warnings do uiwidget
and much more...
This commit is contained in:
Eduardo Bart
2012-02-20 00:27:08 -02:00
parent 96358b317d
commit e03bf33f58
201 changed files with 1443 additions and 707 deletions

View File

@@ -0,0 +1,350 @@
Battle = {}
--TODO
--onCreatureAppears onCreatureHealthChange onCreatureDisappears
--reloadable/disconnects
-- private variables
local battleWindow
local battleButton
local battlePanel
local lastBattleButtonSwitched
local checkCreaturesEvent
local battleButtonsByCreaturesList = {}
local mouseWidget
local hidePlayersButton
local hideNPCsButton
local hideMonstersButton
local hideSkullsButton
local hidePartyButton
local battleButtonColors = {
onIdle = {notHovered = '#888888', hovered = '#FFFFFF' },
onTargeted = {notHovered = '#FF0000', hovered = '#FF8888' },
onFollowed = {notHovered = '#00FF00', hovered = '#88FF88' }
}
local lifeBarColors = {} --Must be sorted by percentAbose
table.insert(lifeBarColors, {percentAbove = 92, color = '#00BC00' } )
table.insert(lifeBarColors, {percentAbove = 60, color = '#50A150' } )
table.insert(lifeBarColors, {percentAbove = 30, color = '#A1A100' } )
table.insert(lifeBarColors, {percentAbove = 8, color = '#3C2727' } )
table.insert(lifeBarColors, {percentAbove = 3, color = '#3C0000' } )
table.insert(lifeBarColors, {percentAbove = -1, color = '#4F0000' } )
-- public functions
function Battle.create()
battleWindow = displayUI('battle.otui', g_game.gameRightPanel)
battleWindow:hide()
battleButton = TopMenu.addGameButton('battleButton', 'Battle (Ctrl+B)', '/game_battle/battle.png', Battle.toggle)
Keyboard.bindKeyDown('Ctrl+B', Battle.toggle)
battlePannel = battleWindow:getChildById('battlePanel')
hidePlayersButton = battleWindow:getChildById('hidePlayers')
hideNPCsButton = battleWindow:getChildById('hideNPCs')
hideMonstersButton = battleWindow:getChildById('hideMonsters')
hideSkullsButton = battleWindow:getChildById('hideSkulls')
hidePartyButton = battleWindow:getChildById('hideParty')
mouseWidget = createWidget('UIButton')
mouseWidget:setVisible(false)
mouseWidget:setFocusable(false)
connect(Creature, { onSkullChange = Battle.checkCreatureSkull,
onEmblemChange = Battle.checkCreatureEmblem } )
connect(g_game, { onAttackingCreatureChange = Battle.onAttack,
onFollowingCreatureChange = Battle.onFollow } )
addEvent(Battle.addAllCreatures)
checkCreaturesEvent = scheduleEvent(Battle.checkCreatures, 200)
end
function Battle.destroy()
Keyboard.unbindKeyDown('Ctrl+B')
battlePannel = nil
lastBattleButtonTargeted = nil
lastBattleButtonFollowed = nil
battleButtonsByCreaturesList = {}
removeEvent(checkCreaturesEvent)
hidePlayersButton = nil
hideNPCsButton = nil
hideMonstersButton = nil
hideSkullsButton = nil
hidePartyButton = nil
checkCreaturesEvent = nil
battleButton:destroy()
battleButton = nil
battleWindow:destroy()
battleWindow = nil
disconnect(Creature, { onSkullChange = Battle.checkCreatureSkull,
onEmblemChange = Battle.checkCreatureEmblem } )
disconnect(g_game, { onAttackingCreatureChange = Battle.onAttack } )
end
function Battle.toggle()
local visible = not battleWindow:isExplicitlyVisible()
battleWindow:setVisible(visible)
battleButton:setOn(visible)
end
function Battle.addAllCreatures()
local spectators = {}
local player = g_game.getLocalPlayer()
if player then
creatures = g_map.getSpectators(player:getPosition(), false)
for i, creature in ipairs(creatures) do
if creature ~= player and Battle.doCreatureFitFilters(creature) then
table.insert(spectators, creature)
end
end
end
for i, v in pairs(spectators) do
Battle.addCreature(v)
end
end
function Battle.doCreatureFitFilters(creature)
local hidePlayers = hidePlayersButton:isChecked()
local hideNPCs = hideNPCsButton:isChecked()
local hideMonsters = hideMonstersButton:isChecked()
local hideSkulls = hideSkullsButton:isChecked()
local hideParty = hidePartyButton:isChecked()
if hidePlayers and not creature:asMonster() and not creature:asNpc() then
return false
elseif hideNPCs and creature:asNpc() then
return false
elseif hideMonsters and creature:asMonster() then
return false
elseif hideSkulls and creature:getSkull() == SkullNone then
return false
elseif hideParty and creature:getShield() > ShieldWhiteBlue then
return false
end
return true
end
function Battle.checkCreatures()
local player = g_game.getLocalPlayer()
if player then
local spectators = {}
-- reloading list of spectators
local creaturesAppeared = {}
creatures = g_map.getSpectators(player:getPosition(), false)
for i, creature in ipairs(creatures) do
if creature ~= player and Battle.doCreatureFitFilters(creature) then
-- searching for creatures that appeared on battle list
local battleButton = battleButtonsByCreaturesList[creature:getId()]
if battleButton == nil then
table.insert(creaturesAppeared, creature)
else
Battle.setLifeBarPercent(battleButton, creature:getHealthPercent())
end
spectators[creature:getId()] = creature
end
end
for i, v in pairs(creaturesAppeared) do
Battle.addCreature(v)
end
-- searching for creatures that disappeared from battle list
local creaturesDisappeared = {}
for i, creature in pairs(battleButtonsByCreaturesList) do
if spectators[creature.creatureId] == nil then
table.insert(creaturesDisappeared, creature.creature)
end
end
for i, v in pairs(creaturesDisappeared) do
Battle.removeCreature(v)
end
end
checkCreaturesEvent = scheduleEvent(Battle.checkCreatures, 500)
end
function Battle.addCreature(creature)
local creatureId = creature:getId()
if battleButtonsByCreaturesList[creatureId] == nil then
local battleButton = displayUI('battleButton.otui', battlePanne)
local creatureWidget = battleButton:getChildById('creature')
local labelWidget = battleButton:getChildById('label')
local lifeBarWidget = battleButton:getChildById('lifeBar')
battleButton:setId('BattleButton_' .. creature:getName():gsub('%s','_'))
battleButton.creatureId = creatureId
battleButton.creature = creature
battleButton.isHovered = false
battleButton.isTarget = false
battleButton.isFollowed = false
labelWidget:setText(creature:getName())
creatureWidget:setCreature(creature)
Battle.setLifeBarPercent(battleButton, creature:getHealthPercent())
battleButtonsByCreaturesList[creatureId] = battleButton
Battle.checkCreatureSkull(battleButton.creature)
Battle.checkCreatureEmblem(battleButton.creature)
end
end
function Battle.checkCreatureSkull(creature, skullId)
local battleButton = battleButtonsByCreaturesList[creature:getId()]
if battleButton then
local skullWidget = battleButton:getChildById('skull')
local labelWidget = battleButton:getChildById('label')
local creature = battleButton.creature
if creature:getSkull() ~= SkullNone then
skullWidget:setWidth(skullWidget:getHeight())
local imagePath = getSkullImagePath(creature:getSkull())
skullWidget:setImageSource('/game/' .. imagePath)
labelWidget:setMarginLeft(5)
else
skullWidget:setWidth(0)
if creature:getEmblem() == EmblemNone then
labelWidget:setMarginLeft(2)
end
end
end
end
function Battle.checkCreatureEmblem(creature, emblemId)
local battleButton = battleButtonsByCreaturesList[creature:getId()]
if battleButton then
local emblemId = emblemId or creature:getEmblem()
local emblemWidget = battleButton:getChildById('emblem')
local labelWidget = battleButton:getChildById('label')
local creature = battleButton.creature
if emblemId ~= EmblemNone then
emblemWidget:setWidth(emblemWidget:getHeight())
local imagePath = getEmblemImagePath(emblemId)
emblemWidget:setImageSource('/game/' .. imagePath)
emblemWidget:setMarginLeft(5)
labelWidget:setMarginLeft(5)
else
emblemWidget:setWidth(0)
emblemWidget:setMarginLeft(0)
if creature:getSkull() == SkullNone then
labelWidget:setMarginLeft(2)
end
end
end
end
function Battle.onMouseRelease(self, mousePosition, mouseButton)
if mouseButton == MouseRightButton then
g_game.createThingMenu(mousePosition, nil, nil, self.creature)
return true
elseif mouseButton == MouseLeftButton then
local modifiers = g_window.getKeyboardModifiers()
if modifiers == KeyboardShiftModifier then
g_game.look(self.creature)
else
if self.isTarget then
g_game.cancelAttack()
else
g_game.attack(self.creature)
end
end
return true
end
end
function Battle.removeCreature(creature)
local creatureId = creature:getId()
if battleButtonsByCreaturesList[creatureId] ~= nil then
if lastBattleButtonSwitched == battleButtonsByCreaturesList[creatureId] then
lastBattleButtonSwitched = nil
end
battleButtonsByCreaturesList[creatureId].creature:hideStaticSquare()
battleButtonsByCreaturesList[creatureId]:destroy()
battleButtonsByCreaturesList[creatureId] = nil
end
end
function Battle.setLifeBarPercent(battleButton, percent)
local lifeBarWidget = battleButton:getChildById('lifeBar')
lifeBarWidget:setPercent(percent)
local color
for i, v in pairs(lifeBarColors) do
if percent > v.percentAbove then
color = v.color
break
end
end
lifeBarWidget:setBackgroundColor(color)
end
function Battle.onbattlePannelHoverChange(widget, hovered)
if widget.isBattleButton then
widget.isHovered = hovered
Battle.checkBattleButton(widget)
end
end
function Battle.onAttack(creature)
local battleButton = creature and battleButtonsByCreaturesList[creature:getId()] or lastBattleButtonSwitched
if battleButton then
battleButton.isTarget = creature and true or false
Battle.checkBattleButton(battleButton)
end
end
function Battle.onFollow(creature)
local battleButton = creature and battleButtonsByCreaturesList[creature:getId()] or lastBattleButtonSwitched
if battleButton then
battleButton.isFollowed = creature and true or false
Battle.checkBattleButton(battleButton)
end
end
function Battle.checkBattleButton(battleButton)
local color = battleButtonColors.onIdle
if battleButton.isTarget then
color = battleButtonColors.onTargeted
elseif battleButton.isFollowed then
color = battleButtonColors.onFollowed
end
color = battleButton.isHovered and color.hovered or color.notHovered
if battleButton.isHovered or battleButton.isTarget or battleButton.isFollowed then
battleButton.creature:showStaticSquare(color)
battleButton:getChildById('creature'):setBorderWidth(1)
battleButton:getChildById('creature'):setBorderColor(color)
battleButton:getChildById('label'):setColor(color)
else
battleButton.creature:hideStaticSquare()
battleButton:getChildById('creature'):setBorderWidth(0)
battleButton:getChildById('label'):setColor(color)
end
if battleButton.isTarget or battleButton.isFollowed then
if lastBattleButtonSwitched and lastBattleButtonSwitched ~= battleButton then
lastBattleButtonSwitched.isTarget = false
lastBattleButtonSwitched.isFollowed = false
Battle.checkBattleButton(lastBattleButtonSwitched)
end
lastBattleButtonSwitched = battleButton
end
end
connect(g_game, { onGameStart = Battle.create,
onGameEnd = Battle.destroy } )

View File

@@ -0,0 +1,7 @@
Module
name: game_battle
description: Manage battle window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'battle'

View File

@@ -0,0 +1,91 @@
BattleIcon < UICheckBox
size: 20 20
image-color: white
image-rect: 0 0 20 20
$hover !disabled:
color: #cccccc
$!checked:
image-clip: 0 0 20 20
$hover !checked:
image-clip: 0 40 20 20
$checked:
image-clip: 0 20 20 20
$hover checked:
image-clip: 0 60 20 20
$disabled:
image-color: #ffffff88
BattlePlayers < BattleIcon
image-source: /game_battle/battle_players.png
BattleNPCs < BattleIcon
image-source: /game_battle/battle_npcs.png
BattleMonsters < BattleIcon
image-source: /game_battle/battle_monsters.png
BattleSkulls < BattleIcon
image-source: /game_battle/battle_skulls.png
BattleParty < BattleIcon
image-source: /game_battle/battle_party.png
MiniWindow
id: battleWindow
text: Battle
height: 250
BattlePlayers
id: hidePlayers
tooltip: Hide players
anchors.top: parent.top
anchors.right: next.left
margin-right: 5
BattleNPCs
id: hideNPCs
tooltip: Hide Npc's
anchors.top: parent.top
anchors.right: next.left
margin-right: 5
BattleMonsters
id: hideMonsters
tooltip: Hide monsters
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
BattleSkulls
id: hideSkulls
tooltip: Hide non-skull players
anchors.top: prev.top
anchors.left: prev.right
margin-left: 5
BattleParty
id: hideParty
tooltip: Hide party members
anchors.top: prev.top
anchors.left: prev.right
margin-left: 5
HorizontalSeparator
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
Panel
id: battlePanel
anchors.fill: parent
anchors.top: prev.bottom
margin-top: 5
layout: verticalBox

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,54 @@
BattleButton < UIButton
BattleButton
height: 20
margin-top: 5
fixed-size: true
&onHoverChange: Battle.onbattlePannelHoverChange
&onMouseRelease: Battle.onMouseRelease
&isBattleButton: true
UICreature
id: creature
size: 20 20
anchors.left: parent.left
anchors.top: parent.top
phantom: true
UIWidget
id: spacer
width: 5
anchors.left: creature.right
anchors.top: creature.top
phantom: true
UIWidget
id: skull
height: 11
anchors.left: spacer.right
anchors.top: spacer.top
phantom: true
UIWidget
id: emblem
height: 11
anchors.left: skull.right
anchors.top: creature.top
phantom: true
Label
id: label
anchors.left: emblem.right
anchors.top: creature.top
color: #888888
margin-left: 2
phantom: true
ProgressBar
id: lifeBar
height: 5
anchors.left: spacer.right
anchors.right: parent.right
anchors.top: label.bottom
margin-top: 2
phantom: true

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,132 @@
CombatControls = {}
-- private variables
local combatControlsButton
local combatControlsWindow
local fightOffensiveBox
local fightBalancedBox
local fightDefensiveBox
local chaseModeButton
local safeFightButton
local fightModeRadioGroup
-- private functions
local function onFightModeChange(self, selectedFightButton)
if selectedFightButton == nil then return end
local buttonId = selectedFightButton:getId()
local fightMode
if buttonId == 'fightOffensiveBox' then
fightMode = FightOffensive
elseif buttonId == 'fightBalancedBox' then
fightMode = FightBalanced
else
fightMode = FightDefensive
end
if g_game.getFightMode ~= fightMode then
g_game.setFightMode(fightMode)
end
end
local function onChaseModeChange(self, checked)
local chaseMode
if checked then
chaseMode = ChaseOpponent
else
chaseMode = DontChase
end
if g_game.getChaseMode() ~= chaseMode then
g_game.setChaseMode(chaseMode)
end
end
local function onSafeFightChange(self, checked)
local safeFight = not checked
if g_game.isSafeFight() ~= safeFight then
g_game.setSafeFight(not checked)
end
end
-- public functions
function CombatControls.init()
combatControlsButton = TopMenu.addGameButton('combatControlsButton', 'Combat Controls', 'combatcontrols.png', CombatControls.toggle)
combatControlsButton:setOn(true)
combatControlsWindow = loadUI('combatcontrols.otui')
fightOffensiveBox = combatControlsWindow:getChildById('fightOffensiveBox')
fightBalancedBox = combatControlsWindow:getChildById('fightBalancedBox')
fightDefensiveBox = combatControlsWindow:getChildById('fightDefensiveBox')
chaseModeButton = combatControlsWindow:getChildById('chaseModeBox')
safeFightButton = combatControlsWindow:getChildById('safeFightBox')
fightModeRadioGroup = RadioGroup.create()
fightModeRadioGroup:addWidget(fightOffensiveBox)
fightModeRadioGroup:addWidget(fightBalancedBox)
fightModeRadioGroup:addWidget(fightDefensiveBox)
connect(fightModeRadioGroup, { onSelectionChange = onFightModeChange })
connect(chaseModeButton, { onCheckChange = onChaseModeChange })
connect(safeFightButton, { onCheckChange = onSafeFightChange })
connect(g_game, { onGameStart = CombatControls.online })
connect(g_game, { onGameEnd = CombatControls.offline })
if g_game.isOnline() then
CombatControls.online()
end
end
function CombatControls.terminate()
if g_game.isOnline() then
CombatControls.offline()
end
fightModeRadioGroup:destroy()
fightModeRadioGroup = nil
fightOffensiveBox = nil
fightBalancedBox = nil
fightDefensiveBox = nil
chaseModeButton = nil
safeFightButton = nil
combatControlsButton:destroy()
combatControlsButton = nil
combatControlsWindow:destroy()
combatControlsWindow = nil
disconnect(g_game, { onGameStart = CombatControls.online })
disconnect(g_game, { onGameEnd = CombatControls.offline })
CombatControls = nil
end
function CombatControls.online()
g_game.gameRightPanel:addChild(combatControlsWindow)
combatControlsWindow:setVisible(combatControlsButton:isOn())
local fightMode = g_game.getFightMode()
if fightMode == FightOffensive then
fightModeRadioGroup:selectWidget(fightOffensiveBox)
elseif fightMode == FightBalanced then
fightModeRadioGroup:selectWidget(fightBalancedBox)
else
fightModeRadioGroup:selectWidget(fightDefensiveBox)
end
local chaseMode = g_game.getChaseMode()
chaseModeButton:setChecked(chaseMode == ChaseOpponent)
local safeFight = g_game.isSafeFight()
safeFightButton:setChecked(not safeFight)
end
function CombatControls.offline()
g_game.gameRightPanel:removeChild(combatControlsWindow)
end
function CombatControls.toggle()
local visible = not combatControlsWindow:isExplicitlyVisible()
combatControlsWindow:setVisible(visible)
combatControlsButton:setOn(visible)
end

View File

@@ -0,0 +1,12 @@
Module
name: game_combatcontrols
description: Combat controls window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'combatcontrols'
CombatControls.init()
onUnload: |
CombatControls.terminate()

View File

@@ -0,0 +1,43 @@
CombatBox < UICheckBox
size: 20 20
image-clip: 0 0 20 20
anchors.top: parent.top
margin-left: 5
margin-right: 5
$checked:
image-clip: 0 20 20 20
FightOffensiveBox < CombatBox
image-source: /game_combatcontrols/icons/fightoffensive.png
FightBalancedBox < CombatBox
image-source: /game_combatcontrols/icons/fightbalanced.png
FightDefensiveBox < CombatBox
image-source: /game_combatcontrols/icons/fightdefensive.png
ChaseModeBox < CombatBox
image-source: /game_combatcontrols/icons/chasemode.png
SafeFightBox < CombatBox
image-source: /game_combatcontrols/icons/safefight.png
UIWindow
width: 130
height: 30
margin-top: 10
margin-left: 6
margin-right: 6
FightOffensiveBox
id: fightOffensiveBox
anchors.right: next.left
FightBalancedBox
id: fightBalancedBox
anchors.right: next.left
FightDefensiveBox
id: fightDefensiveBox
anchors.horizontalCenter: parent.horizontalCenter
ChaseModeBox
id: chaseModeBox
anchors.left: prev.right
SafeFightBox
id: safeFightBox
anchors.left: prev.right

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,56 @@
ChannelListLabel < Label
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
$focus:
background-color: #ffffff22
color: #ffffff
MainWindow
id: channelsWindow
text: Channels
size: 250 238
@onEscape: self:destroy()
TextList
id: channelList
anchors.fill: parent
anchors.bottom: next.top
margin-bottom: 10
padding: 1
focusable: false
Label
id: openPrivateChannelWithLabel
text: Open a private message channel:
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
text-align: center
margin-bottom: 2
LineEdit
id: openPrivateChannelWith
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin-bottom: 10
Button
id: buttonOpen
text: Open
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
@onClick: self:getParent():onEnter()
Button
id: buttonCancel
text: Cancel
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: self:getParent():destroy()

View File

@@ -0,0 +1,373 @@
Console = {}
-- private variables
local SpeakTypesSettings = {
say = { speakType = SpeakSay, color = '#FFFF00' },
whisper = { speakType = SpeakWhisper, color = '#FFFF00' },
yell = { speakType = SpeakYell, color = '#FFFF00' },
broadcast = { speakType = SpeakBroadcast, color = '#F55E5E' },
private = { speakType = SpeakPrivate, color = '#5FF7F7', private = true },
privateRed = { speakType = SpeakPrivateRed, color = '#F55E5E', private = true },
privatePlayerToPlayer = { speakType = SpeakPrivate, color = '#9F9DFD', private = true },
privatePlayerToNpc = { speakType = SpeakPrivatePlayerToNpc, color = '#9F9DFD', private = true, npcChat = true },
privateNpcToPlayer = { speakType = SpeakPrivateNpcToPlayer, color = '#5FF7F7', private = true, npcChat = true },
channelYellow = { speakType = SpeakChannelYellow, color = '#FFFF00' },
channelWhite = { speakType = SpeakChannelWhite, color = '#FFFFFF' },
channelRed = { speakType = SpeakChannelRed, color = '#F55E5E' },
channelOrange = { speakType = SpeakChannelOrange, color = '#FE6500' },
monsterSay = { speakType = SpeakMonsterSay, color = '#FE6500', hideInConsole = true},
monsterYell = { speakType = SpeakMonsterYell, color = '#FE6500', hideInConsole = true},
}
local SpeakTypes = {
[SpeakSay] = SpeakTypesSettings.say,
[SpeakWhisper] = SpeakTypesSettings.whisper,
[SpeakYell] = SpeakTypesSettings.yell,
[SpeakBroadcast] = SpeakTypesSettings.broadcast,
[SpeakPrivate] = SpeakTypesSettings.private,
[SpeakPrivateRed] = SpeakTypesSettings.privateRed,
[SpeakPrivatePlayerToNpc] = SpeakTypesSettings.privatePlayerToNpc,
[SpeakPrivateNpcToPlayer] = SpeakTypesSettings.privateNpcToPlayer,
[SpeakChannelYellow] = SpeakTypesSettings.channelYellow,
[SpeakChannelWhite] = SpeakTypesSettings.channelWhite,
[SpeakChannelRed] = SpeakTypesSettings.channelRed,
[SpeakChannelOrange] = SpeakTypesSettings.channelOrange,
[SpeakMonsterSay] = SpeakTypesSettings.monsterSay,
[SpeakMonsterYell] = SpeakTypesSettings.monsterYell,
}
local SayModes = {
[1] = { speakTypeDesc = 'whisper', icon = '/core_styles/icons/whisper.png' },
[2] = { speakTypeDesc = 'say', icon = '/core_styles/icons/say.png' },
[3] = { speakTypeDesc = 'yell', icon = '/core_styles/icons/yell.png' }
}
local consolePanel
local consoleBuffer
local consoleTabBar
local consoleLineEdit
local channels
local messageHistory = { }
local currentMessageIndex = 0
local MaxHistory = 1000
-- private functions
local function navigateMessageHistory(step)
local numCommands = #messageHistory
if numCommands > 0 then
currentMessageIndex = math.min(math.max(currentMessageIndex + step, 0), numCommands)
if currentMessageIndex > 0 then
local command = messageHistory[numCommands - currentMessageIndex + 1]
consoleLineEdit:setText(command)
else
consoleLineEdit:clearText()
end
end
end
function applyMessagePrefixies(name, level, message)
if name then
if Options.showLevelsInConsole and level > 0 then
message = name .. ' [' .. level .. ']: ' .. message
else
message = name .. ': ' .. message
end
end
return message
end
-- public functions
function Console.create()
consolePanel = displayUI('console.otui', g_game.gameBottomPanel)
consoleLineEdit = consolePanel:getChildById('consoleLineEdit')
consoleBuffer = consolePanel:getChildById('consoleBuffer')
consoleTabBar = consolePanel:getChildById('consoleTabBar')
consoleTabBar:setContentWidget(consoleBuffer)
channels = {}
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.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 })
-- tibia like hotkeys
Keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
Keyboard.bindKeyDown('Ctrl+E', Console.removeCurrentTab)
end
function Console.destroy()
consolePanel:destroy()
consolePanel = nil
end
function Console.setLineEditText(text)
consoleLineEdit:setText(text)
end
function Console.addTab(name, focus)
local tab = consoleTabBar:addTab(name)
if focus then
consoleTabBar:selectTab(tab)
else
consoleTabBar:blinkTab(tab)
end
return tab
end
function Console.onTabChange(tabBar, tab)
if tab:getText() == "Default" or tab:getText() == "Server Log" then
consolePanel:getChildById('closeChannelButton'):disable()
else
consolePanel:getChildById('closeChannelButton'):enable()
end
end
function Console.removeCurrentTab()
local tab = consoleTabBar:getCurrentTab()
if tab:getText() == "Default" or tab:getText() == "Server Log" then return end
consoleTabBar:removeTab(tab)
-- notificate the server that we are leaving the channel
if tab.channelId then
g_game.leaveChannel(tab.channelId)
elseif tab:getText() == "NPCs" then
g_game.closeNpcChannel()
end
end
function Console.getTab(name)
return consoleTabBar:getTab(name)
end
function Console.getCurrentTab()
return consoleTabBar:getCurrentTab()
end
function Console.addChannel(name, id)
channels[id] = name
local tab = Console.addTab(name, true)
tab.channelId = id
return tab
end
function Console.addPrivateText(text, speaktype, name, isPrivateCommand)
local focus = false
if speaktype.speakType == SpeakPrivateNpcToPlayer then
name = 'NPCs'
focus = true
end
local privateTab = Console.getTab(name)
if privateTab == nil then
if Options.showPrivateMessagesInConsole or (isPrivateCommand and not privateTab) then
privateTab = Console.getTab('Default')
else
privateTab = Console.addTab(name, focus)
end
privateTab.npcChat = speaktype.npcChat
elseif focus then
consoleTabBar:selectTab(privateTab)
end
Console.addTabText(text, speaktype, privateTab)
end
function Console.addText(text, speaktype, tabName)
local tab = Console.getTab(tabName)
if tab ~= nil then
Console.addTabText(text, speaktype, tab)
end
end
function Console.addTabText(text, speaktype, tab)
if Options.showTimestampsInConsole then
text = os.date('%H:%M') .. ' ' .. text
end
local panel = consoleTabBar:getTabPanel(tab)
local label = createWidget('ConsoleLabel', panel)
label:setText(text)
label:setColor(speaktype.color)
consoleTabBar:blinkTab(tab)
if panel:getChildCount() > 10 then
panel:removeChild(panel:getFirstChild())
end
end
function Console.sendCurrentMessage()
local message = consoleLineEdit:getText()
if #message == 0 then return end
consoleLineEdit:clearText()
-- get current channel
local tab = Console.getCurrentTab()
-- handling chat commands
local originalMessage = message
local chatCommandSayMode
local chatCommandPrivate
local chatCommandPrivateReady
local chatCommandMessage = message:match("^%#y (.*)")
if chatCommandMessage ~= nil then chatCommandSayMode = 'yell' end -- player used yell command
message = chatCommandMessage or message
local chatCommandMessage = message:match("^%#w (.*)")
if chatCommandMessage ~= nil then chatCommandSayMode = 'whisper' end -- player used whisper
message = chatCommandMessage or message
local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)")
if findIni ~= nil and findIni == 1 then -- player used private chat command
if chatCommandInitial == chatCommandEnd then
chatCommandPrivateRepeat = false
if chatCommandInitial == "*" then
consoleLineEdit:setText('*'.. chatCommandPrivate .. '* ')
end
message = chatCommandMessage:trim()
chatCommandPrivateReady = true
end
end
message = message:gsub("^(%s*)(.*)","%2") -- remove space characters from message init
if #message == 0 then return end
-- add new command to history
currentMessageIndex = 0
table.insert(messageHistory, originalMessage)
if #messageHistory > MaxHistory then
table.remove(messageHistory, 1)
end
-- when talking on server log, the message goes to default channel
local name = tab:getText()
if name == 'Server Log' then
tab = Console.getTab('Default')
name = 'Default'
end
local speaktypedesc
if tab.channelId and not chatCommandPrivateReady then
if tab.channelId == 0 then
speaktypedesc = chatCommandSayMode or SayModes[consolePanel:getChildById('sayModeButton').sayMode].speakTypeDesc
if speaktypedesc ~= 'say' then Console.sayModeChange(2) end -- head back to say mode
else
speaktypedesc = 'channelYellow'
end
g_game.talkChannel(SpeakTypesSettings[speaktypedesc].speakType, tab.channelId, message)
return
else
local isPrivateCommand = false
if chatCommandPrivateReady then
speaktypedesc = 'privatePlayerToPlayer'
name = chatCommandPrivate
isPrivateCommand = true
elseif tab.npcChat then
speaktypedesc = 'privatePlayerToNpc'
else
speaktypedesc = 'privatePlayerToPlayer'
end
local speaktype = SpeakTypesSettings[speaktypedesc]
local player = g_game.getLocalPlayer()
g_game.talkPrivate(speaktype.speakType, name, message)
message = applyMessagePrefixies(player:getName(), player:getLevel(), message)
Console.addPrivateText(message, speaktype, name, isPrivateCommand)
end
end
function Console.sayModeChange(sayMode)
local buttom = consolePanel:getChildById('sayModeButton')
if sayMode == nil then
sayMode = buttom.sayMode + 1
end
if sayMode > #SayModes then sayMode = 1 end
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})

View File

@@ -0,0 +1,7 @@
Module
name: game_console
description: Manage chat window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'console'

View File

@@ -0,0 +1,95 @@
ConsoleLabel < UILabel
font: verdana-11px-antialised
height: 14
color: yellow
ConsoleTabBar < TabBar
ConsoleTabBarPanel < TabBarPanel
layout:
type: verticalBox
align-bottom: true
ConsoleTabBarButton < TabBarButton
Panel
id: consolePanel
anchors.fill: parent
ConsoleButton
id: prevChannelButton
icon: /core_styles/icons/leftarrow.png
anchors.left: parent.left
anchors.top: parent.top
margin-left: 6
margin-top: 6
ConsoleTabBar
id: consoleTabBar
height: 20
anchors.left: prev.right
anchors.top: prev.top
anchors.right: next.left
margin-left: 5
ConsoleButton
id: nextChannelButton
icon: /core_styles/icons/rightarrow.png
anchors.right: next.left
anchors.top: parent.top
margin-right: 5
margin-top: 6
ConsoleButton
id: closeChannelButton
tooltip: Close this channel (Ctrl+E)
icon: /core_styles/icons/closechannel.png
anchors.right: next.left
anchors.top: parent.top
enabled: false
margin-right: 5
margin-top: 6
@onClick: Console.removeCurrentTab()
ConsoleButton
id: channelsButton
tooltip: Open new channel (Ctrl+O)
icon: /core_styles/icons/channels.png
anchors.right: parent.right
anchors.top: parent.top
margin-right: 5
margin-top: 6
@onClick: g_game.requestChannels()
Panel
id: consoleBuffer
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: consoleLineEdit.top
margin-right: 6
margin-left: 6
margin-bottom: 4
margin-top: 4
focusable: false
ConsoleButton
id: sayModeButton
icon: /core_styles/icons/say.png
tooltip: Adjust volume
&sayMode: 2
size: 20 20
anchors.left: parent.left
anchors.bottom: parent.bottom
margin-left: 6
margin-bottom: 6
@onClick: Console.sayModeChange()
LineEdit
id: consoleLineEdit
anchors.left: sayModeButton.right
anchors.right: parent.right
anchors.bottom: parent.bottom
margin-right: 6
margin-left: 6
margin-bottom: 6
always-active: true
focusable: false

View File

@@ -0,0 +1,11 @@
MiniWindow
size: 200 221
layout:
type: grid
cell-size: 34 34
cell-spacing: 5
num-columns: 4
num-lines: 5

View File

@@ -0,0 +1,138 @@
Containers = {}
-- private variables
local m_containers = {}
-- public functions
function Containers.clean()
m_containers = {}
end
function Containers.getFreeContainerId()
for i=0,15 do
if not m_containers[i] then
return i
end
end
return 0
end
-- hooked events
function Containers.onOpenContainer(containerId, itemId, name, capacity, hasParent, items)
local container = m_containers[containerId]
if container then
g_game.gameRightPanel:removeChild(container)
end
container = displayUI('container.otui', g_game.gameRightPanel)
name = name:sub(1,1):upper() .. name:sub(2)
container:setText(name)
-- set icon, itemid
-- closebutton
-- resize
if hasParent then
-- parent button
end
container.itemCount = #items
container.capacity = capacity
for i=1,capacity do
local itemWidget = UIItem.create()
itemWidget:setStyle('Item')
container:addChild(itemWidget)
itemWidget.position = {x=65535, y=containerId+64, z=i-1}
if i <= #items then
local item = items[i]
item:setPosition(itemWidget.position)
itemWidget:setItem(item)
end
end
m_containers[containerId] = container
end
function Containers.onCloseContainer(containerId)
local container = m_containers[containerId]
if container then
g_game.gameRightPanel:removeChild(container)
end
m_containers[containerId] = nil
end
function Containers.onContainerAddItem(containerId, item)
local container = m_containers[containerId]
if not container or not item or container.itemCount >= container.capacity then return end
local i = container.itemCount
while i >= 1 do
local itemWidget = container:getChildByIndex(i)
if not itemWidget then return end
local nextItemWidget = container:getChildByIndex(i+1)
if not nextItemWidget then return end
local swapItem = itemWidget:getItem()
if swapItem then
swapItem:setPosition(nextItemWidget.position)
nextItemWidget:setItem(swapItem)
end
i = i - 1
end
local itemWidget = container:getChildByIndex(1)
if not itemWidget then return end
item:setPosition(itemWidget.position)
itemWidget:setItem(item)
container.itemCount = container.itemCount + 1
end
function Containers.onContainerUpdateItem(containerId, slot, item)
local container = m_containers[containerId]
if not container then return end
local itemWidget = container:getChildByIndex(slot + 1)
if not itemWidget then return end
itemWidget:setItem(item)
item:setPosition(itemWidget.position)
end
function Containers.onContainerRemoveItem(containerId, slot)
local container = m_containers[containerId]
if not container then return end
local itemWidget = container:getChildByIndex(slot+1)
if not itemWidget then return end
itemWidget:setItem(nil)
for i=slot,container.itemCount-2 do
local itemWidget = container:getChildByIndex(i+1)
if not itemWidget then return end
local nextItemWidget = container:getChildByIndex(i+2)
if not nextItemWidget then return end
local item = nextItemWidget:getItem()
local pos = item:getPosition()
pos.z = pos.z - 1
item:setPosition(pos)
itemWidget:setItem(item)
nextItemWidget:setItem(nil)
end
container.itemCount = container.itemCount - 1
end
connect(g_game, { onGameStart = Containers.clean,
onGameEnd = Containers.clean,
onOpenContainer = Containers.onOpenContainer,
onCloseContainer = Containers.onCloseContainer,
onContainerAddItem = Containers.onContainerAddItem,
onContainerUpdateItem = Containers.onContainerUpdateItem,
onContainerRemoveItem = Containers.onContainerRemoveItem })

View File

@@ -0,0 +1,7 @@
Module
name: game_containers
description: Manage containers
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'containers'

View File

@@ -0,0 +1,59 @@
HealthBar = {}
-- private variables
local healthBarWindow
local healthBar
local manaBar
local healthLabel
local manaLabel
-- public functions
function HealthBar.create()
healthBarWindow = displayUI('healthbar.otui', g_game.gameRightPanel)
healthBarButton = TopMenu.addGameButton('healthBarButton', 'Healh Bar', 'healthbar.png', HealthBar.toggle)
healthBarButton:setOn(true)
healthBar = healthBarWindow:getChildById('healthBar')
manaBar = healthBarWindow:getChildById('manaBar')
healthLabel = healthBarWindow:getChildById('healthLabel')
manaLabel = healthBarWindow:getChildById('manaLabel')
end
function HealthBar.destroy()
healthBarWindow:destroy()
healthBarWindow = nil
healthBarButton:destroy()
healthBarButton = nil
healthBar = nil
manaBar = nil
healthLabel = nil
manaLabel = nil
end
function HealthBar.toggle()
local visible = not healthBarWindow:isExplicitlyVisible()
healthBarWindow:setVisible(visible)
healthBarButton:setOn(visible)
end
-- hooked events
function HealthBar.onHealthChange(localPlayer, health, maxHealth)
healthLabel:setText(health .. ' / ' .. maxHealth)
healthBar:setPercent(health / maxHealth * 100)
end
function HealthBar.onManaChange(localPlayer, mana, maxMana)
manaLabel:setText(mana .. ' / ' .. maxMana)
local percent
if maxMana == 0 then
percent = 100
else
percent = (mana * 100)/maxMana
end
manaBar:setPercent(percent)
end
connect(g_game, { onGameStart = HealthBar.create,
onGameEnd = HealthBar.destroy })
connect(LocalPlayer, { onHealthChange = HealthBar.onHealthChange,
onManaChange = HealthBar.onManaChange })

View File

@@ -0,0 +1,7 @@
Module
name: game_healthbar
description: Displays health and mana points
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'healthbar'

View File

@@ -0,0 +1,47 @@
HealthBar < ProgressBar
id: healthBar
height: 15
background-color: #ff4444
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ManaBar < ProgressBar
id: manaBar
height: 15
background-color: #4444ff
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
HealthLabel < GameLabel
id: healthLabel
color: white
text-align: center
font: verdana-11px-rounded
anchors.fill: healthBar
margin-top: 2
text: 0 / 0
ManaLabel < GameLabel
id: manaLabel
color: white
text-align: center
font: verdana-11px-rounded
anchors.fill: manaBar
margin-top: 2
text: 0 / 0
UIWindow
id: healthManaPanel
width: 192
height: 34
margin-top: 10
margin-left: 6
margin-right: 6
move-policy: free updated
HealthBar
HealthLabel
ManaBar
ManaLabel

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

View File

@@ -0,0 +1,458 @@
HotkeysManager = {}
local hotkeysManagerLoaded = false
local hotkeysWindow
local hotkeysButton
local currentHotkeysList
local hotkeyLabelSelectedOnList
local currentItemPreview
local itemWidget
local addHotkey
local removeHotkey
local hotkeyText
local hotKeyTextLabel
local sendAutomatically
local selectObjectButton
local clearObjectButton
local useOnSelf
local useOnTarget
local useWith
local hotkeyList = {}
HOTKEY_MANAGER_USEONSELF = 1
HOTKEY_MANAGER_USEONTARGET = 2
HOTKEY_MANAGER_USEWITH = 3
local hotkeyColors = {
text = '#888888',
textAutoSend = '#FFFFFF',
itemUse = '#8888FF',
itemUseSelf = '#00FF00',
itemUseTarget = '#FF0000',
itemUseWith = '#CC0000',
}
-- public functions
function HotkeysManager.init()
hotkeysWindow = displayUI('hotkeys_manager.otui')
hotkeysWindow:setVisible(false)
hotkeysButton = TopMenu.addButton('hotkeysButton', 'Hotkeys (Ctrl+K)', '/game_hotkeys/icon.png', HotkeysManager.toggle)
Keyboard.bindKeyDown('Ctrl+K', HotkeysManager.toggle)
currentHotkeysList = hotkeysWindow:getChildById('currentHotkeys')
currentItemPreview = hotkeysWindow:getChildById('itemPreview')
addHotkey = hotkeysWindow:getChildById('addHotkey')
removeHotkey = hotkeysWindow:getChildById('removeHotkey')
hotkeyText = hotkeysWindow:getChildById('hotkeyText')
hotKeyTextLabel = hotkeysWindow:getChildById('hotKeyTextLabel')
sendAutomatically = hotkeysWindow:getChildById('sendAutomatically')
selectObjectButton = hotkeysWindow:getChildById('selectObjectButton')
clearObjectButton = hotkeysWindow:getChildById('clearObjectButton')
useOnSelf = hotkeysWindow:getChildById('useOnSelf')
useOnTarget = hotkeysWindow:getChildById('useOnTarget')
useWith = hotkeysWindow:getChildById('useWith')
itemWidget = createWidget('UIItem')
itemWidget:setVirtual(true)
itemWidget:setVisible(false)
itemWidget:setFocusable(false)
connect(currentHotkeysList, { onChildFocusChange = function (self, focusedChild) HotkeysManager.checkSelectedHotkey(focusedChild) end } )
hotkeysManagerLoaded = true
HotkeysManager.load()
end
function HotkeysManager.load()
local hotkeySettings = Settings.getNode('HotkeysManager')
if hotkeySettings ~= nil then
for i, v in pairs(hotkeySettings) do
HotkeysManager.addKeyCombo(nil, v.keyCombo, v)
end
end
end
function HotkeysManager.save()
local hotkeySettings = {}
for i = 1, currentHotkeysList:getChildCount() do
local child = currentHotkeysList:getChildByIndex(i)
table.insert(hotkeySettings, {keyCombo = child.keyCombo,
autoSend = child.autoSend,
itemId = child.itemId,
useType = child.useType,
value = child.value})
end
Settings.setNode('HotkeysManager', hotkeySettings)
end
function HotkeysManager.terminate()
hotkeysManagerLoaded = false
Keyboard.unbindKeyDown('Ctrl+K')
HotkeysManager.save()
currentHotkeysList = nil
hotkeyLabelSelectedOnList = nil
currentItemPreview = nil
hotkeyList = {}
addHotkey = nil
removeHotkey = nil
hotkeyText = nil
hotKeyTextLabel = nil
sendAutomatically = nil
selectObjectButton = nil
clearObjectButton = nil
useOnSelf = nil
useOnTarget = nil
useWith = nil
itemWidget:destroy()
itemWidget = nil
hotkeysWindow:destroy()
hotkeysWindow = nil
hotkeysButton:destroy()
hotkeysButton = nil
end
function HotkeysManager.toggle()
if hotkeysWindow:isVisible() then
HotkeysManager.hide()
else
HotkeysManager.show()
end
end
function HotkeysManager.show()
if g_game.isOnline() then
hotkeysWindow:grabKeyboard()
hotkeysWindow:show()
hotkeysWindow:lock()
hotkeysWindow:raise()
end
end
function HotkeysManager.hide()
hotkeysWindow:ungrabKeyboard()
hotkeysWindow:unlock()
hotkeysWindow:hide()
end
-- private functions
function HotkeysManager.onChooseItemMouseRelease(self, mousePosition, mouseButton)
local item = nil
if mouseButton == MouseLeftButton then
local clickedWidget = g_game.gameUi:recursiveGetChildByPos(mousePosition)
if clickedWidget then
if clickedWidget:getClassName() == 'UIMap' then
local tile = clickedWidget:getTile(mousePosition)
if tile then
local thing = tile:getTopMoveThing()
if thing then
item = thing:asItem()
end
end
elseif clickedWidget:getClassName() == 'UIItem' and not clickedWidget:isVirtual() then
item = clickedWidget:getItem()
end
end
end
if item then
currentItemPreview:setItemId(item:getId())
hotkeyLabelSelectedOnList.itemId = item:getId()
HotkeysManager.changeUseType(HOTKEY_MANAGER_USEONSELF)
HotkeysManager.checkSelectedHotkey(hotkeyLabelSelectedOnList)
HotkeysManager:show()
end
Mouse.restoreCursor()
self:ungrabMouse()
self:destroy()
end
function HotkeysManager.startChooseItem()
local mouseGrabberWidget = createWidget('UIWidget')
mouseGrabberWidget:setVisible(false)
mouseGrabberWidget:setFocusable(false)
connect(mouseGrabberWidget, { onMouseRelease = HotkeysManager.onChooseItemMouseRelease })
mouseGrabberWidget:grabMouse()
Mouse.setTargetCursor()
HotkeysManager:hide()
end
function HotkeysManager.clearObject()
hotkeyLabelSelectedOnList.itemId = nil
currentItemPreview:clearItem()
HotkeysManager.changeUseType(HOTKEY_MANAGER_USEONSELF)
HotkeysManager.sendAutomatically(false)
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': ')
HotkeysManager.checkSelectedHotkey(hotkeyLabelSelectedOnList)
end
function HotkeysManager.addHotkey()
local widget
messageBox = createWidget('MainWindow', hotkeysWindow)
messageBox:grabKeyboard()
messageBox:setId('assignWindow')
messageBox:setText('Button Assign')
messageBox:setWidth(420)
messageBox:setHeight(140)
messageBox:setDragable(false)
widget = createWidget('Label', messageBox)
widget:setText('Please, press the key you wish to add onto your hotkeys manager')
widget:resizeToText()
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
widget:addAnchor(AnchorTop, 'parent', AnchorTop)
widget = createWidget('Label', messageBox)
widget:setId('comboPreview')
widget:setText('Current hotkey to add: None')
widget.keyCombo = ''
widget:resizeToText()
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
widget:addAnchor(AnchorTop, 'prev', AnchorBottom)
widget:setMarginTop(20)
widget = createWidget('Button', messageBox)
widget:setId('cancelButton')
widget:setText('Cancel')
widget:setWidth(64)
widget:addAnchor(AnchorBottom, 'parent', AnchorBottom)
widget:addAnchor(AnchorRight, 'parent', AnchorRight)
widget.onClick = function (self)
messageBox = nil
self:getParent():destroy()
end
widget = createWidget('Button', messageBox)
widget:setId('addButton')
widget:setText('Add')
widget:setWidth(64)
widget:disable()
widget:addAnchor(AnchorBottom, 'cancelButton', AnchorBottom)
widget:addAnchor(AnchorRight, 'cancelButton', AnchorLeft)
widget:setMarginRight(10)
widget.onClick = function (self)
messageBox = nil
HotkeysManager.addKeyCombo(self:getParent(), self:getParent():getChildById('comboPreview').keyCombo)
end
connect(messageBox, { onKeyDown = HotkeysManager.hotkeyCapture }, true)
end
function HotkeysManager.addKeyCombo(messageBox, keyCombo, keySettings)
local label = nil
if currentHotkeysList:getChildById(keyCombo) == nil then
local label = createWidget('HotkeyListLabel', currentHotkeysList)
label:setId(keyCombo)
label:setColor(hotkeyColors.text)
label:setText(keyCombo..': ')
if keySettings then
hotkeyLabelSelectedOnList = label
label.keyCombo = keyCombo
HotkeysManager.sendAutomatically(keySettings.autoSend)
label.itemId = keySettings.itemId
currentItemPreview:setItemId(keySettings.itemId)
HotkeysManager.changeUseType(tonumber(keySettings.useType))
label.value = keySettings.value
else
label.keyCombo = keyCombo
label.autoSend = false
label.itemId = nil
label.useType = HOTKEY_MANAGER_USEONSELF
label.value = ''
end
HotkeysManager.checkSelectedHotkey(label)
hotkeyList[keyCombo] = label
Keyboard.bindKeyPress(keyCombo, function () HotkeysManager.call(keyCombo) end, nil, 350)
end
if messageBox then
messageBox:destroy()
messageBox = nil
end
end
function HotkeysManager.call(keyCombo)
if g_game.isOnline() then
local hotKey = hotkeyList[keyCombo]
if hotKey.itemId == nil and hotKey.value ~= '' then
if hotKey.autoSend then
g_game.talk(hotKey.value)
else
Console.setLineEditText(hotKey.value)
end
elseif hotKey.itemId ~= nil then
if hotKey.useType == HOTKEY_MANAGER_USEONSELF then
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
local attackingCreature = g_game.getAttackingCreature()
if attackingCreature then
g_game.useInventoryItemWith(hotKey.itemId, attackingCreature)
end
elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then
itemWidget:setItemId(hotKey.itemId)
g_game.startUseWith(itemWidget:getItem())
end
end
end
end
function HotkeysManager.checkSelectedHotkey(focused)
if hotkeysManagerLoaded then
hotkeyLabelSelectedOnList = focused
if hotkeyLabelSelectedOnList ~= nil then
removeHotkey:enable()
if hotkeyLabelSelectedOnList.itemId == nil then
hotkeyText:enable()
hotKeyTextLabel:enable()
hotkeyText:setText(hotkeyLabelSelectedOnList.value)
if hotkeyLabelSelectedOnList.value ~= '' then
sendAutomatically:enable()
else
sendAutomatically:disable()
end
selectObjectButton:enable()
clearObjectButton:disable()
currentItemPreview:setItemId(0)
else
hotkeyText:clearText()
hotkeyText:disable()
hotKeyTextLabel:disable()
sendAutomatically:disable()
selectObjectButton:disable()
clearObjectButton:enable()
currentItemPreview:setItemId(hotkeyLabelSelectedOnList.itemId)
end
HotkeysManager.changeUseType(hotkeyLabelSelectedOnList.useType)
else
hotkeyText:clearText()
removeHotkey:disable()
hotkeyText:disable()
sendAutomatically:disable()
sendAutomatically:setChecked(false)
currentItemPreview:setItemId(0)
selectObjectButton:disable()
clearObjectButton:disable()
useOnSelf:disable()
useOnTarget:disable()
useWith:disable()
useOnSelf:setChecked(false)
useOnTarget:setChecked(false)
useWith:setChecked(false)
end
end
end
function HotkeysManager.changeUseType(useType, checked)
if checked == nil or checked then
hotkeyLabelSelectedOnList.useType = useType
if hotkeyLabelSelectedOnList.itemId ~= nil and currentItemPreview:getItem():isMultiUse() then
useOnSelf:enable()
useOnTarget:enable()
useWith:enable()
if useType == HOTKEY_MANAGER_USEONSELF then
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': (use object on yourself)')
hotkeyLabelSelectedOnList:setColor(hotkeyColors.itemUseSelf)
useOnSelf:setChecked(true)
useOnTarget:setChecked(false)
useWith:setChecked(false)
elseif useType == HOTKEY_MANAGER_USEONTARGET then
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': (use object on target)')
hotkeyLabelSelectedOnList:setColor(hotkeyColors.itemUseTarget)
useOnSelf:setChecked(false)
useOnTarget:setChecked(true)
useWith:setChecked(false)
elseif useType == HOTKEY_MANAGER_USEWITH then
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': (use object with crosshair)')
hotkeyLabelSelectedOnList:setColor(hotkeyColors.itemUseWith)
useOnSelf:setChecked(false)
useOnTarget:setChecked(false)
useWith:setChecked(true)
end
elseif hotkeyLabelSelectedOnList.itemId ~= nil and not currentItemPreview:getItem():isMultiUse() then
useOnSelf:disable()
useOnTarget:disable()
useWith:disable()
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': (use object)')
hotkeyLabelSelectedOnList:setColor(hotkeyColors.itemUse)
useOnSelf:setChecked(false)
useOnTarget:setChecked(false)
useWith:setChecked(false)
else
useOnSelf:disable()
useOnTarget:disable()
useWith:disable()
useOnSelf:setChecked(false)
useOnTarget:setChecked(false)
useWith:setChecked(false)
end
end
end
function HotkeysManager.removeHotkey()
if hotkeyLabelSelectedOnList ~= nil then
hotkeyList[hotkeyLabelSelectedOnList.keyCombo] = nil
Keyboard.unbindKeyPress(hotkeyLabelSelectedOnList.keyCombo)
hotkeyLabelSelectedOnList:destroy()
end
end
function HotkeysManager.onHotkeyTextChange(id, value)
if hotkeyLabelSelectedOnList ~= nil and hotkeyLabelSelectedOnList.keyCombo ~= nil then
hotkeyLabelSelectedOnList:setText(hotkeyLabelSelectedOnList.keyCombo .. ': ' .. value)
hotkeyLabelSelectedOnList.value = value
if value ~= '' then
sendAutomatically:enable()
else
sendAutomatically:disable()
sendAutomatically:setChecked(false)
end
end
end
function HotkeysManager.sendAutomatically(value)
hotkeyLabelSelectedOnList.autoSend = value
if value then
hotkeyLabelSelectedOnList:setColor(hotkeyColors.autoSend)
else
hotkeyLabelSelectedOnList:setColor(hotkeyColors.text)
end
end
function HotkeysManager.hotkeyCapture(widget, keyCode, keyboardModifiers)
local keyCombo = determineKeyComboDesc(keyCode, keyboardModifiers)
local comboPreview = hotkeysWindow:getChildById('assignWindow'):getChildById('comboPreview')
comboPreview:setText('Current hotkey to add: '.. keyCombo)
comboPreview.keyCombo = keyCombo
comboPreview:resizeToText()
hotkeysWindow:getChildById('assignWindow'):getChildById('addButton'):enable()
return true
end

View File

@@ -0,0 +1,15 @@
Module
name: game_hotkeys
description: Manage client hotkeys
author: OTClient team
website: https://github.com/edubart/otclient
dependencies:
- client_tibiafiles
onLoad: |
dofile 'hotkeys_manager'
HotkeysManager.init()
onUnload: |
HotkeysManager.terminate()

View File

@@ -0,0 +1,159 @@
HotkeyListLabel < UILabel
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
phantom: false
$focus:
background-color: #ffffff22
MainWindow
id: hotkeysWindow
text: Hotkeys
size: 340 460
@onEnter: HotkeysManager.hide()
@onEscape: HotkeysManager.hide()
Label
id: currentHotkeysLabel
text: Current hotkeys:
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
TextList
id: currentHotkeys
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
height: 150
margin-top: 2
padding: 1
focusable: false
Label
text: Manage hotkeys:
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 10
Button
id: addHotkey
text: Add
width: 64
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 2
@onClick: HotkeysManager.addHotkey()
Button
id: removeHotkey
text: Remove
width: 64
enabled: false
anchors.left: prev.right
anchors.top: prev.top
margin-left: 10
@onClick: HotkeysManager.removeHotkey()
Label
id: hotKeyTextLabel
text: Edit hotkey text:
enable: false
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 20
LineEdit
id: hotkeyText
enabled: false
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-bottom: 2
@onTextChange: HotkeysManager.onHotkeyTextChange(self:getId(), self:getText())
CheckBox
id: sendAutomatically
text: Send automatically
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
enabled:false
margin-top: 10
@onCheckChange: HotkeysManager.sendAutomatically(self:isChecked())
Item
id: itemPreview
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 10
virtual: true
Button
id: selectObjectButton
text: Select object
width: 128
enabled: false
anchors.left: prev.right
anchors.top: prev.top
margin-left: 10
@onClick: HotkeysManager.startChooseItem()
Button
id: clearObjectButton
text: Clear object
width: 128
enabled: false
anchors.left: prev.left
anchors.right: prev.right
anchors.top: prev.bottom
margin-top: 2
@onClick: HotkeysManager.clearObject()
ButtonBox
id: useOnSelf
text: Use on yourself
width: 128
enabled: false
anchors.left: selectObjectButton.right
anchors.right: parent.right
anchors.top: selectObjectButton.top
checked: false
margin-left: 10
@onCheckChange: HotkeysManager.changeUseType(HOTKEY_MANAGER_USEONSELF, self:isChecked())
ButtonBox
id: useOnTarget
text: Use on target
width: 128
enabled: false
anchors.left: prev.left
anchors.right: parent.right
anchors.top: prev.bottom
checked: false
margin-top: 2
@onCheckChange: HotkeysManager.changeUseType(HOTKEY_MANAGER_USEONTARGET, self:isChecked())
ButtonBox
id: useWith
text: With crosshair
width: 128
enabled: false
anchors.left: prev.left
anchors.right: parent.right
anchors.top: prev.bottom
checked: false
margin-top: 2
@onCheckChange: HotkeysManager.changeUseType(HOTKEY_MANAGER_USEWITH, self:isChecked())
Button
text: Close
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: HotkeysManager.hide()

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

View File

@@ -0,0 +1,199 @@
GameInterface = {}
-- private variables
local WALK_AUTO_REPEAT_DELAY = 90
local gameRootPanel
local gameMapPanel
local gameRightPanel
local gameLeftPanel
local gameBottomPanel
-- private functions
function onGameStart()
-- hook window close event
setonclose(GameInterface.tryLogout)
GameInterface.show()
end
function onGameEnd()
setonclose(exit)
GameInterface.hide()
end
-- public functions
function GameInterface.init()
gameRootPanel = displayUI('gameinterface.otui')
gameRootPanel:lower()
connect(g_game, { onGameStart = onGameStart }, true)
connect(g_game, { onGameEnd = onGameEnd })
Keyboard.bindKeyPress('Up', function() g_game.walk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Right', function() g_game.walk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Down', function() g_game.walk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Left', function() g_game.walk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad8', function() g_game.walk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad9', function() g_game.walk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad6', function() g_game.walk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad3', function() g_game.walk(SouthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad2', function() g_game.walk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad1', function() g_game.walk(SouthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad4', function() g_game.walk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Numpad7', function() g_game.walk(NorthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Down', function() g_game.turn(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Left', function() g_game.turn(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Numpad8', function() g_game.turn(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
Keyboard.bindKeyPress('Esc', function() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
end
function GameInterface.terminate()
disconnect(g_game, { onGameStart = onGameStart }, true)
disconnect(g_game, { onGameEnd = onGameEnd })
end
function GameInterface.show()
gameRootPanel:show()
end
function GameInterface.hide()
gameRootPanel:hide()
end
function GameInterface.tryLogout()
if g_game.isOnline() then
g_game.forceLogout()
else
exit()
end
end
function GameInterface.getRootPanel()
return gameRootPanel
end
function GameInterface.getMapPanel()
return gameMapPanel
end
function GameInterface.getRightPanel()
return gameRightPanel
end
function GameInterface.getLeftPanel()
return gameLeftPanel
end
function GameInterface.getBottomPanel()
return gameBottomPanel
end
function GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatureThing)
local menu = createWidget('PopupMenu')
if lookThing then
menu:addOption('Look', function() g_game.look(lookThing) end)
end
if useThing then
if useThing:isContainer() then
if useThing:isInsideContainer() then
menu:addOption('Open', function() g_game.open(useThing, useThing:getContainerId()) end)
menu:addOption('Open in new window', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
else
menu:addOption('Open', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
end
else
if useThing:isMultiUse() then
menu:addOption('Use with ...', function() g_game.startUseWith(useThing) end)
else
menu:addOption('Use', function() g_game.use(useThing) end)
end
end
if useThing:isRotateable() then
menu:addOption('Rotate', function() g_game.rotate(useThing) end)
end
end
if lookThing and not lookThing:asCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then
menu:addSeparator()
menu:addOption('Trade with ...', function() print('trade with') end)
end
-- check for move up
if creatureThing then
menu:addSeparator()
if creatureThing:asLocalPlayer() then
menu:addOption('Set Outfit', function() g_game.requestOutfit() end)
if creatureThing:asPlayer():isPartyMember() --[[and not fighting]] then
if creatureThing:asPlayer():isPartyLeader() then
if creatureThing:asPlayer():isPartySharedExperienceActive() then
menu:addOption('Disable Shared Experience', function() g_game.partyShareExperience(false) end)
else
menu:addOption('Enable Shared Experience', function() g_game.partyShareExperience(true) end)
end
end
menu:addOption('Leave Party', function() g_game.partyLeave() end)
end
else
local localPlayer = g_game.getLocalPlayer()
if localPlayer then
if g_game.getAttackingCreature() ~= creatureThing then
menu:addOption('Attack', function() g_game.attack(creatureThing) end)
else
menu:addOption('Stop Attack', function() g_game.cancelAttack() end)
end
if g_game.getFollowingCreature() ~= creatureThing then
menu:addOption('Follow', function() g_game.follow(creatureThing) end)
else
menu:addOption('Stop Follow', function() g_game.cancelFollow() end)
end
if creatureThing:asPlayer() then
menu:addSeparator()
menu:addOption('Message to ' .. creatureThing:getName(), function() print('message') end)
menu:addOption('Add to VIP list', function() g_game.addVip(creatureThing:getName()) end)
local localPlayerShield = localPlayer:asCreature():getShield()
local creatureShield = creatureThing:getShield()
if localPlayerShield == ShieldNone or localPlayerShield == ShieldWhiteBlue then
if creatureShield == ShieldWhiteYellow then
menu:addOption('Join ' .. creatureThing:getName() .. '\'s Party', function() g_game.partyJoin(creatureThing:getId()) end)
else
menu:addOption('Invite to Party', function() g_game.partyInvite(creatureThing:getId()) end)
end
elseif localPlayerShield == ShieldWhiteYellow then
if creatureShield == ShieldWhiteBlue then
menu:addOption('Revoke ' .. creatureThing:getName() .. '\'s Invitation', function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
end
elseif localPlayerShield == ShieldYellow or localPlayerShield == ShieldYellowSharedExp or localPlayerShield == ShieldYellowNoSharedExpBlink or localPlayerShield == ShieldYellowNoSharedExp then
if creatureShield == ShieldWhiteBlue then
menu:addOption('Revoke ' .. creatureThing:getName() .. '\'s Invitation', function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
elseif creatureShield == ShieldBlue or creatureShield == ShieldBlueSharedExp or creatureShield == ShieldBlueNoSharedExpBlink or creatureShield == ShieldBlueNoSharedExp then
menu:addOption('Pass Leadership to ' .. creatureThing:getName(), function() g_game.partyPassLeadership(creatureThing:getId()) end)
else
menu:addOption('Invite to Party', function() g_game.partyInvite(creatureThing:getId()) end)
end
end
end
end
end
menu:addSeparator()
menu:addOption('Copy Name', function() g_window.setClipboardText(creatureThing:getName()) end)
end
menu:display(menuPosition)
end

View File

@@ -0,0 +1,20 @@
Module
name: game_interface
description: |
Create the game main interface (map and bottom/left/right panels),
any game module must use it to add ingame interfaces
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'uiminiwindow'
dofile 'uiminiwindowcontainer'
dofile 'uiitem'
dofile 'uimap'
dofile 'gameinterface'
GameInterface.init()
onUnload: |
GameInterface.terminate()

View File

@@ -0,0 +1,46 @@
GameSidePanel < UIMiniWindowContainer
image-source: /core_styles/styles/images/sidepanel.png
image-border: 4
GameBottomPanel < Panel
image-source: /core_styles/styles/images/bottompanel.png
image-border: 4
GameMapPanel < UIMap
padding: 4
image-source: /core_styles/styles/images/mappanel.png
image-border: 4
UIGame
id: gameRootPanel
anchors.fill: parent
anchors.top: topMenu.bottom
InterfacePanel
id: gameRightPanel
width: 190
layout: verticalBox
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
GameBottomPanel
id: gameBottomPanel
height: 170
anchors.left: parent.left
anchors.right: gameRightPanel.left
anchors.bottom: parent.bottom
GameMapPanel
id: gameMapPanel
anchors.left: parent.left
anchors.right: gameRightPanel.left
anchors.top: parent.top
anchors.bottom: gameBottomPanel.top
focusable: false
UIWidget
id: mouseGrabber
focusable: false
visible: false

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,75 @@
function UIItem:onDragEnter(mousePos)
if self:isVirtual() then return false end
local item = self:getItem()
if not item then return false end
self:setBorderWidth(1)
self.parsed = false
self.currentDragThing = item
Mouse.setTargetCursor()
return true
end
function UIItem:onDragLeave(droppedWidget, mousePos)
if self:isVirtual() then return false end
if not self.parsed then
self.currentDragThing = nil
end
Mouse.restoreCursor()
self:setBorderWidth(0)
return true
end
function UIItem:onDrop(widget, mousePos)
if self:isVirtual() then return false end
if not widget or not widget.currentDragThing then return true end
local pos = self.position
local count = widget.currentDragThing:getCount()
if widget.currentDragThing:isStackable() and count > 1 then
widget.parsed = true
local moveWindow = displayUI('/game/movewindow.otui')
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
moveWindow.onEnter = okButton.onClick
else
g_game.move(widget.currentDragThing, pos, 1)
end
self:setBorderWidth(0)
return true
end
function UIItem:onHoverChange(hovered)
if self:isVirtual() then return end
local draggingWidget = g_ui.getDraggingWidget()
if draggingWidget and self ~= draggingWidget then
local gotMap = draggingWidget:getClassName() == 'UIMap'
local gotItem = draggingWidget:getClassName() == 'UIItem' and not draggingWidget:isVirtual()
if hovered and (gotItem or gotMap) then
self:setBorderWidth(1)
else
self:setBorderWidth(0)
end
end
end
function UIItem:onMouseRelease(mousePosition, mouseButton)
if self:isVirtual() then return false end
local item = self:getItem()
if not item or not self:containsPoint(mousePosition) then return false end
return g_game.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item)
end

View File

@@ -0,0 +1,56 @@
function UIMap:onDragEnter(mousePos)
local tile = self:getTile(mousePos)
if not tile then return false end
local thing = tile:getTopMoveThing()
if not thing then return false end
self.parsed = false
self.currentDragThing = thing
Mouse.setTargetCursor()
return true
end
function UIMap:onDragLeave(droppedWidget, mousePos)
if not self.parsed then
self.currentDragThing = nil
end
Mouse.restoreCursor()
return true
end
function UIMap:onDrop(widget, mousePos)
if not widget or not widget.currentDragThing then return false end
local tile = self:getTile(mousePos)
if not tile then return false end
local count = widget.currentDragThing:getCount()
if widget.currentDragThing:isStackable() and count > 1 then
widget.parsed = true
local moveWindow = displayUI('/game/movewindow.otui')
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 UIMap:onMouseRelease(mousePosition, mouseButton)
local tile = self:getTile(mousePosition)
if tile and g_game.processMouseAction(mousePosition, mouseButton, nil, tile:getTopLookThing(), tile:getTopUseThing(), tile:getTopCreature(), tile:getTopMultiUseThing()) then return true end
return false
end

View File

@@ -0,0 +1,36 @@
UIMiniWindow = extends(UIWindow)
function UIMiniWindow.create()
local miniwindow = UIMiniWindow.internalCreate()
return miniwindow
end
function UIMiniWindow:onDragEnter(mousePos)
local parent = self:getParent()
if not parent then return false end
if parent:getClassName() == 'UIMiniWindowContainer' then
local containerParent = parent:getParent()
parent:removeChild(self)
containerParent:addChild(self)
end
local oldPos = self:getPosition()
self.movingReference = { x = mousePos.x - oldPos.x, y = mousePos.y - oldPos.y }
self:setPosition(oldPos)
return true
end
function UIMiniWindow:onDragLeave(droppedWidget, mousePos)
-- TODO: drop on other interfaces
end
function UIMiniWindow:onFocusChange(focused)
-- miniwindows only raises when its outside MiniWindowContainers
if not focused then return end
local parent = self:getParent()
if parent and parent:getClassName() ~= 'UIMiniWindowContainer' then
self:raise()
end
end

View File

@@ -0,0 +1,12 @@
UIMiniWindowContainer = extends(UIWidget)
function UIMiniWindowContainer.create()
local container = UIMiniWindowContainer.internalCreate()
container:setFocusable(false)
container:setPhantom(true)
return container
end
function UIMiniWindowContainer:getClassName()
return 'UIMiniWindowContainer'
end

View File

@@ -0,0 +1,50 @@
Inventory = {}
-- private variables
local inventoryWindow
local inventoryButton
-- public functions
function Inventory.create()
inventoryWindow = displayUI('inventory.otui', g_game.gameRightPanel)
inventoryButton = TopMenu.addGameButton('inventoryButton', 'Inventory (Ctrl+I)', 'inventory.png', Inventory.toggle)
inventoryButton:setOn(true)
Keyboard.bindKeyDown('Ctrl+I', Inventory.toggle)
end
function Inventory.destroy()
Keyboard.unbindKeyDown('Ctrl+I')
inventoryWindow:destroy()
inventoryWindow = nil
inventoryButton:destroy()
inventoryButton = nil
end
function Inventory.toggle()
local visible = not inventoryWindow:isExplicitlyVisible()
inventoryWindow:setVisible(visible)
inventoryButton:setOn(visible)
end
-- hooked events
function Inventory.onInventoryChange(slot, item)
local itemWidget = inventoryWindow:getChildById('slot' .. slot)
itemWidget:setItem(item)
end
function Inventory.onFreeCapacityChange(freeCapacity)
local widget = inventoryWindow:getChildById('capacity')
widget:setText("Cap:\n" .. freeCapacity)
end
function Inventory.onSoulChange(soul)
local widget = inventoryWindow:getChildById('soul')
widget:setText("Soul:\n" .. soul)
end
connect(g_game, { onGameStart = Inventory.create,
onGameEnd = Inventory.destroy,
onInventoryChange = Inventory.onInventoryChange,
onFreeCapacityChange = Inventory.onFreeCapacityChange,
onSoulChange = Inventory.onSoulChange })

View File

@@ -0,0 +1,7 @@
Module
name: game_inventory
description: View local player equipments window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'inventory'

View File

@@ -0,0 +1,114 @@
UIWindow
width: 192
height: 154
margin-top: 10
margin-left: 6
margin-right: 6
Item
// head
id: slot1
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
&position: {x=65535, y=1, z=0}
Item
// armor
id: slot4
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=4, z=0}
Item
// legs
id: slot7
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=7, z=0}
Item
// feet
id: slot8
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=8, z=0}
Item
// necklace
id: slot2
anchors.top: parent.top
anchors.right: slot1.left
margin-top: 10
margin-right: 5
&position: {x=65535, y=2, z=0}
Item
// left
id: slot6
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=6, z=0}
Item
// ring
id: slot9
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=9, z=0}
Item
// backpack
id: slot3
anchors.top: parent.top
anchors.left: slot1.right
margin-top: 10
margin-left: 5
&position: {x=65535, y=3, z=0}
Item
// right
id: slot5
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=5, z=0}
Item
// ammo
id: slot10
anchors.top: prev.bottom
anchors.horizontalCenter: prev.horizontalCenter
margin-top: 5
&position: {x=65535, y=10, z=0}
GameLabel
id: soul
anchors.top: slot9.bottom
anchors.bottom: slot8.bottom
anchors.left: slot9.left
anchors.right: slot9.right
margin-top: 5
text-align: center
image-source: /core_styles/styles/images/panel_flat.png
image-border: 1
GameLabel
id: capacity
anchors.top: slot10.bottom
anchors.bottom: slot8.bottom
anchors.left: slot10.left
anchors.right: slot10.right
margin-top: 5
text-align: center
image-source: /core_styles/styles/images/panel_flat.png
image-border: 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

View File

@@ -0,0 +1,202 @@
Outfit = {}
-- private variables
local window = nil
local m_creature = nil
local m_outfit = nil
local m_outfits = nil
local m_currentOutfit = 1
local m_currentColor = nil
local m_currentClothe = nil
-- private functions
local function onAddonCheckChange(addon, value)
if addon:isChecked() then
m_outfit.addons = m_outfit.addons + value
else
m_outfit.addons = m_outfit.addons - value
end
m_creature:setOutfit(m_outfit)
end
local function onColorCheckChange(color)
if color == m_currentColor then
color.onCheckChange = nil
color:setChecked(true)
color.onCheckChange = onColorCheckChange
else
m_currentColor.onCheckChange = nil
m_currentColor:setChecked(false)
m_currentColor.onCheckChange = onColorCheckChange
m_currentColor = color
if m_currentClothe:getId() == 'head' then
m_outfit.head = m_currentColor.colorId
elseif m_currentClothe:getId() == 'primary' then
m_outfit.body = m_currentColor.colorId
elseif m_currentClothe:getId() == 'secondary' then
m_outfit.legs = m_currentColor.colorId
elseif m_currentClothe:getId() == 'detail' then
m_outfit.feet = m_currentColor.colorId
end
m_creature:setOutfit(m_outfit)
end
end
local function onClotheCheckChange(clothe)
if clothe == m_currentClothe then
clothe.onCheckChange = nil
clothe:setChecked(true)
clothe.onCheckChange = onClotheCheckChange
else
m_currentClothe.onCheckChange = nil
m_currentClothe:setChecked(false)
m_currentClothe.onCheckChange = onClotheCheckChange
m_currentClothe = clothe
local color = 0
if m_currentClothe:getId() == 'head' then
color = m_outfit.head
elseif m_currentClothe:getId() == 'primary' then
color = m_outfit.body
elseif m_currentClothe:getId() == 'secondary' then
color = m_outfit.legs
elseif m_currentClothe:getId() == 'detail' then
color = m_outfit.feet
end
window:getChildById('color' .. color):setChecked(true)
end
end
local function update()
local nameWidget = window:getChildById('name')
nameWidget:setText(m_outfits[m_currentOutfit][2])
local availableAddons = m_outfits[m_currentOutfit][3]
local addon1 = window:getChildById('addon1')
local addon2 = window:getChildById('addon2')
local addon3 = window:getChildById('addon3')
addon1:setChecked(false)
addon2:setChecked(false)
addon3:setChecked(false)
addon1.onCheckChange = function(self) onAddonCheckChange(self, 1) end
addon2.onCheckChange = function(self) onAddonCheckChange(self, 2) end
addon3.onCheckChange = function(self) onAddonCheckChange(self, 4) end
addon1:setEnabled(false)
addon2:setEnabled(false)
addon3:setEnabled(false)
-- Maybe rework this someday
if availableAddons == 1 then
addon1:setEnabled(true)
elseif availableAddons == 2 then
addon2:setEnabled(true)
elseif availableAddons == 3 then
addon1:setEnabled(true)
addon2:setEnabled(true)
elseif availableAddons == 4 then
addon3:setEnabled(true)
elseif availableAddons == 5 then
addon1:setEnabled(true)
addon3:setEnabled(true)
elseif availableAddons == 6 then
addon2:setEnabled(true)
addon3:setEnabled(true)
elseif availableAddons == 7 then
addon1:setEnabled(true)
addon2:setEnabled(true)
addon3:setEnabled(true)
end
m_outfit.type = m_outfits[m_currentOutfit][1]
m_outfit.addons = 0
m_creature:setOutfit(m_outfit)
end
-- public functions
function Outfit.create(creature, outfitList)
Outfit.destroy()
window = displayUI('outfit.otui')
window:lock()
m_outfit = creature:getOutfit()
m_currentClothe = window:getChildById('head')
window:getChildById('head').onCheckChange = onClotheCheckChange
window:getChildById('primary').onCheckChange = onClotheCheckChange
window:getChildById('secondary').onCheckChange = onClotheCheckChange
window:getChildById('detail').onCheckChange = onClotheCheckChange
local creatureWidget = window:getChildById('creature')
creatureWidget:setCreature(creature)
for i=0,18 do
for j=0,6 do
local color = createWidget('Color', window)
local outfitColor = getOufitColor(j*19 + i)
color:setId('color' .. j*19+i)
color.colorId = j*19 + i
color:setImageColor(outfitColor)
color:setMarginTop(j * 3 + j * 14)
color:setMarginLeft(10 + i * 3 + i * 14)
if j*19 + i == m_outfit.head then
m_currentColor = color
color:setChecked(true)
end
color.onCheckChange = onColorCheckChange
end
end
m_creature = creature
m_outfits = outfitList
m_currentOutfit = 1
for i=1,#outfitList do
if outfitList[i][1] == m_outfit.type then
m_currentOutfit = i
break
end
end
update()
end
function Outfit.destroy()
if window ~= nil then
window:destroy()
window = nil
end
end
function Outfit.accept()
g_game.changeOutfit(m_outfit)
Outfit.destroy()
end
function Outfit.nextType()
m_currentOutfit = m_currentOutfit + 1
if m_currentOutfit > #m_outfits then
m_currentOutfit = 1
end
update()
end
function Outfit.previousType()
m_currentOutfit = m_currentOutfit - 1
if m_currentOutfit <= 0 then
m_currentOutfit = #m_outfits
end
update()
end
-- hooked events
connect(g_game, { onOpenOutfitWindow = Outfit.create,
onGameEnd = Outfit.destroy })

View File

@@ -0,0 +1,7 @@
Module
name: game_outfit
description: Change local player outfit
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'outfit'

View File

@@ -0,0 +1,128 @@
Color < ColorBox
anchors.top: head.top
anchors.left: head.right
Window
text: Select Outfit
size: 550 280
padding: 0 0 0 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
@onEnter: Outfit.accept()
@onEscape: Outfit.destroy()
Label
id: name
text: Outfit Name
width: 100
anchors.top: parent.top
anchors.left: parent.left
margin-top: 34
margin-left: 20
Creature
id: creature
anchors.top: name.bottom
anchors.left: name.left
margin-top: 5
padding: 16 4 4 16
fixed-creature-size: true
ButtonBox
id: head
text: Head
anchors.top: creature.top
anchors.left: creature.right
margin-left: 10
checked: true
ButtonBox
id: primary
text: Primary
anchors.top: prev.bottom
anchors.left: prev.left
ButtonBox
id: secondary
text: Secondary
anchors.top: prev.bottom
anchors.left: prev.left
ButtonBox
id: detail
text: Detail
anchors.top: prev.bottom
anchors.left: prev.left
Button
@onClick: Outfit.nextType()
text: >>
width: 32
margin-top: 4
anchors.top: creature.bottom
anchors.right: creature.right
Button
@onClick: Outfit.previousType()
text: <<
width: 32
margin-top: 4
anchors.top: creature.bottom
anchors.left: creature.left
CheckBox
id: addon1
text: Addon 1
enabled: false
margin-top: 10
width: 100
anchors.top: prev.bottom
anchors.left: prev.left
CheckBox
id: addon2
text: Addon 2
enabled: false
margin-top: 10
width: 100
anchors.top: prev.bottom
anchors.left: prev.left
CheckBox
id: addon3
text: Addon 3
enabled: false
margin-top: 10
width: 100
anchors.top: prev.bottom
anchors.left: prev.left
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin-left: 16
margin-right: 16
margin-bottom: 10
Button
id: buttonOk
text: Ok
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-bottom: 16
margin-right: 16
@onClick: Outfit.accept()
Button
id: buttonCancel
text: Cancel
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
margin-bottom: 16
margin-right: 16
@onClick: Outfit.destroy()

View File

@@ -0,0 +1,137 @@
Skills = {}
-- private variables
local skillsWindow
local skillsButton
-- private functions
local function getNumberString(number)
local out = ''
number = tostring(number):reverse()
for i=1,#number do
out = out .. number:sub(i, i)
if i % 3 == 0 and i ~= #number then
out = out .. ','
end
end
out = out:reverse()
return out
end
local function setSkillValue(id, value)
local skill = skillsWindow:recursiveGetChildById(id)
if skill then
local widget = skill:getChildById('value')
widget:setText(value)
end
end
local function setSkillPercent(id, percent, tooltip)
local skill = skillsWindow:recursiveGetChildById(id)
if skill then
local widget = skill:getChildById('percent')
widget:setPercent(percent)
if tooltip then
widget:setTooltip(tooltip)
end
end
end
-- public functions
function Skills.create()
skillsWindow = displayUI('skills.otui', g_game.gameRightPanel)
skillsWindow:hide()
skillsButton = TopMenu.addGameButton('skillsButton', 'Skills (Ctrl+S)', '/core_styles/icons/skills.png', Skills.toggle)
Keyboard.bindKeyDown('Ctrl+S', Skills.toggle)
end
function Skills.destroy()
Keyboard.unbindKeyDown('Ctrl+S')
skillsButton:destroy()
skillsButton = nil
skillsWindow:destroy()
skillsWindow = nil
end
function Skills.toggle()
local visible = not skillsWindow:isExplicitlyVisible()
skillsWindow:setVisible(visible)
skillsButton:setOn(visible)
end
function Skills.onSkillButtonClick(button)
local percentBar = button:getChildById('percent')
if percentBar then
percentBar:setVisible(not percentBar:isVisible())
if percentBar:isVisible() then
button:setHeight(21)
else
button:setHeight(21 - 6)
end
end
end
-- hooked events
function Skills.onExperienceChange(localPlayer, value)
setSkillValue('experience', getNumberString(value))
end
function Skills.onLevelChange(localPlayer, value, percent)
setSkillValue('level', getNumberString(value))
setSkillPercent('level', percent, 'You have ' .. (100 - percent) .. ' percent to go')
end
function Skills.onHealthChange(localPlayer, health, maxHealth)
setSkillValue('health', getNumberString(health))
end
function Skills.onManaChange(localPlayer, mana, maxMana)
setSkillValue('mana', getNumberString(mana))
end
function Skills.onSoulChange(localPlayer, soul)
setSkillValue('soul', soul)
end
function Skills.onFreeCapacityChange(localPlayer, freeCapacity)
setSkillValue('capacity', freeCapacity)
end
function Skills.onStaminaChange(localPlayer, stamina)
local hours = math.floor(stamina / 60)
local minutes = stamina % 60
if minutes < 10 then
minutes = '0' .. minutes
end
local percent = 100 * stamina / (42 * 60) -- max is 42 hours
setSkillValue('stamina', hours .. ":" .. minutes)
setSkillPercent('stamina', percent, 'You have ' .. percent .. ' percent')
end
function Skills.onMagicLevelChange(localPlayer, value, percent)
setSkillValue('magiclevel', value)
setSkillPercent('magiclevel', percent, 'You have ' .. (100 - percent) .. ' percent to go')
end
function Skills.onSkillChange(localPlayer, id, level, percent)
setSkillValue('skillId' .. id, level)
setSkillPercent('skillId' .. id, percent, 'You have ' .. (100 - percent) .. ' percent to go')
end
connect(g_game, { onGameStart = Skills.create,
onGameEnd = Skills.destroy })
connect(LocalPlayer, {
onExperienceChange = Skills.onExperienceChange,
onLevelChange = Skills.onLevelChange,
onHealthChange = Skills.onHealthChange,
onManaChange = Skills.onManaChange,
onSoulChange = Skills.onSoulChange,
onFreeCapacityChange = Skills.onFreeCapacityChange,
onStaminaChange = Skills.onStaminaChange,
onMagicLevelChange = Skills.onMagicLevelChange,
onSkillChange = Skills.onSkillChange })

View File

@@ -0,0 +1,7 @@
Module
name: game_skills
description: Manage skills window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'skills'

View File

@@ -0,0 +1,150 @@
SkillFirstWidget < UIWidget
SkillButton < UIButton
height: 21
margin-bottom: 2
&onClick: Skills.onSkillButtonClick
SkillNameLabel < GameLabel
font: verdana-11px-monochrome
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
SkillValueLabel < GameLabel
id: value
font: verdana-11px-monochrome
text-align: topright
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: prev.left
SkillPercentPanel < ProgressBar
id: percent
background-color: green
height: 5
margin-top: 15
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
tooltip: 0
MiniWindow
id: skillWindow
text: Skills
height: 350
Panel
id: skillPanel
anchors.fill: parent
layout: verticalBox
SkillButton
id: experience
height: 15
SkillNameLabel
text: Experience
SkillValueLabel
SkillButton
id: level
SkillNameLabel
text: Level
SkillValueLabel
SkillPercentPanel
background-color: red
SkillButton
id: health
height: 15
SkillNameLabel
text: Hit Points
SkillValueLabel
SkillButton
id: mana
height: 15
SkillNameLabel
text: Mana
SkillValueLabel
SkillButton
id: soul
height: 15
SkillNameLabel
text: Soul Points
SkillValueLabel
SkillButton
id: capacity
height: 15
SkillNameLabel
text: Capacity
SkillValueLabel
SkillButton
id: stamina
SkillNameLabel
text: Stamina
SkillValueLabel
SkillPercentPanel
SkillButton
id: magiclevel
SkillNameLabel
text: Magic Level
SkillValueLabel
SkillPercentPanel
background-color: red
SkillButton
id: skillId0
SkillNameLabel
text: Fist Fighting
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId1
SkillNameLabel
text: Club Fighting
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId2
SkillNameLabel
text: Sword Fighting
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId3
SkillNameLabel
text: Axe Fighting
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId4
SkillNameLabel
text: Distance Fighting
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId5
SkillNameLabel
text: Shielding
SkillValueLabel
SkillPercentPanel
SkillButton
id: skillId6
SkillNameLabel
text: Fishing
SkillValueLabel
SkillPercentPanel

View File

@@ -0,0 +1,117 @@
TextMessage = {}
-- require styles
importStyle 'textmessage.otui'
-- private variables
local MessageTypes = {
consoleRed = { color = '#F55E5E', consoleTab = 'Default' },
consoleOrange = { color = '#FE6500', consoleTab = 'Default' },
consoleBlue = { color = '#9F9DFD', consoleTab = 'Default' },
warning = { color = '#F55E5E', consoleTab = 'Server Log', labelId = 'centerWarning', wrap = true },
infoDescription = { color = '#00EB00', consoleTab = 'Server Log', labelId = 'centerInfo', consoleOption = 'showInfoMessagesInConsole', wrap = true },
eventAdvance = { color = '#FFFFFF', consoleTab = 'Server Log', labelId = 'centerAdvance', consoleOption = 'showEventMessagesInConsole', wrap = true },
eventDefault = { color = '#FFFFFF', consoleTab = 'Server Log', labelId = 'bottomStatus', consoleOption = 'showEventMessagesInConsole' },
statusDefault = { color = '#FFFFFF', consoleTab = 'Server Log', labelId = 'bottomStatus', consoleOption = 'showStatusMessagesInConsole' },
statusSmall = { color = '#FFFFFF', labelId = 'bottomStatus' },
}
local centerTextMessagePanel
local centerLabel
-- private functions
local function displayMessage(msgtype, msg, time)
if not g_game.isOnline() then return end
if msgtype.consoleTab ~= nil then
if msgtype.consoleOption == nil or Options[msgtype.consoleOption] then
Console.addText(msg, msgtype, msgtype.consoleTab)
end
end
if msgtype.labelId then
local label = g_game.gameMapPanel: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)
end
if not time then
time = math.max(#msg * 100, 4000)
else
time = time * 1000
end
removeEvent(label.hideEvent)
label.hideEvent = scheduleEvent(function() label:setVisible(false) end, time)
end
end
local function createTextMessageLabel(id, parent)
local label = createWidget('UILabel', parent)
label:setFont('verdana-11px-rounded')
label:setTextAlign(AlignCenter)
label:setId(id)
label:setMarginBottom(2)
label:setVisible(false)
return label
end
-- public functions
function TextMessage.create()
centerTextMessagePanel = createWidget('Panel', g_game.gameMapPanel)
centerTextMessagePanel:setId('centerTextMessagePanel')
local layout = UIVerticalLayout.create(centerTextMessagePanel)
layout:setFitChildren(true)
centerTextMessagePanel:setLayout(layout)
centerTextMessagePanel:setWidth(360)
centerTextMessagePanel:centerIn('parent')
createTextMessageLabel('centerWarning', centerTextMessagePanel)
createTextMessageLabel('centerAdvance', centerTextMessagePanel)
createTextMessageLabel('centerInfo', centerTextMessagePanel)
bottomStatusLabel = createTextMessageLabel('bottomStatus', g_game.gameMapPanel)
bottomStatusLabel:setHeight(16)
bottomStatusLabel:addAnchor(AnchorBottom, 'parent', AnchorBottom)
bottomStatusLabel:addAnchor(AnchorLeft, 'parent', AnchorLeft)
bottomStatusLabel:addAnchor(AnchorRight, 'parent', AnchorRight)
end
function TextMessage.displayStatus(msg, time)
displayMessage(MessageTypes.warning, msg)
end
function TextMessage.displayEventAdvance(msg, time)
displayMessage(MessageTypes.eventAdvance, msg, time)
end
function TextMessage.display(msgtypedesc, msg)
local msgtype = MessageTypes[msgtypedesc]
if msgtype then
displayMessage(msgtype, msg)
end
end
-- hooked events
local function onGameDeath()
local advanceLabel = g_game.gameMapPanel: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 })

View File

@@ -0,0 +1,7 @@
Module
name: game_textmessage
description: Manage game text messages
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'textmessage'

View File

@@ -0,0 +1,15 @@
CenterLabel < GameLabel
font: verdana-11px-rounded
height: 64
text-align: center
anchors.centerIn: parent
size: 360 264
BottomLabel < GameLabel
font: verdana-11px-rounded
height: 16
text-align: center
margin-bottom: 2
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right

View File

@@ -0,0 +1,39 @@
MainWindow
size: 256 128
text: Add to VIP list
@onEnter: VipList.addVip()
@onEscape: VipList.destroyAddWindow()
Label
text: Please enter a character name:
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
LineEdit
id: name
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 4
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin-bottom: 10
Button
text: Ok
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
@onClick: VipList.addVip()
Button
text: Cancel
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: VipList.destroyAddWindow()

View File

@@ -0,0 +1,129 @@
VipList = {}
-- private variables
local vipWindow
local vipButton
local addVipWindow
-- public functions
function VipList.create()
vipWindow = displayUI('viplist.otui', g_game.gameRightPanel)
vipWindow:hide()
vipButton = TopMenu.addGameButton('vipListButton', 'VIP list', 'viplist.png', VipList.toggle)
end
function VipList.destroy()
vipWindow:destroy()
vipWindow = nil
vipButton:destroy()
vipButton = nil
end
function VipList.toggle()
local visible = not vipWindow:isExplicitlyVisible()
vipWindow:setVisible(visible)
vipButton:setOn(visible)
end
function VipList.createAddWindow()
addVipWindow = displayUI('addvip.otui')
end
function VipList.destroyAddWindow()
addVipWindow:destroy()
addVipWindow = nil
end
function VipList.addVip()
g_game.addVip(addVipWindow:getChildById('name'):getText())
VipList.destroyAddWindow()
end
-- hooked events
function VipList.onAddVip(id, name, online)
local vipList = vipWindow:getChildById('vipList')
local label = createWidget('VipListLabel', nil)
label:setId('vip' .. id)
label:setText(name)
if online then
label:setColor('#00ff00')
else
label:setColor('#ff0000')
end
label.vipOnline = online
label:setPhantom(false)
connect(label, { onDoubleClick = function () g_game.openPrivateChannel(label:getText()) return true end } )
local nameLower = name:lower()
local childrenCount = vipList:getChildCount()
for i=1,childrenCount do
local child = vipList:getChildByIndex(i)
if online and not child.vipOnline then
vipList:insertChild(i, label)
return
end
if (not online and not child.vipOnline) or (online and child.vipOnline) then
local childText = child:getText():lower()
local length = math.min(childText:len(), nameLower:len())
for j=1,length do
if nameLower:byte(j) < childText:byte(j) then
vipList:insertChild(i, label)
return
elseif nameLower:byte(j) > childText:byte(j) then
break
end
end
end
end
vipList:insertChild(childrenCount+1, label)
end
function VipList.onVipStateChange(id, online)
local vipList = vipWindow:getChildById('vipList')
local label = vipList:getChildById('vip' .. id)
local text = label:getText()
vipList:removeChild(label)
VipList.onAddVip(id, text, online)
end
function VipList.onVipListMousePress(widget, mousePos, mouseButton)
if mouseButton ~= MouseRightButton then return end
local vipList = vipWindow:getChildById('vipList')
local menu = createWidget('PopupMenu')
menu:addOption('Add new VIP', function() VipList.createAddWindow() end)
menu:display(mousePos)
return true
end
function VipList.onVipListLabelMousePress(widget, mousePos, mouseButton)
if mouseButton ~= MouseRightButton then return end
local vipList = vipWindow:getChildById('vipList')
local menu = createWidget('PopupMenu')
menu:addOption('Add new VIP', function() VipList.createAddWindow() end)
menu:addOption('Remove ' .. widget:getText(), function() if widget then g_game.removeVip(widget:getId():sub(4)) vipList:removeChild(widget) end end)
menu:addSeparator()
menu:addOption('Copy Name', function() g_window.setClipboardText(widget:getText()) end)
menu:display(mousePos)
return true
end
connect(g_game, { onGameStart = VipList.create,
onGameEnd = VipList.destroy,
onAddVip = VipList.onAddVip,
onVipStateChange = VipList.onVipStateChange })

View File

@@ -0,0 +1,7 @@
Module
name: game_viplist
description: Manage vip list window
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
dofile 'viplist'

View File

@@ -0,0 +1,15 @@
VipListLabel < GameLabel
font: verdana-11px-monochrome
phantom: false
&onMousePress: VipList.onVipListLabelMousePress
MiniWindow
id: vipWindow
text: VIP List
height: 100
UIWidget
id: vipList
layout: verticalBox
anchors.fill: parent
&onMousePress: VipList.onVipListMousePress

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B