| @@ -0,0 +1,390 @@ | |||
| 1 | + | local SpelllistProfile = 'Default' | |
| 2 | + | ||
| 3 | + | spelllistWindow = nil | |
| 4 | + | spelllistButton = nil | |
| 5 | + | spellList = nil | |
| 6 | + | nameValueLabel = nil | |
| 7 | + | formulaValueLabel = nil | |
| 8 | + | vocationValueLabel = nil | |
| 9 | + | groupValueLabel = nil | |
| 10 | + | typeValueLabel = nil | |
| 11 | + | cooldownValueLabel = nil | |
| 12 | + | levelValueLabel = nil | |
| 13 | + | manaValueLabel = nil | |
| 14 | + | premiumValueLabel = nil | |
| 15 | + | descriptionValueLabel = nil | |
| 16 | + | ||
| 17 | + | vocationBoxAny = nil | |
| 18 | + | vocationBoxSorcerer = nil | |
| 19 | + | vocationBoxDruid = nil | |
| 20 | + | vocationBoxPaladin = nil | |
| 21 | + | vocationBoxKnight = nil | |
| 22 | + | ||
| 23 | + | groupBoxAny = nil | |
| 24 | + | groupBoxAttack = nil | |
| 25 | + | groupBoxHealing = nil | |
| 26 | + | groupBoxSupport = nil | |
| 27 | + | ||
| 28 | + | premiumBoxAny = nil | |
| 29 | + | premiumBoxNo = nil | |
| 30 | + | premiumBoxYes = nil | |
| 31 | + | ||
| 32 | + | vocationRadioGroup = nil | |
| 33 | + | groupRadioGroup = nil | |
| 34 | + | premiumRadioGroup = nil | |
| 35 | + | ||
| 36 | + | -- consts | |
| 37 | + | FILTER_PREMIUM_ANY = 0 | |
| 38 | + | FILTER_PREMIUM_NO = 1 | |
| 39 | + | FILTER_PREMIUM_YES = 2 | |
| 40 | + | ||
| 41 | + | FILTER_VOCATION_ANY = 0 | |
| 42 | + | FILTER_VOCATION_SORCERER = 1 | |
| 43 | + | FILTER_VOCATION_DRUID = 2 | |
| 44 | + | FILTER_VOCATION_PALADIN = 3 | |
| 45 | + | FILTER_VOCATION_KNIGHT = 4 | |
| 46 | + | ||
| 47 | + | FILTER_GROUP_ANY = 0 | |
| 48 | + | FILTER_GROUP_ATTACK = 1 | |
| 49 | + | FILTER_GROUP_HEALING = 2 | |
| 50 | + | FILTER_GROUP_SUPPORT = 3 | |
| 51 | + | ||
| 52 | + | -- Filter Settings | |
| 53 | + | local filters = { | |
| 54 | + | level = false, | |
| 55 | + | vocation = false, | |
| 56 | + | ||
| 57 | + | vocationId = FILTER_VOCATION_ANY, | |
| 58 | + | premium = FILTER_PREMIUM_ANY, | |
| 59 | + | groupId = FILTER_GROUP_ANY | |
| 60 | + | } | |
| 61 | + | ||
| 62 | + | function getSpelllistProfile() | |
| 63 | + | return SpelllistProfile | |
| 64 | + | end | |
| 65 | + | ||
| 66 | + | function setSpelllistProfile(name) | |
| 67 | + | if SpelllistProfile == name then return end | |
| 68 | + | ||
| 69 | + | if SpelllistSettings[name] and SpellInfo[name] then | |
| 70 | + | local oldProfile = SpelllistProfile | |
| 71 | + | SpelllistProfile = name | |
| 72 | + | changeSpelllistProfile(oldProfile) | |
| 73 | + | else | |
| 74 | + | perror('Spelllist profile \'' .. name .. '\' could not be set.') | |
| 75 | + | end | |
| 76 | + | end | |
| 77 | + | ||
| 78 | + | function online() | |
| 79 | + | if g_game.getFeature(GameSpellList) then | |
| 80 | + | --spelllistButton:show() | |
| 81 | + | else | |
| 82 | + | --spelllistButton:hide() | |
| 83 | + | end | |
| 84 | + | ||
| 85 | + | -- Vocation is only send in newer clients | |
| 86 | + | if g_game.getClientVersion() >= 950 then | |
| 87 | + | spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true) | |
| 88 | + | else | |
| 89 | + | spelllistWindow:getChildById('buttonFilterVocation'):setVisible(false) | |
| 90 | + | end | |
| 91 | + | end | |
| 92 | + | ||
| 93 | + | function offline() | |
| 94 | + | resetWindow() | |
| 95 | + | end | |
| 96 | + | ||
| 97 | + | function init() | |
| 98 | + | connect(g_game, { onGameStart = online, | |
| 99 | + | onGameEnd = offline }) | |
| 100 | + | ||
| 101 | + | spelllistWindow = g_ui.displayUI('spelllist', modules.game_interface.getRightPanel()) | |
| 102 | + | spelllistWindow:hide() | |
| 103 | + | ||
| 104 | + | --spelllistButton = modules.client_topmenu.addRightGameToggleButton('spelllistButton', tr('Spell List'), '/images/topbuttons/spelllist', toggle, false, 4) | |
| 105 | + | --spelllistButton:setOn(false) | |
| 106 | + | ||
| 107 | + | nameValueLabel = spelllistWindow:getChildById('labelNameValue') | |
| 108 | + | formulaValueLabel = spelllistWindow:getChildById('labelFormulaValue') | |
| 109 | + | vocationValueLabel = spelllistWindow:getChildById('labelVocationValue') | |
| 110 | + | groupValueLabel = spelllistWindow:getChildById('labelGroupValue') | |
| 111 | + | typeValueLabel = spelllistWindow:getChildById('labelTypeValue') | |
| 112 | + | cooldownValueLabel = spelllistWindow:getChildById('labelCooldownValue') | |
| 113 | + | levelValueLabel = spelllistWindow:getChildById('labelLevelValue') | |
| 114 | + | manaValueLabel = spelllistWindow:getChildById('labelManaValue') | |
| 115 | + | premiumValueLabel = spelllistWindow:getChildById('labelPremiumValue') | |
| 116 | + | descriptionValueLabel = spelllistWindow:getChildById('labelDescriptionValue') | |
| 117 | + | ||
| 118 | + | vocationBoxAny = spelllistWindow:getChildById('vocationBoxAny') | |
| 119 | + | vocationBoxSorcerer = spelllistWindow:getChildById('vocationBoxSorcerer') | |
| 120 | + | vocationBoxDruid = spelllistWindow:getChildById('vocationBoxDruid') | |
| 121 | + | vocationBoxPaladin = spelllistWindow:getChildById('vocationBoxPaladin') | |
| 122 | + | vocationBoxKnight = spelllistWindow:getChildById('vocationBoxKnight') | |
| 123 | + | ||
| 124 | + | groupBoxAny = spelllistWindow:getChildById('groupBoxAny') | |
| 125 | + | groupBoxAttack = spelllistWindow:getChildById('groupBoxAttack') | |
| 126 | + | groupBoxHealing = spelllistWindow:getChildById('groupBoxHealing') | |
| 127 | + | groupBoxSupport = spelllistWindow:getChildById('groupBoxSupport') | |
| 128 | + | ||
| 129 | + | premiumBoxAny = spelllistWindow:getChildById('premiumBoxAny') | |
| 130 | + | premiumBoxYes = spelllistWindow:getChildById('premiumBoxYes') | |
| 131 | + | premiumBoxNo = spelllistWindow:getChildById('premiumBoxNo') | |
| 132 | + | ||
| 133 | + | vocationRadioGroup = UIRadioGroup.create() | |
| 134 | + | vocationRadioGroup:addWidget(vocationBoxAny) | |
| 135 | + | vocationRadioGroup:addWidget(vocationBoxSorcerer) | |
| 136 | + | vocationRadioGroup:addWidget(vocationBoxDruid) | |
| 137 | + | vocationRadioGroup:addWidget(vocationBoxPaladin) | |
| 138 | + | vocationRadioGroup:addWidget(vocationBoxKnight) | |
| 139 | + | ||
| 140 | + | groupRadioGroup = UIRadioGroup.create() | |
| 141 | + | groupRadioGroup:addWidget(groupBoxAny) | |
| 142 | + | groupRadioGroup:addWidget(groupBoxAttack) | |
| 143 | + | groupRadioGroup:addWidget(groupBoxHealing) | |
| 144 | + | groupRadioGroup:addWidget(groupBoxSupport) | |
| 145 | + | ||
| 146 | + | premiumRadioGroup = UIRadioGroup.create() | |
| 147 | + | premiumRadioGroup:addWidget(premiumBoxAny) | |
| 148 | + | premiumRadioGroup:addWidget(premiumBoxYes) | |
| 149 | + | premiumRadioGroup:addWidget(premiumBoxNo) | |
| 150 | + | ||
| 151 | + | premiumRadioGroup:selectWidget(premiumBoxAny) | |
| 152 | + | vocationRadioGroup:selectWidget(vocationBoxAny) | |
| 153 | + | groupRadioGroup:selectWidget(groupBoxAny) | |
| 154 | + | ||
| 155 | + | vocationRadioGroup.onSelectionChange = toggleFilter | |
| 156 | + | groupRadioGroup.onSelectionChange = toggleFilter | |
| 157 | + | premiumRadioGroup.onSelectionChange = toggleFilter | |
| 158 | + | ||
| 159 | + | spellList = spelllistWindow:getChildById('spellList') | |
| 160 | + | ||
| 161 | + | g_keyboard.bindKeyPress('Down', function() spellList:focusNextChild(KeyboardFocusReason) end, spelllistWindow) | |
| 162 | + | g_keyboard.bindKeyPress('Up', function() spellList:focusPreviousChild(KeyboardFocusReason) end, spelllistWindow) | |
| 163 | + | ||
| 164 | + | initializeSpelllist() | |
| 165 | + | resizeWindow() | |
| 166 | + | ||
| 167 | + | if g_game.isOnline() then | |
| 168 | + | online() | |
| 169 | + | end | |
| 170 | + | end | |
| 171 | + | ||
| 172 | + | function terminate() | |
| 173 | + | disconnect(g_game, { onGameStart = online, | |
| 174 | + | onGameEnd = offline }) | |
| 175 | + | ||
| 176 | + | disconnect(spellList, { onChildFocusChange = function(self, focusedChild) | |
| 177 | + | if focusedChild == nil then return end | |
| 178 | + | updateSpellInformation(focusedChild) | |
| 179 | + | end }) | |
| 180 | + | ||
| 181 | + | spelllistWindow:destroy() | |
| 182 | + | --spelllistButton:destroy() | |
| 183 | + | ||
| 184 | + | vocationRadioGroup:destroy() | |
| 185 | + | groupRadioGroup:destroy() | |
| 186 | + | premiumRadioGroup:destroy() | |
| 187 | + | end | |
| 188 | + | ||
| 189 | + | function initializeSpelllist() | |
| 190 | + | for i = 1, #SpelllistSettings[SpelllistProfile].spellOrder do | |
| 191 | + | local spell = SpelllistSettings[SpelllistProfile].spellOrder[i] | |
| 192 | + | local info = SpellInfo[SpelllistProfile][spell] | |
| 193 | + | ||
| 194 | + | local tmpLabel = g_ui.createWidget('SpellListLabel', spellList) | |
| 195 | + | tmpLabel:setId(spell) | |
| 196 | + | tmpLabel:setText(spell .. '\n\'' .. info.words .. '\'') | |
| 197 | + | tmpLabel:setPhantom(false) | |
| 198 | + | ||
| 199 | + | local iconId = tonumber(info.icon) | |
| 200 | + | if not iconId and SpellIcons[info.icon] then | |
| 201 | + | iconId = SpellIcons[info.icon][1] | |
| 202 | + | end | |
| 203 | + | ||
| 204 | + | if not(iconId) then | |
| 205 | + | perror('Spell icon \'' .. info.icon .. '\' not found.') | |
| 206 | + | end | |
| 207 | + | ||
| 208 | + | tmpLabel:setHeight(SpelllistSettings[SpelllistProfile].iconSize.height + 4) | |
| 209 | + | tmpLabel:setTextOffset(topoint((SpelllistSettings[SpelllistProfile].iconSize.width + 10) .. ' ' .. (SpelllistSettings[SpelllistProfile].iconSize.height - 32)/2 + 3)) | |
| 210 | + | tmpLabel:setImageSource(SpelllistSettings[SpelllistProfile].iconFile) | |
| 211 | + | tmpLabel:setImageClip(Spells.getImageClip(iconId, SpelllistProfile)) | |
| 212 | + | tmpLabel:setImageSize(tosize(SpelllistSettings[SpelllistProfile].iconSize.width .. ' ' .. SpelllistSettings[SpelllistProfile].iconSize.height)) | |
| 213 | + | tmpLabel.onClick = updateSpellInformation | |
| 214 | + | end | |
| 215 | + | ||
| 216 | + | connect(spellList, { onChildFocusChange = function(self, focusedChild) | |
| 217 | + | if focusedChild == nil then return end | |
| 218 | + | updateSpellInformation(focusedChild) | |
| 219 | + | end }) | |
| 220 | + | end | |
| 221 | + | ||
| 222 | + | function changeSpelllistProfile(oldProfile) | |
| 223 | + | -- Delete old labels | |
| 224 | + | for i = 1, #SpelllistSettings[oldProfile].spellOrder do | |
| 225 | + | local spell = SpelllistSettings[oldProfile].spellOrder[i] | |
| 226 | + | local tmpLabel = spellList:getChildById(spell) | |
| 227 | + | ||
| 228 | + | tmpLabel:destroy() | |
| 229 | + | end | |
| 230 | + | ||
| 231 | + | -- Create new spelllist and ajust window | |
| 232 | + | initializeSpelllist() | |
| 233 | + | resizeWindow() | |
| 234 | + | resetWindow() | |
| 235 | + | end | |
| 236 | + | ||
| 237 | + | function updateSpelllist() | |
| 238 | + | for i = 1, #SpelllistSettings[SpelllistProfile].spellOrder do | |
| 239 | + | local spell = SpelllistSettings[SpelllistProfile].spellOrder[i] | |
| 240 | + | local info = SpellInfo[SpelllistProfile][spell] | |
| 241 | + | local tmpLabel = spellList:getChildById(spell) | |
| 242 | + | ||
| 243 | + | local localPlayer = g_game.getLocalPlayer() | |
| 244 | + | if (not(filters.level) or info.level <= localPlayer:getLevel()) and (not(filters.vocation) or table.find(info.vocations, localPlayer:getVocation())) and (filters.vocationId == FILTER_VOCATION_ANY or table.find(info.vocations, filters.vocationId) or table.find(info.vocations, filters.vocationId+4)) and (filters.groupId == FILTER_GROUP_ANY or info.group[filters.groupId]) and (filters.premium == FILTER_PREMIUM_ANY or (info.premium and filters.premium == FILTER_PREMIUM_YES) or (not(info.premium) and filters.premium == FILTER_PREMIUM_NO)) then | |
| 245 | + | tmpLabel:setVisible(true) | |
| 246 | + | else | |
| 247 | + | tmpLabel:setVisible(false) | |
| 248 | + | end | |
| 249 | + | end | |
| 250 | + | end | |
| 251 | + | ||
| 252 | + | function updateSpellInformation(widget) | |
| 253 | + | local spell = widget:getId() | |
| 254 | + | ||
| 255 | + | local name = '' | |
| 256 | + | local formula = '' | |
| 257 | + | local vocation = '' | |
| 258 | + | local group = '' | |
| 259 | + | local type = '' | |
| 260 | + | local cooldown = '' | |
| 261 | + | local level = '' | |
| 262 | + | local mana = '' | |
| 263 | + | local premium = '' | |
| 264 | + | local description = '' | |
| 265 | + | ||
| 266 | + | if SpellInfo[SpelllistProfile][spell] then | |
| 267 | + | local info = SpellInfo[SpelllistProfile][spell] | |
| 268 | + | ||
| 269 | + | name = spell | |
| 270 | + | formula = info.words | |
| 271 | + | ||
| 272 | + | for i = 1, #info.vocations do | |
| 273 | + | local vocationId = info.vocations[i] | |
| 274 | + | if vocationId <= 4 or not(table.find(info.vocations, (vocationId-4))) then | |
| 275 | + | vocation = vocation .. (vocation:len() == 0 and '' or ', ') .. VocationNames[vocationId] | |
| 276 | + | end | |
| 277 | + | end | |
| 278 | + | ||
| 279 | + | cooldown = (info.exhaustion / 1000) .. 's' | |
| 280 | + | for groupId, groupName in ipairs(SpellGroups) do | |
| 281 | + | if info.group[groupId] then | |
| 282 | + | group = group .. (group:len() == 0 and '' or ' / ') .. groupName | |
| 283 | + | cooldown = cooldown .. ' / ' .. (info.group[groupId] / 1000) .. 's' | |
| 284 | + | end | |
| 285 | + | end | |
| 286 | + | ||
| 287 | + | type = info.type | |
| 288 | + | level = info.level | |
| 289 | + | mana = info.mana .. ' / ' .. info.soul | |
| 290 | + | premium = (info.premium and 'yes' or 'no') | |
| 291 | + | description = info.description or '-' | |
| 292 | + | end | |
| 293 | + | ||
| 294 | + | nameValueLabel:setText(name) | |
| 295 | + | formulaValueLabel:setText(formula) | |
| 296 | + | vocationValueLabel:setText(vocation) | |
| 297 | + | groupValueLabel:setText(group) | |
| 298 | + | typeValueLabel:setText(type) | |
| 299 | + | cooldownValueLabel:setText(cooldown) | |
| 300 | + | levelValueLabel:setText(level) | |
| 301 | + | manaValueLabel:setText(mana) | |
| 302 | + | premiumValueLabel:setText(premium) | |
| 303 | + | descriptionValueLabel:setText(description) | |
| 304 | + | end | |
| 305 | + | ||
| 306 | + | function toggle() | |
| 307 | + | --[[if spelllistButton:isOn() then | |
| 308 | + | spelllistButton:setOn(false) | |
| 309 | + | spelllistWindow:hide() | |
| 310 | + | else | |
| 311 | + | spelllistButton:setOn(true) | |
| 312 | + | spelllistWindow:show() | |
| 313 | + | spelllistWindow:raise() | |
| 314 | + | spelllistWindow:focus() | |
| 315 | + | end]] | |
| 316 | + | end | |
| 317 | + | ||
| 318 | + | function toggleFilter(widget, selectedWidget) | |
| 319 | + | if widget == vocationRadioGroup then | |
| 320 | + | local boxId = selectedWidget:getId() | |
| 321 | + | if boxId == 'vocationBoxAny' then | |
| 322 | + | filters.vocationId = FILTER_VOCATION_ANY | |
| 323 | + | elseif boxId == 'vocationBoxSorcerer' then | |
| 324 | + | filters.vocationId = FILTER_VOCATION_SORCERER | |
| 325 | + | elseif boxId == 'vocationBoxDruid' then | |
| 326 | + | filters.vocationId = FILTER_VOCATION_DRUID | |
| 327 | + | elseif boxId == 'vocationBoxPaladin' then | |
| 328 | + | filters.vocationId = FILTER_VOCATION_PALADIN | |
| 329 | + | elseif boxId == 'vocationBoxKnight' then | |
| 330 | + | filters.vocationId = FILTER_VOCATION_KNIGHT | |
| 331 | + | end | |
| 332 | + | elseif widget == groupRadioGroup then | |
| 333 | + | local boxId = selectedWidget:getId() | |
| 334 | + | if boxId == 'groupBoxAny' then | |
| 335 | + | filters.groupId = FILTER_GROUP_ANY | |
| 336 | + | elseif boxId == 'groupBoxAttack' then | |
| 337 | + | filters.groupId = FILTER_GROUP_ATTACK | |
| 338 | + | elseif boxId == 'groupBoxHealing' then | |
| 339 | + | filters.groupId = FILTER_GROUP_HEALING | |
| 340 | + | elseif boxId == 'groupBoxSupport' then | |
| 341 | + | filters.groupId = FILTER_GROUP_SUPPORT | |
| 342 | + | end | |
| 343 | + | elseif widget == premiumRadioGroup then | |
| 344 | + | local boxId = selectedWidget:getId() | |
| 345 | + | if boxId == 'premiumBoxAny' then | |
| 346 | + | filters.premium = FILTER_PREMIUM_ANY | |
| 347 | + | elseif boxId == 'premiumBoxNo' then | |
| 348 | + | filters.premium = FILTER_PREMIUM_NO | |
| 349 | + | elseif boxId == 'premiumBoxYes' then | |
| 350 | + | filters.premium = FILTER_PREMIUM_YES | |
| 351 | + | end | |
| 352 | + | else | |
| 353 | + | local id = widget:getId() | |
| 354 | + | if id == 'buttonFilterLevel' then | |
| 355 | + | filters.level = not(filters.level) | |
| 356 | + | widget:setOn(filters.level) | |
| 357 | + | elseif id == 'buttonFilterVocation' then | |
| 358 | + | filters.vocation = not(filters.vocation) | |
| 359 | + | widget:setOn(filters.vocation) | |
| 360 | + | end | |
| 361 | + | end | |
| 362 | + | ||
| 363 | + | updateSpelllist() | |
| 364 | + | end | |
| 365 | + | ||
| 366 | + | function resizeWindow() | |
| 367 | + | spelllistWindow:setWidth(SpelllistSettings['Default'].spellWindowWidth + SpelllistSettings[SpelllistProfile].iconSize.width - 32) | |
| 368 | + | spellList:setWidth(SpelllistSettings['Default'].spellListWidth + SpelllistSettings[SpelllistProfile].iconSize.width - 32) | |
| 369 | + | end | |
| 370 | + | ||
| 371 | + | function resetWindow() | |
| 372 | + | spelllistWindow:hide() | |
| 373 | + | --spelllistButton:setOn(false) | |
| 374 | + | ||
| 375 | + | -- Resetting filters | |
| 376 | + | filters.level = false | |
| 377 | + | filters.vocation = false | |
| 378 | + | ||
| 379 | + | local buttonFilterLevel = spelllistWindow:getChildById('buttonFilterLevel') | |
| 380 | + | buttonFilterLevel:setOn(filters.level) | |
| 381 | + | ||
| 382 | + | local buttonFilterVocation = spelllistWindow:getChildById('buttonFilterVocation') | |
| 383 | + | buttonFilterVocation:setOn(filters.vocation) | |
| 384 | + | ||
| 385 | + | vocationRadioGroup:selectWidget(vocationBoxAny) | |
| 386 | + | groupRadioGroup:selectWidget(groupBoxAny) | |
| 387 | + | premiumRadioGroup:selectWidget(premiumBoxAny) | |
| 388 | + | ||
| 389 | + | updateSpelllist() | |
| 390 | + | end |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | Module | |
| 2 | + | name: game_spelllist | |
| 3 | + | description: View available spells | |
| 4 | + | author: Summ, Edubart | |
| 5 | + | website: https://github.com/edubart/otclient | |
| 6 | + | sandboxed: true | |
| 7 | + | scripts: [ spelllist ] | |
| 8 | + | @onLoad: init() | |
| 9 | + | @onUnload: terminate() |
| @@ -0,0 +1,326 @@ | |||
| 1 | + | SpellListLabel < Label | |
| 2 | + | font: verdana-11px-monochrome | |
| 3 | + | background-color: alpha | |
| 4 | + | text-offset: 42 3 | |
| 5 | + | focusable: true | |
| 6 | + | height: 36 | |
| 7 | + | image-clip: 0 0 32 32 | |
| 8 | + | image-size: 32 32 | |
| 9 | + | image-offset: 2 2 | |
| 10 | + | image-source: /images/game/spells/defaultspells | |
| 11 | + | ||
| 12 | + | $focus: | |
| 13 | + | background-color: #ffffff22 | |
| 14 | + | color: #ffffff | |
| 15 | + | ||
| 16 | + | SpellInfoLabel < Label | |
| 17 | + | width: 70 | |
| 18 | + | font: verdana-11px-monochrome | |
| 19 | + | text-align: right | |
| 20 | + | margin-left: 10 | |
| 21 | + | margin-top: 5 | |
| 22 | + | ||
| 23 | + | SpellInfoValueLabel < Label | |
| 24 | + | text-align: left | |
| 25 | + | width: 190 | |
| 26 | + | margin-left: 10 | |
| 27 | + | margin-top: 5 | |
| 28 | + | ||
| 29 | + | FilterButton < Button | |
| 30 | + | width: 64 | |
| 31 | + | anchors.left: prev.right | |
| 32 | + | anchors.top: spellList.bottom | |
| 33 | + | @onClick: toggleFilter(self) | |
| 34 | + | margin: 5 0 0 6 | |
| 35 | + | color: #630000 | |
| 36 | + | $on: | |
| 37 | + | color: green | |
| 38 | + | ||
| 39 | + | MainWindow | |
| 40 | + | id: spelllistWindow | |
| 41 | + | !text: tr('Spell List') | |
| 42 | + | size: 550 400 | |
| 43 | + | @onEscape: toggle() | |
| 44 | + | ||
| 45 | + | TextList | |
| 46 | + | id: spellList | |
| 47 | + | vertical-scrollbar: spellsScrollBar | |
| 48 | + | anchors.top: parent.top | |
| 49 | + | anchors.left: parent.left | |
| 50 | + | anchors.bottom: next.top | |
| 51 | + | margin-bottom: 10 | |
| 52 | + | padding: 1 | |
| 53 | + | width: 210 | |
| 54 | + | focusable: false | |
| 55 | + | ||
| 56 | + | Button | |
| 57 | + | id: buttonCancel | |
| 58 | + | !text: tr('Close') | |
| 59 | + | width: 64 | |
| 60 | + | anchors.right: parent.right | |
| 61 | + | anchors.bottom: parent.bottom | |
| 62 | + | @onClick: toggle() | |
| 63 | + | ||
| 64 | + | VerticalScrollBar | |
| 65 | + | id: spellsScrollBar | |
| 66 | + | anchors.top: spellList.top | |
| 67 | + | anchors.bottom: spellList.bottom | |
| 68 | + | anchors.right: spellList.right | |
| 69 | + | step: 50 | |
| 70 | + | pixels-scroll: true | |
| 71 | + | ||
| 72 | + | SpellInfoLabel | |
| 73 | + | id: labelName | |
| 74 | + | anchors.left: spellList.right | |
| 75 | + | anchors.top: spellList.top | |
| 76 | + | !text: tr('Name') .. ':' | |
| 77 | + | ||
| 78 | + | Label | |
| 79 | + | anchors.left: parent.left | |
| 80 | + | anchors.top: spellList.bottom | |
| 81 | + | !text: tr('Filters') .. ':' | |
| 82 | + | margin-top: 8 | |
| 83 | + | ||
| 84 | + | FilterButton | |
| 85 | + | id: buttonFilterLevel | |
| 86 | + | !text: tr('Level') | |
| 87 | + | !tooltip: tr('Hide spells for higher exp. levels') | |
| 88 | + | ||
| 89 | + | FilterButton | |
| 90 | + | id: buttonFilterVocation | |
| 91 | + | !text: tr('Vocation') | |
| 92 | + | !tooltip: tr('Hide spells for other vocations') | |
| 93 | + | ||
| 94 | + | SpellInfoLabel | |
| 95 | + | id: labelFormula | |
| 96 | + | anchors.left: spellList.right | |
| 97 | + | anchors.top: labelName.bottom | |
| 98 | + | !text: tr('Formula') .. ':' | |
| 99 | + | ||
| 100 | + | ||
| 101 | + | SpellInfoLabel | |
| 102 | + | id: labelVocation | |
| 103 | + | anchors.left: spellList.right | |
| 104 | + | anchors.top: labelFormula.bottom | |
| 105 | + | !text: tr('Vocation') .. ':' | |
| 106 | + | ||
| 107 | + | SpellInfoLabel | |
| 108 | + | id: labelGroup | |
| 109 | + | anchors.left: spellList.right | |
| 110 | + | anchors.top: labelVocation.bottom | |
| 111 | + | !text: tr('Group') .. ':' | |
| 112 | + | ||
| 113 | + | SpellInfoLabel | |
| 114 | + | id: labelType | |
| 115 | + | anchors.left: spellList.right | |
| 116 | + | anchors.top: labelGroup.bottom | |
| 117 | + | !text: tr('Type') .. ':' | |
| 118 | + | ||
| 119 | + | SpellInfoLabel | |
| 120 | + | id: labelCooldown | |
| 121 | + | anchors.left: spellList.right | |
| 122 | + | anchors.top: labelType.bottom | |
| 123 | + | !text: tr('Cooldown') .. ':' | |
| 124 | + | ||
| 125 | + | SpellInfoLabel | |
| 126 | + | id: labelLevel | |
| 127 | + | anchors.left: spellList.right | |
| 128 | + | anchors.top: labelCooldown.bottom | |
| 129 | + | !text: tr('Level') .. ':' | |
| 130 | + | ||
| 131 | + | SpellInfoLabel | |
| 132 | + | id: labelMana | |
| 133 | + | anchors.left: spellList.right | |
| 134 | + | anchors.top: labelLevel.bottom | |
| 135 | + | !text: tr('Mana') .. ' / ' .. tr('Soul') .. ':' | |
| 136 | + | ||
| 137 | + | SpellInfoLabel | |
| 138 | + | id: labelPremium | |
| 139 | + | anchors.left: spellList.right | |
| 140 | + | anchors.top: labelMana.bottom | |
| 141 | + | !text: tr('Premium') .. ':' | |
| 142 | + | ||
| 143 | + | SpellInfoLabel | |
| 144 | + | id: labelDescription | |
| 145 | + | anchors.left: spellList.right | |
| 146 | + | anchors.top: labelPremium.bottom | |
| 147 | + | !text: tr('Description') .. ':' | |
| 148 | + | ||
| 149 | + | SpellInfoValueLabel | |
| 150 | + | id: labelNameValue | |
| 151 | + | anchors.left: labelName.right | |
| 152 | + | anchors.top: spellList.top | |
| 153 | + | ||
| 154 | + | SpellInfoValueLabel | |
| 155 | + | id: labelFormulaValue | |
| 156 | + | anchors.left: labelFormula.right | |
| 157 | + | anchors.top: labelNameValue.bottom | |
| 158 | + | ||
| 159 | + | SpellInfoValueLabel | |
| 160 | + | id: labelVocationValue | |
| 161 | + | anchors.left: labelVocation.right | |
| 162 | + | anchors.top: labelFormulaValue.bottom | |
| 163 | + | ||
| 164 | + | SpellInfoValueLabel | |
| 165 | + | id: labelGroupValue | |
| 166 | + | anchors.left: labelGroup.right | |
| 167 | + | anchors.top: labelVocationValue.bottom | |
| 168 | + | ||
| 169 | + | SpellInfoValueLabel | |
| 170 | + | id: labelTypeValue | |
| 171 | + | anchors.left: labelType.right | |
| 172 | + | anchors.top: labelGroupValue.bottom | |
| 173 | + | ||
| 174 | + | SpellInfoValueLabel | |
| 175 | + | id: labelCooldownValue | |
| 176 | + | anchors.left: labelCooldown.right | |
| 177 | + | anchors.top: labelTypeValue.bottom | |
| 178 | + | ||
| 179 | + | SpellInfoValueLabel | |
| 180 | + | id: labelLevelValue | |
| 181 | + | anchors.left: labelLevel.right | |
| 182 | + | anchors.top: labelCooldownValue.bottom | |
| 183 | + | ||
| 184 | + | SpellInfoValueLabel | |
| 185 | + | id: labelManaValue | |
| 186 | + | anchors.left: labelMana.right | |
| 187 | + | anchors.top: labelLevelValue.bottom | |
| 188 | + | ||
| 189 | + | SpellInfoValueLabel | |
| 190 | + | id: labelPremiumValue | |
| 191 | + | anchors.left: labelPremium.right | |
| 192 | + | anchors.top: labelManaValue.bottom | |
| 193 | + | ||
| 194 | + | SpellInfoValueLabel | |
| 195 | + | id: labelDescriptionValue | |
| 196 | + | anchors.left: labelDescription.right | |
| 197 | + | anchors.top: labelPremiumValue.bottom | |
| 198 | + | ||
| 199 | + | Label | |
| 200 | + | id: labelVocationFilter | |
| 201 | + | anchors.top: labelPremium.bottom | |
| 202 | + | anchors.left: spellList.right | |
| 203 | + | width: 70 | |
| 204 | + | font: verdana-11px-monochrome | |
| 205 | + | !text: tr('Vocation') | |
| 206 | + | margin-top: 30 | |
| 207 | + | margin-left: 20 | |
| 208 | + | ||
| 209 | + | CheckBox | |
| 210 | + | id: vocationBoxAny | |
| 211 | + | anchors.left: prev.left | |
| 212 | + | anchors.top: prev.bottom | |
| 213 | + | margin-top: 3 | |
| 214 | + | margin-left: 3 | |
| 215 | + | !text: tr('Any') | |
| 216 | + | width: 75 | |
| 217 | + | ||
| 218 | + | CheckBox | |
| 219 | + | id: vocationBoxSorcerer | |
| 220 | + | anchors.left: prev.left | |
| 221 | + | anchors.top: prev.bottom | |
| 222 | + | margin-top: 3 | |
| 223 | + | !text: tr('Sorcerer') | |
| 224 | + | width: 75 | |
| 225 | + | ||
| 226 | + | CheckBox | |
| 227 | + | id: vocationBoxDruid | |
| 228 | + | anchors.left: prev.left | |
| 229 | + | anchors.top: prev.bottom | |
| 230 | + | margin-top: 3 | |
| 231 | + | !text: tr('Druid') | |
| 232 | + | width: 75 | |
| 233 | + | ||
| 234 | + | CheckBox | |
| 235 | + | id: vocationBoxPaladin | |
| 236 | + | anchors.left: prev.left | |
| 237 | + | anchors.top: prev.bottom | |
| 238 | + | margin-top: 3 | |
| 239 | + | !text: tr('Paladin') | |
| 240 | + | width: 75 | |
| 241 | + | ||
| 242 | + | CheckBox | |
| 243 | + | id: vocationBoxKnight | |
| 244 | + | anchors.left: prev.left | |
| 245 | + | anchors.top: prev.bottom | |
| 246 | + | margin-top: 3 | |
| 247 | + | !text: tr('Knight') | |
| 248 | + | width: 75 | |
| 249 | + | ||
| 250 | + | Label | |
| 251 | + | id: labelGroupFilter | |
| 252 | + | anchors.top: labelPremium.bottom | |
| 253 | + | anchors.left: labelVocationFilter.right | |
| 254 | + | width: 70 | |
| 255 | + | font: verdana-11px-monochrome | |
| 256 | + | !text: tr('Group') | |
| 257 | + | margin-top: 30 | |
| 258 | + | margin-left: 20 | |
| 259 | + | ||
| 260 | + | CheckBox | |
| 261 | + | id: groupBoxAny | |
| 262 | + | anchors.left: prev.left | |
| 263 | + | anchors.top: prev.bottom | |
| 264 | + | margin-top: 3 | |
| 265 | + | margin-left: 3 | |
| 266 | + | !text: tr('Any') | |
| 267 | + | width: 75 | |
| 268 | + | ||
| 269 | + | CheckBox | |
| 270 | + | id: groupBoxAttack | |
| 271 | + | anchors.left: prev.left | |
| 272 | + | anchors.top: prev.bottom | |
| 273 | + | margin-top: 3 | |
| 274 | + | !text: tr('Attack') | |
| 275 | + | width: 75 | |
| 276 | + | ||
| 277 | + | CheckBox | |
| 278 | + | id: groupBoxHealing | |
| 279 | + | anchors.left: prev.left | |
| 280 | + | anchors.top: prev.bottom | |
| 281 | + | margin-top: 3 | |
| 282 | + | !text: tr('Healing') | |
| 283 | + | width: 75 | |
| 284 | + | ||
| 285 | + | CheckBox | |
| 286 | + | id: groupBoxSupport | |
| 287 | + | anchors.left: prev.left | |
| 288 | + | anchors.top: prev.bottom | |
| 289 | + | margin-top: 3 | |
| 290 | + | !text: tr('Support') | |
| 291 | + | width: 75 | |
| 292 | + | ||
| 293 | + | Label | |
| 294 | + | id: labelPremiumFilter | |
| 295 | + | anchors.top: labelPremium.bottom | |
| 296 | + | anchors.left: labelGroupFilter.right | |
| 297 | + | width: 70 | |
| 298 | + | font: verdana-11px-monochrome | |
| 299 | + | !text: tr('Premium') | |
| 300 | + | margin-top: 30 | |
| 301 | + | margin-left: 20 | |
| 302 | + | ||
| 303 | + | CheckBox | |
| 304 | + | id: premiumBoxAny | |
| 305 | + | anchors.left: prev.left | |
| 306 | + | anchors.top: prev.bottom | |
| 307 | + | margin-top: 3 | |
| 308 | + | margin-left: 3 | |
| 309 | + | !text: tr('Any') | |
| 310 | + | width: 75 | |
| 311 | + | ||
| 312 | + | CheckBox | |
| 313 | + | id: premiumBoxNo | |
| 314 | + | anchors.left: prev.left | |
| 315 | + | anchors.top: prev.bottom | |
| 316 | + | margin-top: 3 | |
| 317 | + | !text: tr('No') | |
| 318 | + | width: 75 | |
| 319 | + | ||
| 320 | + | CheckBox | |
| 321 | + | id: premiumBoxYes | |
| 322 | + | anchors.left: prev.left | |
| 323 | + | anchors.top: prev.bottom | |
| 324 | + | margin-top: 3 | |
| 325 | + | !text: tr('Yes') | |
| 326 | + | width: 75 |
| @@ -0,0 +1,58 @@ | |||
| 1 | + | ui = nil | |
| 2 | + | updateEvent = nil | |
| 3 | + | ||
| 4 | + | function init() | |
| 5 | + | ui = g_ui.loadUI('stats', modules.game_interface.getMapPanel()) | |
| 6 | + | ||
| 7 | + | if not modules.client_options.getOption("showPing") then | |
| 8 | + | ui.fps:hide() | |
| 9 | + | end | |
| 10 | + | if not modules.client_options.getOption("showFps") then | |
| 11 | + | ui.ping:hide() | |
| 12 | + | end | |
| 13 | + | ||
| 14 | + | updateEvent = scheduleEvent(update, 200) | |
| 15 | + | end | |
| 16 | + | ||
| 17 | + | function terminate() | |
| 18 | + | removeEvent(updateEvent) | |
| 19 | + | end | |
| 20 | + | ||
| 21 | + | function update() | |
| 22 | + | updateEvent = scheduleEvent(update, 500) | |
| 23 | + | if ui:isHidden() then return end | |
| 24 | + | ||
| 25 | + | text = 'FPS: ' .. g_app.getFps() | |
| 26 | + | ui.fps:setText(text) | |
| 27 | + | ||
| 28 | + | local ping = g_game.getPing() | |
| 29 | + | if g_proxy and g_proxy.getPing() > 0 then | |
| 30 | + | ping = g_proxy.getPing() | |
| 31 | + | end | |
| 32 | + | ||
| 33 | + | local text = 'Ping: ' | |
| 34 | + | local color | |
| 35 | + | if ping < 0 then | |
| 36 | + | text = text .. "??" | |
| 37 | + | color = 'yellow' | |
| 38 | + | else | |
| 39 | + | text = text .. ping .. ' ms' | |
| 40 | + | if ping >= 500 then | |
| 41 | + | color = 'red' | |
| 42 | + | elseif ping >= 250 then | |
| 43 | + | color = 'yellow' | |
| 44 | + | else | |
| 45 | + | color = 'green' | |
| 46 | + | end | |
| 47 | + | end | |
| 48 | + | ui.ping:setText(text) | |
| 49 | + | ui.ping:setColor(color) | |
| 50 | + | end | |
| 51 | + | ||
| 52 | + | function show() | |
| 53 | + | ui:setVisible(true) | |
| 54 | + | end | |
| 55 | + | ||
| 56 | + | function hide() | |
| 57 | + | ui:setVisible(false) | |
| 58 | + | end |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | Module | |
| 2 | + | name: game_stats | |
| 3 | + | description: Display ping and fps | |
| 4 | + | author: otclient.ovh | |
| 5 | + | website: http://otclient.ovh | |
| 6 | + | sandboxed: true | |
| 7 | + | scripts: [ stats ] | |
| 8 | + | @onLoad: init() | |
| 9 | + | @onUnload: terminate() |
| @@ -0,0 +1,17 @@ | |||
| 1 | + | UIWidget | |
| 2 | + | id: game_stats | |
| 3 | + | anchors.top: parent.top | |
| 4 | + | anchors.left: parent.left | |
| 5 | + | margin-left: 3 | |
| 6 | + | size: 100 100 | |
| 7 | + | visible: false | |
| 8 | + | layout: | |
| 9 | + | type: verticalBox | |
| 10 | + | ||
| 11 | + | Label | |
| 12 | + | id: fps | |
| 13 | + | font: verdana-11px-rounded | |
| 14 | + | ||
| 15 | + | Label | |
| 16 | + | id: ping | |
| 17 | + | font: verdana-11px-rounded |
| @@ -0,0 +1,249 @@ | |||
| 1 | + | if not Color then | |
| 2 | + | local mapping = { | |
| 3 | + | red = "#FF0000", | |
| 4 | + | orange = "#FFA500", | |
| 5 | + | blue = "#0000FF", | |
| 6 | + | white = "#FFFFFF", | |
| 7 | + | green = "#00FF00", | |
| 8 | + | yellow = "#FFFF00", | |
| 9 | + | lightblue = "#ADD8E6", | |
| 10 | + | purple = "#800080", | |
| 11 | + | } | |
| 12 | + | Color = { | |
| 13 | + | fromString = function(s) | |
| 14 | + | s = s:match("^%s*(.-)%s*$") or s -- trim extra spaces | |
| 15 | + | return mapping[string.lower(s)] or "#FFFFFF" | |
| 16 | + | end | |
| 17 | + | } | |
| 18 | + | end | |
| 19 | + | ||
| 20 | + | MessageSettings = { | |
| 21 | + | none = {}, | |
| 22 | + | consoleRed = { color = TextColors.red, consoleTab='Default' }, | |
| 23 | + | consoleOrange = { color = TextColors.orange, consoleTab='Default' }, | |
| 24 | + | consoleBlue = { color = TextColors.blue, consoleTab='Default' }, | |
| 25 | + | centerRed = { color = TextColors.red, consoleTab='Server Log', screenTarget='lowCenterLabel' }, | |
| 26 | + | centerGreen = { color = TextColors.green, consoleTab='Server Log', screenTarget='highCenterLabel', consoleOption='showInfoMessagesInConsole' }, | |
| 27 | + | centerWhite = { color = TextColors.white, consoleTab='Server Log', screenTarget='middleCenterLabel', consoleOption='showEventMessagesInConsole' }, | |
| 28 | + | centerOrange = { color = TextColors.orange, consoleTab='Server Log', screenTarget='lowCenterLabel' }, | |
| 29 | + | centerBlue = { color = TextColors.blue, consoleTab='Server Log', screenTarget='highCenterLabel' }, | |
| 30 | + | centerYellow = { color = TextColors.yellow, consoleTab='Server Log', screenTarget='middleCenterLabel' }, | |
| 31 | + | centerLightblue = { color = TextColors.lightblue, consoleTab='Server Log', screenTarget='lowCenterLabel' }, | |
| 32 | + | centerPurple = { color = TextColors.purple, consoleTab='Server Log', screenTarget='highCenterLabel' }, | |
| 33 | + | bottomWhite = { color = TextColors.white, consoleTab='Server Log', screenTarget='statusLabel', consoleOption='showEventMessagesInConsole' }, | |
| 34 | + | status = { color = TextColors.white, consoleTab='Server Log', screenTarget='statusLabel', consoleOption='showStatusMessagesInConsole' }, | |
| 35 | + | statusSmall = { color = TextColors.white, screenTarget='statusLabel' }, | |
| 36 | + | private = { color = TextColors.lightblue, screenTarget='privateLabel' }, | |
| 37 | + | privateAlert = { screenTarget='privateAlertWindow' } | |
| 38 | + | } | |
| 39 | + | ||
| 40 | + | MessageTypes = { | |
| 41 | + | [MessageModes.MonsterSay] = MessageSettings.consoleOrange, | |
| 42 | + | [MessageModes.MonsterYell] = MessageSettings.consoleOrange, | |
| 43 | + | [MessageModes.BarkLow] = MessageSettings.consoleOrange, | |
| 44 | + | [MessageModes.BarkLoud] = MessageSettings.consoleOrange, | |
| 45 | + | [MessageModes.Failure] = MessageSettings.statusSmall, | |
| 46 | + | [MessageModes.Login] = MessageSettings.bottomWhite, | |
| 47 | + | [MessageModes.Game] = MessageSettings.centerWhite, | |
| 48 | + | [MessageModes.Status] = MessageSettings.status, | |
| 49 | + | [MessageModes.Warning] = MessageSettings.centerRed, | |
| 50 | + | [MessageModes.Look] = MessageSettings.centerGreen, | |
| 51 | + | [MessageModes.Loot] = MessageSettings.centerGreen, | |
| 52 | + | [MessageModes.Red] = MessageSettings.consoleRed, | |
| 53 | + | [MessageModes.Blue] = MessageSettings.consoleBlue, | |
| 54 | + | [MessageModes.PrivateFrom] = MessageSettings.consoleBlue, | |
| 55 | + | ||
| 56 | + | [MessageModes.GamemasterBroadcast] = MessageSettings.consoleRed, | |
| 57 | + | ||
| 58 | + | [MessageModes.DamageDealed] = MessageSettings.status, | |
| 59 | + | [MessageModes.DamageReceived] = MessageSettings.status, | |
| 60 | + | [MessageModes.Heal] = MessageSettings.status, | |
| 61 | + | [MessageModes.Exp] = MessageSettings.status, | |
| 62 | + | ||
| 63 | + | [MessageModes.DamageOthers] = MessageSettings.none, | |
| 64 | + | [MessageModes.HealOthers] = MessageSettings.none, | |
| 65 | + | [MessageModes.ExpOthers] = MessageSettings.none, | |
| 66 | + | ||
| 67 | + | [MessageModes.TradeNpc] = MessageSettings.centerWhite, | |
| 68 | + | [MessageModes.Guild] = MessageSettings.centerWhite, | |
| 69 | + | [MessageModes.Party] = MessageSettings.centerGreen, | |
| 70 | + | [MessageModes.PartyManagement] = MessageSettings.centerWhite, | |
| 71 | + | [MessageModes.TutorialHint] = MessageSettings.centerWhite, | |
| 72 | + | [MessageModes.BeyondLast] = MessageSettings.centerWhite, | |
| 73 | + | [MessageModes.Report] = MessageSettings.consoleRed, | |
| 74 | + | [MessageModes.HotkeyUse] = MessageSettings.centerGreen, | |
| 75 | + | ||
| 76 | + | [254] = MessageSettings.private | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | MessageTypes[50] = MessageTypes[MessageModes.Warning] or MessageSettings.centerRed | |
| 80 | + | ||
| 81 | + | messagesPanel = nil | |
| 82 | + | ||
| 83 | + | function init() | |
| 84 | + | for messageMode, _ in pairs(MessageTypes) do | |
| 85 | + | registerMessageMode(messageMode, displayMessage) | |
| 86 | + | end | |
| 87 | + | ||
| 88 | + | connect(g_game, 'onGameEnd', clearMessages) | |
| 89 | + | messagesPanel = g_ui.loadUI('textmessage', modules.game_interface.getRootPanel()) | |
| 90 | + | end | |
| 91 | + | ||
| 92 | + | function terminate() | |
| 93 | + | for messageMode, _ in pairs(MessageTypes) do | |
| 94 | + | unregisterMessageMode(messageMode, displayMessage) | |
| 95 | + | end | |
| 96 | + | ||
| 97 | + | disconnect(g_game, 'onGameEnd', clearMessages) | |
| 98 | + | clearMessages() | |
| 99 | + | messagesPanel:destroy() | |
| 100 | + | end | |
| 101 | + | ||
| 102 | + | function calculateVisibleTime(text) | |
| 103 | + | return math.max(#text * 50, 3000) | |
| 104 | + | end | |
| 105 | + | ||
| 106 | + | function displayMessage(mode, text) | |
| 107 | + | if not g_game.isOnline() then return end | |
| 108 | + | ||
| 109 | + | local msgtype = MessageTypes[mode] | |
| 110 | + | if not msgtype then | |
| 111 | + | -- Fallback: handle color|text messages for unmapped modes | |
| 112 | + | if text:find('|') then | |
| 113 | + | local parts = text:explode('|') | |
| 114 | + | local color = parts[1] | |
| 115 | + | local message = parts[2] | |
| 116 | + | if type(color) == "string" then | |
| 117 | + | color = Color.fromString(color) | |
| 118 | + | end | |
| 119 | + | local label = messagesPanel:recursiveGetChildById('customMessage') | |
| 120 | + | label:setText(message) | |
| 121 | + | label:setColor(color) | |
| 122 | + | label:setBorderColor(color) | |
| 123 | + | label:setWidth(label:getTextSize().width+110) | |
| 124 | + | label:show() | |
| 125 | + | addEvent(function() g_effects.fadeIn(label, 250) end) | |
| 126 | + | removeEvent(label.hideEvent) | |
| 127 | + | label.hideEvent = scheduleEvent(function() | |
| 128 | + | addEvent(function() g_effects.fadeOut(label, 250) end) | |
| 129 | + | scheduleEvent(function() label:hide() end, 250) | |
| 130 | + | end, calculateVisibleTime(message)) | |
| 131 | + | end | |
| 132 | + | return | |
| 133 | + | end | |
| 134 | + | ||
| 135 | + | if msgtype == MessageSettings.none then return end | |
| 136 | + | ||
| 137 | + | if mode == MessageModes.Warning then | |
| 138 | + | local label = messagesPanel:recursiveGetChildById('customMessage') | |
| 139 | + | local color = msgtype.color | |
| 140 | + | if text:find('|') then | |
| 141 | + | local ex = text:explode('|') | |
| 142 | + | color = ex[1] | |
| 143 | + | if type(color) == "string" then | |
| 144 | + | color = Color.fromString(color) | |
| 145 | + | end | |
| 146 | + | text = ex[2] | |
| 147 | + | else | |
| 148 | + | if type(color) == "string" then | |
| 149 | + | color = Color.fromString(color) | |
| 150 | + | end | |
| 151 | + | end | |
| 152 | + | ||
| 153 | + | label:setText(text) | |
| 154 | + | label:setColor(color) | |
| 155 | + | label:setBorderColor(color) | |
| 156 | + | label:setWidth(label:getTextSize().width+110) | |
| 157 | + | label:show() | |
| 158 | + | ||
| 159 | + | addEvent(function() g_effects.fadeIn(label, 250) end) | |
| 160 | + | removeEvent(label.hideEvent) | |
| 161 | + | label.hideEvent = scheduleEvent(function() | |
| 162 | + | addEvent(function() g_effects.fadeOut(label, 250) end) | |
| 163 | + | scheduleEvent(function() label:hide() end, 250) | |
| 164 | + | end, calculateVisibleTime(text)) | |
| 165 | + | return | |
| 166 | + | end | |
| 167 | + | ||
| 168 | + | if msgtype.consoleTab ~= nil and (msgtype.consoleOption == nil or modules.client_options.getOption(msgtype.consoleOption)) then | |
| 169 | + | modules.game_chat.addText(text, msgtype, tr(msgtype.consoleTab)) | |
| 170 | + | --TODO move to game_console | |
| 171 | + | end | |
| 172 | + | ||
| 173 | + | if msgtype.screenTarget then | |
| 174 | + | local label = messagesPanel:recursiveGetChildById(msgtype.screenTarget) | |
| 175 | + | local col = msgtype.color | |
| 176 | + | if type(col) == "string" then | |
| 177 | + | col = Color.fromString(col) | |
| 178 | + | end | |
| 179 | + | if text:match('@') then | |
| 180 | + | label:setText('') | |
| 181 | + | else | |
| 182 | + | label:setText(text) | |
| 183 | + | end | |
| 184 | + | label:setColor(col) | |
| 185 | + | label:setVisible(true) | |
| 186 | + | removeEvent(label.hideEvent) | |
| 187 | + | label.hideEvent = scheduleEvent(function() label:setVisible(false) end, calculateVisibleTime(text)) | |
| 188 | + | end | |
| 189 | + | end | |
| 190 | + | ||
| 191 | + | function displayPrivateMessage(text) | |
| 192 | + | displayMessage(254, text) | |
| 193 | + | end | |
| 194 | + | ||
| 195 | + | function displayPrivateAlert(name, message) | |
| 196 | + | local msgtype = MessageSettings.privateAlert | |
| 197 | + | local window = messagesPanel:recursiveGetChildById(msgtype.screenTarget) | |
| 198 | + | if not window then return end | |
| 199 | + | ||
| 200 | + | -- Truncar mensaje si es muy largo para la alerta (según conteo del usuario: 46 caracteres) | |
| 201 | + | local displayMessage = message | |
| 202 | + | if #displayMessage > 46 then | |
| 203 | + | displayMessage = displayMessage:sub(1, 46) .. "...." | |
| 204 | + | end | |
| 205 | + | ||
| 206 | + | window:recursiveGetChildById('titleLabel'):setText("Private from " .. name .. ":") | |
| 207 | + | window:recursiveGetChildById('messageLabel'):setText(displayMessage) | |
| 208 | + | window:show() | |
| 209 | + | ||
| 210 | + | addEvent(function() g_effects.fadeIn(window, 250) end) | |
| 211 | + | removeEvent(window.hideEvent) | |
| 212 | + | window.hideEvent = scheduleEvent(function() | |
| 213 | + | addEvent(function() g_effects.fadeOut(window, 250) end) | |
| 214 | + | scheduleEvent(function() window:hide() end, 250) | |
| 215 | + | end, calculateVisibleTime(message)) | |
| 216 | + | end | |
| 217 | + | ||
| 218 | + | function displayStatusMessage(text) | |
| 219 | + | displayMessage(MessageModes.Status, text) | |
| 220 | + | end | |
| 221 | + | ||
| 222 | + | function displayFailureMessage(text) | |
| 223 | + | displayMessage(MessageModes.Failure, text) | |
| 224 | + | end | |
| 225 | + | ||
| 226 | + | function displayGameMessage(text) | |
| 227 | + | displayMessage(MessageModes.Game, text) | |
| 228 | + | end | |
| 229 | + | ||
| 230 | + | function displayBroadcastMessage(text) | |
| 231 | + | displayMessage(MessageModes.Warning, text) | |
| 232 | + | end | |
| 233 | + | ||
| 234 | + | function clearMessages() | |
| 235 | + | for _i,child in pairs(messagesPanel:recursiveGetChildren()) do | |
| 236 | + | if child:getId():match('Label') then | |
| 237 | + | child:hide() | |
| 238 | + | removeEvent(child.hideEvent) | |
| 239 | + | end | |
| 240 | + | end | |
| 241 | + | end | |
| 242 | + | function getSilentPMAlert() | |
| 243 | + | return messagesPanel:recursiveGetChildById('silentPMAlert') | |
| 244 | + | end | |
| 245 | + | ||
| 246 | + | ||
| 247 | + | function LocalPlayer:onAutoWalkFail(player) | |
| 248 | + | modules.game_textmessage.displayFailureMessage(tr('There is no way.')) | |
| 249 | + | end |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | Module | |
| 2 | + | name: game_textmessage | |
| 3 | + | description: Manage game text messages | |
| 4 | + | author: edubart | |
| 5 | + | website: https://github.com/edubart/otclient | |
| 6 | + | sandboxed: true | |
| 7 | + | scripts: [ textmessage ] | |
| 8 | + | @onLoad: init() | |
| 9 | + | @onUnload: terminate() |