mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-19 06:03:27 +02:00
Version 2.5 - http://otclient.net/showthread.php?tid=238
This commit is contained in:
@@ -15,7 +15,7 @@ local serverSelector
|
||||
local clientVersionSelector
|
||||
local serverHostTextEdit
|
||||
local rememberPasswordBox
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "870", "961", "1077", "1090", "1096", "1098", "1099", "1100"}
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "870", "961", "1000", "1077", "1090", "1096", "1098", "1099", "1100", "1200"}
|
||||
|
||||
local checkedByUpdater = {}
|
||||
|
||||
@@ -107,14 +107,91 @@ local function validateThings(things)
|
||||
return incorrectThings
|
||||
end
|
||||
|
||||
local function onTibia12HTTPResult(session, playdata)
|
||||
local characters = {}
|
||||
local worlds = {}
|
||||
local account = {
|
||||
status = 0,
|
||||
subStatus = 0,
|
||||
premDays = 0
|
||||
}
|
||||
if session["status"] ~= "active" then
|
||||
account.status = 1
|
||||
end
|
||||
if session["ispremium"] then
|
||||
account.subStatus = 1 -- premium
|
||||
end
|
||||
if session["premiumuntil"] > g_clock.seconds() then
|
||||
account.subStatus = math.floor((session["premiumuntil"] - g_clock.seconds()) / 86400)
|
||||
end
|
||||
|
||||
local things = {
|
||||
data = {G.clientVersion .. "/Tibia.dat", ""},
|
||||
sprites = {G.clientVersion .. "/Tibia.spr", ""},
|
||||
}
|
||||
|
||||
local incorrectThings = validateThings(things)
|
||||
if #incorrectThings > 0 then
|
||||
g_logger.error(incorrectThings)
|
||||
if Updater and not checkedByUpdater[G.clientVersion] then
|
||||
checkedByUpdater[G.clientVersion] = true
|
||||
return Updater.check({
|
||||
version = G.clientVersion,
|
||||
host = G.host
|
||||
})
|
||||
else
|
||||
return EnterGame.onError(incorrectThings)
|
||||
end
|
||||
end
|
||||
|
||||
onSessionKey(nil, session["sessionkey"])
|
||||
|
||||
for _, world in pairs(playdata["worlds"]) do
|
||||
worlds[world.id] = {
|
||||
name = world.name,
|
||||
port = world.externalportunprotected or world.externalportprotected,
|
||||
address = world.externaladdressunprotected or world.externaladdressprotected
|
||||
}
|
||||
end
|
||||
|
||||
for _, character in pairs(playdata["characters"]) do
|
||||
local world = worlds[character.worldid]
|
||||
if world then
|
||||
table.insert(characters, {
|
||||
name = character.name,
|
||||
worldName = world.name,
|
||||
worldIp = world.address,
|
||||
worldPort = world.port
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
g_game.setCustomProtocolVersion(0)
|
||||
g_game.chooseRsa(G.host)
|
||||
g_game.setClientVersion(G.clientVersion)
|
||||
g_game.setProtocolVersion(g_game.getClientProtocolVersion(G.clientVersion))
|
||||
g_game.setCustomOs(-1) -- disable
|
||||
if not g_game.getFeature(GameExtendedOpcode) then
|
||||
g_game.setCustomOs(5) -- set os to windows if opcodes are disabled
|
||||
end
|
||||
|
||||
onCharacterList(nil, characters, account, nil)
|
||||
end
|
||||
|
||||
local function onHTTPResult(data, err)
|
||||
if err then
|
||||
return EnterGame.onError(err)
|
||||
end
|
||||
if data['error'] and #data['error'] > 0 then
|
||||
if data['error'] and data['error']:len() > 0 then
|
||||
return EnterGame.onLoginError(data['error'])
|
||||
elseif data['errorMessage'] and data['errorMessage']:len() > 0 then
|
||||
return EnterGame.onLoginError(data['errorMessage'])
|
||||
end
|
||||
|
||||
if type(data["session"]) == "table" and type(data["playdata"]) == "table" then
|
||||
return onTibia12HTTPResult(data["session"], data["playdata"])
|
||||
end
|
||||
|
||||
local characters = data["characters"]
|
||||
local account = data["account"]
|
||||
local session = data["session"]
|
||||
@@ -331,11 +408,18 @@ function EnterGame.doLogin()
|
||||
g_settings.set('client-version', G.clientVersion)
|
||||
g_settings.save()
|
||||
|
||||
if G.host:find("http") ~= nil then
|
||||
local server_params = G.host:split(":")
|
||||
if G.host:lower():find("http") ~= nil then
|
||||
if #server_params >= 4 then
|
||||
G.host = server_params[1] .. ":" .. server_params[2] .. ":" .. server_params[3]
|
||||
G.clientVersion = tonumber(server_params[4])
|
||||
elseif #server_params >= 3 then
|
||||
G.host = server_params[1] .. ":" .. server_params[2]
|
||||
G.clientVersion = tonumber(server_params[3])
|
||||
end
|
||||
return EnterGame.doLoginHttp()
|
||||
end
|
||||
|
||||
local server_params = G.host:split(":")
|
||||
local server_ip = server_params[1]
|
||||
local server_port = 7171
|
||||
if #server_params >= 2 then
|
||||
@@ -381,6 +465,9 @@ function EnterGame.doLogin()
|
||||
EnterGame.show()
|
||||
end })
|
||||
|
||||
if G.clientVersion == 1000 then -- some people don't understand that tibia 10 uses 1100 protocol
|
||||
G.clientVersion = 1100
|
||||
end
|
||||
-- if you have custom rsa or protocol edit it here
|
||||
g_game.setClientVersion(G.clientVersion)
|
||||
g_game.setProtocolVersion(g_game.getClientProtocolVersion(G.clientVersion))
|
||||
@@ -421,14 +508,20 @@ function EnterGame.doLoginHttp()
|
||||
loadBox = nil
|
||||
EnterGame.show()
|
||||
end })
|
||||
|
||||
|
||||
local data = {
|
||||
type = "login",
|
||||
account = G.account,
|
||||
accountname = G.account,
|
||||
email = G.account,
|
||||
password = G.password,
|
||||
accountpassword = G.password,
|
||||
token = G.authenticatorToken,
|
||||
version = APP_VERSION,
|
||||
uid = G.UUID
|
||||
}
|
||||
uid = G.UUID,
|
||||
stayloggedin = true
|
||||
}
|
||||
|
||||
HTTP.postJSON(G.host, data, onHTTPResult)
|
||||
EnterGame.hide()
|
||||
end
|
||||
|
@@ -112,7 +112,7 @@ EnterGameWindow
|
||||
|
||||
MenuLabel
|
||||
id: serverLabel
|
||||
!text: tr('IP:PORT')
|
||||
!text: tr('IP:PORT or URL')
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 8
|
||||
|
@@ -256,14 +256,18 @@ function updateStatus()
|
||||
if not Services or not Services.status or Services.status:len() < 4 then return end
|
||||
if not topMenu.onlineLabel then return end
|
||||
if g_game.isOnline() then return end
|
||||
HTTP.getJSON(Services.status, function(data, err)
|
||||
HTTP.postJSON(Services.status, {type="cacheinfo"}, function(data, err)
|
||||
if err then
|
||||
g_logger.warning("HTTP error for " .. Services.status .. ": " .. err)
|
||||
statusUpdateEvent = scheduleEvent(updateStatus, 5000)
|
||||
return
|
||||
end
|
||||
if data.online and topMenu.onlineLabel then
|
||||
topMenu.onlineLabel:setText(data.online)
|
||||
if topMenu.onlineLabel then
|
||||
if data.online then
|
||||
topMenu.onlineLabel:setText(data.online)
|
||||
elseif data.playersonline then
|
||||
topMenu.onlineLabel:setText(data.playersonline .. " players online")
|
||||
end
|
||||
end
|
||||
if data.discord_online and topMenu.discordLabel then
|
||||
topMenu.discordLabel:setText(data.discord_online)
|
||||
|
@@ -1,9 +1,10 @@
|
||||
HTTP = {
|
||||
timeout=5,
|
||||
websocketTimeout=15,
|
||||
agent="Mozilla/5.0",
|
||||
imageId=1000,
|
||||
images={},
|
||||
operations={}
|
||||
operations={},
|
||||
}
|
||||
|
||||
function HTTP.get(url, callback)
|
||||
@@ -274,4 +275,4 @@ connect(g_http,
|
||||
onWsClose = HTTP.onWsClose,
|
||||
onWsError = HTTP.onWsError,
|
||||
})
|
||||
|
||||
g_http.setUserAgent(HTTP.agent)
|
||||
|
@@ -335,7 +335,7 @@ function check()
|
||||
return
|
||||
end
|
||||
|
||||
checkEvent = scheduleEvent(check, 25)
|
||||
checkEvent = scheduleEvent(check, 10)
|
||||
|
||||
local status, result = pcall(function()
|
||||
return botExecutor.script()
|
||||
|
@@ -34,11 +34,16 @@ context.macro = function(timeout, name, hotkey, callback, parent)
|
||||
hotkey = retranslateKeyComboDesc(hotkey)
|
||||
end
|
||||
|
||||
-- min timeout is 50, to avoid lags
|
||||
if timeout < 50 then
|
||||
timeout = 50
|
||||
end
|
||||
|
||||
table.insert(context._macros, {
|
||||
enabled = false,
|
||||
name = name,
|
||||
timeout = timeout,
|
||||
lastExecution = context.now,
|
||||
lastExecution = context.now + math.random(0, 100),
|
||||
hotkey = hotkey,
|
||||
})
|
||||
local macro = context._macros[#context._macros]
|
||||
|
@@ -5,11 +5,27 @@ context.getMapPanel = context.getMapView
|
||||
context.zoomIn = function() modules.game_interface.getMapPanel():zoomIn() end
|
||||
context.zoomOut = function() modules.game_interface.getMapPanel():zoomOut() end
|
||||
|
||||
context.getSpectators = function(multifloor)
|
||||
if multifloor ~= true then
|
||||
multifloor = false
|
||||
context.getSpectators = function(param1, param2)
|
||||
--[[
|
||||
if param1 is table (position) then it's used for central position, then param2 is used as param1
|
||||
if param1 is true/false then it's used for multifloor, example: getSpectators(true)
|
||||
if param1 is string then it's used for getSpectatorsByPattern
|
||||
]]--
|
||||
local pos = context.player:getPosition()
|
||||
if type(param1) == 'table' then
|
||||
pos = param1
|
||||
param1 = param2
|
||||
end
|
||||
return g_map.getSpectators(context.player:getPosition(), multifloor)
|
||||
|
||||
if type(param1) == 'string' then
|
||||
return g_map.getSpectatorsByPattern(pos, param1)
|
||||
end
|
||||
|
||||
local multifloor = false
|
||||
if type(param1) == 'boolean' and param1 == true then
|
||||
multifloor = true
|
||||
end
|
||||
return g_map.getSpectators(pos, multifloor)
|
||||
end
|
||||
|
||||
context.getCreatureById = function(id, multifloor)
|
||||
|
@@ -161,3 +161,6 @@ context.cancelAttackAndFollow = g_game.cancelAttackAndFollow
|
||||
context.logout = g_game.forceLogout
|
||||
context.ping = g_game.getPing
|
||||
|
||||
modules.game_cooldown.isGroupCooldownIconActive(id)
|
||||
modules.game_cooldown.isCooldownIconActive(id)
|
||||
|
||||
|
@@ -32,6 +32,9 @@ context.getContainers = function() return g_game.getContainers() end
|
||||
context.getContainer = function(index) return g_game.getContainer(index) end
|
||||
|
||||
context.moveToSlot = function(item, slot, count)
|
||||
if type(item) == 'number' then
|
||||
item = context.findItem(item)
|
||||
end
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
|
@@ -189,5 +189,12 @@ function updateFeatures(version)
|
||||
g_game.enableFeature(GamePrey)
|
||||
end
|
||||
|
||||
if(version >= 1200) then
|
||||
g_game.enableFeature(GameSequencedPackets)
|
||||
--g_game.enableFeature(GameSendWorldName)
|
||||
g_game.enableFeature(GamePlayerStateU32)
|
||||
g_game.enableFeature(GameTibia12Protocol)
|
||||
end
|
||||
|
||||
modules.game_things.load()
|
||||
end
|
||||
|
@@ -39,6 +39,7 @@ Module
|
||||
- game_prey
|
||||
- game_imbuing
|
||||
- game_stats
|
||||
- game_shaders
|
||||
- game_bot
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
||||
|
@@ -11,7 +11,7 @@ ADDON_SETS = {
|
||||
outfitWindow = nil
|
||||
outfit = nil
|
||||
outfits = nil
|
||||
outfitCreature = nil
|
||||
outfitCreatureBox = nil
|
||||
currentOutfit = 1
|
||||
|
||||
addons = nil
|
||||
@@ -21,7 +21,7 @@ colorBoxes = {}
|
||||
|
||||
mount = nil
|
||||
mounts = nil
|
||||
mountCreature = nil
|
||||
mountCreatureBox = nil
|
||||
currentMount = 1
|
||||
ignoreNextOutfitWindow = 0
|
||||
|
||||
@@ -51,7 +51,65 @@ function updateMount()
|
||||
mountCreature:setOutfit(mount)
|
||||
end
|
||||
|
||||
function create(creatureOutfit, outfitList, creatureMount, mountList)
|
||||
function setupSelector(widget, id, outfit, list)
|
||||
widget:setId(id)
|
||||
local pos = 1
|
||||
for i, o in pairs(list) do
|
||||
if outfit[id] == o[1] then
|
||||
pos = i
|
||||
end
|
||||
end
|
||||
if list[pos] then
|
||||
widget.outfit = list[pos]
|
||||
if id == "shader" then
|
||||
widget.creature:setOutfit({
|
||||
shader = list[pos][1]
|
||||
})
|
||||
else
|
||||
widget.creature:setOutfit({
|
||||
type = list[pos][1]
|
||||
})
|
||||
end
|
||||
widget.label:setText(list[pos][2])
|
||||
end
|
||||
widget.prevButton.onClick = function()
|
||||
if pos == 1 then
|
||||
pos = #list
|
||||
else
|
||||
pos = pos - 1
|
||||
end
|
||||
local outfit = widget.creature:getOutfit()
|
||||
if id == "shader" then
|
||||
outfit.shader = list[pos][1]
|
||||
else
|
||||
outfit.type = list[pos][1]
|
||||
end
|
||||
widget.outfit = list[pos]
|
||||
widget.creature:setOutfit(outfit)
|
||||
widget.label:setText(list[pos][2])
|
||||
updateOutfit()
|
||||
end
|
||||
widget.nextButton.onClick = function()
|
||||
if pos == #list then
|
||||
pos = 1
|
||||
else
|
||||
pos = pos + 1
|
||||
end
|
||||
local outfit = widget.creature:getOutfit()
|
||||
if id == "shader" then
|
||||
outfit.shader = list[pos][1]
|
||||
else
|
||||
outfit.type = list[pos][1]
|
||||
end
|
||||
widget.outfit = list[pos]
|
||||
widget.creature:setOutfit(outfit)
|
||||
widget.label:setText(list[pos][2])
|
||||
updateOutfit()
|
||||
end
|
||||
return w
|
||||
end
|
||||
|
||||
function create(currentOutfit, outfitList, mountList, wingList, auraList, shaderList)
|
||||
if ignoreNextOutfitWindow and g_clock.millis() < ignoreNextOutfitWindow + 1000 then
|
||||
return
|
||||
end
|
||||
@@ -59,38 +117,51 @@ function create(creatureOutfit, outfitList, creatureMount, mountList)
|
||||
return
|
||||
end
|
||||
|
||||
outfitCreature = creatureOutfit
|
||||
mountCreature = creatureMount
|
||||
outfits = outfitList
|
||||
mounts = mountList
|
||||
destroy()
|
||||
|
||||
outfitWindow = g_ui.displayUI('outfitwindow')
|
||||
local colorBoxPanel = outfitWindow:getChildById('colorBoxPanel')
|
||||
|
||||
-- setup outfit/mount display boxs
|
||||
local outfitCreatureBox = outfitWindow:getChildById('outfitCreatureBox')
|
||||
if outfitCreature then
|
||||
outfit = outfitCreature:getOutfit()
|
||||
outfitCreatureBox:setCreature(outfitCreature)
|
||||
else
|
||||
outfitCreatureBox:hide()
|
||||
outfitWindow:getChildById('outfitName'):hide()
|
||||
outfitWindow:getChildById('outfitNextButton'):hide()
|
||||
outfitWindow:getChildById('outfitPrevButton'):hide()
|
||||
|
||||
setupSelector(outfitWindow.type, "type", currentOutfit, outfitList)
|
||||
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
outfit.head = currentOutfit.head
|
||||
outfit.body = currentOutfit.body
|
||||
outfit.legs = currentOutfit.legs
|
||||
outfit.feet = currentOutfit.feet
|
||||
outfitWindow.type.creature:setOutfit(outfit)
|
||||
|
||||
if g_game.getFeature(GamePlayerMounts) then
|
||||
setupSelector(g_ui.createWidget('OutfitSelectorPanel', outfitWindow.extensions), "mount", currentOutfit, mountList)
|
||||
end
|
||||
|
||||
local mountCreatureBox = outfitWindow:getChildById('mountCreatureBox')
|
||||
if mountCreature then
|
||||
mount = mountCreature:getOutfit()
|
||||
mountCreatureBox:setCreature(mountCreature)
|
||||
else
|
||||
mountCreatureBox:hide()
|
||||
outfitWindow:getChildById('mountName'):hide()
|
||||
outfitWindow:getChildById('mountNextButton'):hide()
|
||||
outfitWindow:getChildById('mountPrevButton'):hide()
|
||||
if g_game.getFeature(GameWingsAndAura) then
|
||||
setupSelector(g_ui.createWidget('OutfitSelectorPanel', outfitWindow.extensions), "wings", currentOutfit, wingList)
|
||||
setupSelector(g_ui.createWidget('OutfitSelectorPanel', outfitWindow.extensions), "aura", currentOutfit, auraList)
|
||||
end
|
||||
if g_game.getFeature(GameOutfitShaders) then
|
||||
setupSelector(g_ui.createWidget('OutfitSelectorPanel', outfitWindow.extensions), "shader", currentOutfit, shaderList)
|
||||
end
|
||||
|
||||
if not outfitWindow.extensions:getFirstChild() then
|
||||
outfitWindow:setHeight(outfitWindow:getHeight() - 128)
|
||||
end
|
||||
|
||||
for j=0,6 do
|
||||
for i=0,18 do
|
||||
local colorBox = g_ui.createWidget('ColorBox', outfitWindow.colorBoxPanel)
|
||||
local outfitColor = getOutfitColor(j*19 + i)
|
||||
colorBox:setImageColor(outfitColor)
|
||||
colorBox:setId('colorBox' .. j*19+i)
|
||||
colorBox.colorId = j*19 + i
|
||||
|
||||
if j*19 + i == currentOutfit.head then
|
||||
currentColorBox = colorBox
|
||||
colorBox:setChecked(true)
|
||||
end
|
||||
colorBox.onCheckChange = onColorCheckChange
|
||||
colorBoxes[#colorBoxes+1] = colorBox
|
||||
end
|
||||
end
|
||||
|
||||
-- set addons
|
||||
addons = {
|
||||
[1] = {widget = outfitWindow:getChildById('addon1'), value = 1},
|
||||
@@ -102,63 +173,26 @@ function create(creatureOutfit, outfitList, creatureMount, mountList)
|
||||
addon.widget.onCheckChange = function(self) onAddonCheckChange(self, addon.value) end
|
||||
end
|
||||
|
||||
if outfit.addons and outfit.addons > 0 then
|
||||
for _, i in pairs(ADDON_SETS[outfit.addons]) do
|
||||
if currentOutfit.addons and currentOutfit.addons > 0 then
|
||||
for _, i in pairs(ADDON_SETS[currentOutfit.addons]) do
|
||||
addons[i].widget:setChecked(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- hook outfit sections
|
||||
currentClotheButtonBox = outfitWindow:getChildById('head')
|
||||
outfitWindow:getChildById('head').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('primary').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('secondary').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('detail').onCheckChange = onClotheCheckChange
|
||||
|
||||
-- populate color panel
|
||||
for j=0,6 do
|
||||
for i=0,18 do
|
||||
local colorBox = g_ui.createWidget('ColorBox', colorBoxPanel)
|
||||
local outfitColor = getOutfitColor(j*19 + i)
|
||||
colorBox:setImageColor(outfitColor)
|
||||
colorBox:setId('colorBox' .. j*19+i)
|
||||
colorBox.colorId = j*19 + i
|
||||
|
||||
if j*19 + i == outfit.head then
|
||||
currentColorBox = colorBox
|
||||
colorBox:setChecked(true)
|
||||
end
|
||||
colorBox.onCheckChange = onColorCheckChange
|
||||
colorBoxes[#colorBoxes+1] = colorBox
|
||||
end
|
||||
end
|
||||
|
||||
-- set current outfit/mount
|
||||
currentOutfit = 1
|
||||
for i=1,#outfitList do
|
||||
if outfit and outfitList[i][1] == outfit.type then
|
||||
currentOutfit = i
|
||||
break
|
||||
end
|
||||
end
|
||||
currentMount = 1
|
||||
for i=1,#mountList do
|
||||
if mount and mountList[i][1] == mount.type then
|
||||
currentMount = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
currentClotheButtonBox = outfitWindow.head
|
||||
outfitWindow.head.onCheckChange = onClotheCheckChange
|
||||
outfitWindow.primary.onCheckChange = onClotheCheckChange
|
||||
outfitWindow.secondary.onCheckChange = onClotheCheckChange
|
||||
outfitWindow.detail.onCheckChange = onClotheCheckChange
|
||||
|
||||
updateOutfit()
|
||||
updateMount()
|
||||
end
|
||||
|
||||
function destroy()
|
||||
if outfitWindow then
|
||||
outfitWindow:destroy()
|
||||
outfitWindow = nil
|
||||
outfitCreature = nil
|
||||
mountCreature = nil
|
||||
currentColorBox = nil
|
||||
currentClotheButtonBox = nil
|
||||
colorBoxes = {}
|
||||
@@ -168,10 +202,10 @@ end
|
||||
|
||||
function randomize()
|
||||
local outfitTemplate = {
|
||||
outfitWindow:getChildById('head'),
|
||||
outfitWindow:getChildById('primary'),
|
||||
outfitWindow:getChildById('secondary'),
|
||||
outfitWindow:getChildById('detail')
|
||||
outfitWindow.head,
|
||||
outfitWindow.primary,
|
||||
outfitWindow.secondary,
|
||||
outfitWindow.detail
|
||||
}
|
||||
|
||||
for i = 1, #outfitTemplate do
|
||||
@@ -183,65 +217,30 @@ function randomize()
|
||||
end
|
||||
|
||||
function accept()
|
||||
if mount then outfit.mount = mount.type end
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
for i, child in pairs(outfitWindow.extensions:getChildren()) do
|
||||
if child:getId() == "shader" then
|
||||
outfit[child:getId()] = child.creature:getOutfit().shader
|
||||
else
|
||||
outfit[child:getId()] = child.creature:getOutfit().type
|
||||
end
|
||||
end
|
||||
g_game.changeOutfit(outfit)
|
||||
destroy()
|
||||
end
|
||||
|
||||
function nextOutfitType()
|
||||
if not outfits then
|
||||
return
|
||||
end
|
||||
currentOutfit = currentOutfit + 1
|
||||
if currentOutfit > #outfits then
|
||||
currentOutfit = 1
|
||||
end
|
||||
updateOutfit()
|
||||
end
|
||||
|
||||
function previousOutfitType()
|
||||
if not outfits then
|
||||
return
|
||||
end
|
||||
currentOutfit = currentOutfit - 1
|
||||
if currentOutfit <= 0 then
|
||||
currentOutfit = #outfits
|
||||
end
|
||||
updateOutfit()
|
||||
end
|
||||
|
||||
function nextMountType()
|
||||
if not mounts then
|
||||
return
|
||||
end
|
||||
currentMount = currentMount + 1
|
||||
if currentMount > #mounts then
|
||||
currentMount = 1
|
||||
end
|
||||
updateMount()
|
||||
end
|
||||
|
||||
function previousMountType()
|
||||
if not mounts then
|
||||
return
|
||||
end
|
||||
currentMount = currentMount - 1
|
||||
if currentMount <= 0 then
|
||||
currentMount = #mounts
|
||||
end
|
||||
updateMount()
|
||||
end
|
||||
|
||||
function onAddonCheckChange(addon, value)
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
if addon:isChecked() then
|
||||
outfit.addons = outfit.addons + value
|
||||
else
|
||||
outfit.addons = outfit.addons - value
|
||||
end
|
||||
outfitCreature:setOutfit(outfit)
|
||||
outfitWindow.type.creature:setOutfit(outfit)
|
||||
end
|
||||
|
||||
function onColorCheckChange(colorBox)
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
if colorBox == currentColorBox then
|
||||
colorBox.onCheckChange = nil
|
||||
colorBox:setChecked(true)
|
||||
@@ -264,12 +263,12 @@ function onColorCheckChange(colorBox)
|
||||
elseif currentClotheButtonBox:getId() == 'detail' then
|
||||
outfit.feet = currentColorBox.colorId
|
||||
end
|
||||
|
||||
outfitCreature:setOutfit(outfit)
|
||||
outfitWindow.type.creature:setOutfit(outfit)
|
||||
end
|
||||
end
|
||||
|
||||
function onClotheCheckChange(clotheButtonBox)
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
if clotheButtonBox == currentClotheButtonBox then
|
||||
clotheButtonBox.onCheckChange = nil
|
||||
clotheButtonBox:setChecked(true)
|
||||
@@ -296,14 +295,11 @@ function onClotheCheckChange(clotheButtonBox)
|
||||
end
|
||||
|
||||
function updateOutfit()
|
||||
if table.empty(outfits) or not outfit then
|
||||
return
|
||||
end
|
||||
local nameWidget = outfitWindow:getChildById('outfitName')
|
||||
nameWidget:setText(outfits[currentOutfit][2])
|
||||
|
||||
local availableAddons = outfits[currentOutfit][3]
|
||||
local currentSelection = outfitWindow.type.outfit
|
||||
if not currentSelection then return end
|
||||
local outfit = outfitWindow.type.creature:getOutfit()
|
||||
|
||||
local availableAddons = currentSelection[3]
|
||||
local prevAddons = {}
|
||||
for k, addon in pairs(addons) do
|
||||
prevAddons[k] = addon.widget:isChecked()
|
||||
@@ -311,6 +307,7 @@ function updateOutfit()
|
||||
addon.widget:setEnabled(false)
|
||||
end
|
||||
outfit.addons = 0
|
||||
outfitWindow.type.creature:setOutfit(outfit)
|
||||
|
||||
if availableAddons > 0 then
|
||||
for _, i in pairs(ADDON_SETS[availableAddons]) do
|
||||
@@ -318,8 +315,5 @@ function updateOutfit()
|
||||
addons[i].widget:setChecked(true)
|
||||
end
|
||||
end
|
||||
|
||||
outfit.type = outfits[currentOutfit][1]
|
||||
outfitCreature:setOutfit(outfit)
|
||||
end
|
||||
|
||||
|
@@ -3,160 +3,159 @@ PrevOutfitButton < PreviousButton
|
||||
NextMountButton < NextButton
|
||||
PrevMountButton < PreviousButton
|
||||
|
||||
OutfitSelectorPanel < Panel
|
||||
size: 125 120
|
||||
|
||||
UICreature
|
||||
id: creature
|
||||
size: 96 96
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 1
|
||||
|
||||
PreviousButton
|
||||
id: prevButton
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
NextButton
|
||||
id: nextButton
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Label
|
||||
id: label
|
||||
text: Outfit name
|
||||
text-align: center
|
||||
anchors.left: prevButton.right
|
||||
anchors.right: nextButton.left
|
||||
anchors.top: prevButton.top
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 2
|
||||
margin-right: 2
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 2
|
||||
text: -
|
||||
|
||||
MainWindow
|
||||
!text: tr('Select Outfit')
|
||||
size: 338 355
|
||||
size: 540 335
|
||||
|
||||
@onEnter: modules.game_outfit.accept()
|
||||
@onEscape: modules.game_outfit.destroy()
|
||||
|
||||
// Creature Boxes
|
||||
Creature
|
||||
id: outfitCreatureBox
|
||||
anchors.top: parent.top
|
||||
|
||||
Panel
|
||||
id: line1
|
||||
anchors.top: outfit.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 15
|
||||
margin-left: 22
|
||||
padding: 4 4 4 4
|
||||
size: 96 96
|
||||
fixed-creature-size: true
|
||||
raw: true
|
||||
|
||||
Label
|
||||
id: outfitName
|
||||
!text: tr('No Outfit')
|
||||
width: 115
|
||||
anchors.bottom: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-bottom: 2
|
||||
|
||||
NextOutfitButton
|
||||
id: outfitNextButton
|
||||
anchors.left: outfitCreatureBox.right
|
||||
anchors.verticalCenter: outfitCreatureBox.verticalCenter
|
||||
margin-left: 3
|
||||
enabled: true
|
||||
@onClick: modules.game_outfit.nextOutfitType()
|
||||
|
||||
PrevOutfitButton
|
||||
id: outfitPrevButton
|
||||
anchors.right: outfitCreatureBox.left
|
||||
anchors.verticalCenter: outfitCreatureBox.verticalCenter
|
||||
margin-right: 3
|
||||
enabled: true
|
||||
@onClick: modules.game_outfit.previousOutfitType()
|
||||
|
||||
Creature
|
||||
id: mountCreatureBox
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 15
|
||||
margin-right: 22
|
||||
padding: 4 4 4 4
|
||||
size: 96 96
|
||||
fixed-creature-size: true
|
||||
raw: true
|
||||
|
||||
Label
|
||||
id: mountName
|
||||
!text: tr('No Mount')
|
||||
width: 115
|
||||
anchors.bottom: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-bottom: 2
|
||||
|
||||
NextMountButton
|
||||
id: mountNextButton
|
||||
anchors.left: mountCreatureBox.right
|
||||
anchors.verticalCenter: mountCreatureBox.verticalCenter
|
||||
margin-left: 3
|
||||
enabled: true
|
||||
@onClick: modules.game_outfit.nextMountType()
|
||||
|
||||
PrevMountButton
|
||||
id: mountPrevButton
|
||||
anchors.right: mountCreatureBox.left
|
||||
anchors.verticalCenter: mountCreatureBox.verticalCenter
|
||||
margin-right: 3
|
||||
enabled: true
|
||||
@onClick: modules.game_outfit.previousMountType()
|
||||
|
||||
// Addon Check Boxes
|
||||
backgroud: red
|
||||
layout:
|
||||
type: horizontalBox
|
||||
spacing: 3
|
||||
|
||||
OutfitSelectorPanel
|
||||
id: type
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
CheckBox
|
||||
id: addon1
|
||||
!text: tr('Addon 1')
|
||||
width: 80
|
||||
anchors.top: outfitCreatureBox.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 6
|
||||
anchors.top: type.bottom
|
||||
anchors.left: type.left
|
||||
!text: tr('Addon 1')
|
||||
margin-left: 2
|
||||
margin-top: 5
|
||||
enabled: false
|
||||
|
||||
CheckBox
|
||||
id: addon2
|
||||
!text: tr('Addon 2')
|
||||
width: 80
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
!text: tr('Addon 2')
|
||||
enabled: false
|
||||
|
||||
CheckBox
|
||||
id: addon3
|
||||
!text: tr('Addon 3')
|
||||
width: 80
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
!text: tr('Addon 3')
|
||||
enabled: false
|
||||
|
||||
// Body Selection Buttons
|
||||
|
||||
|
||||
ButtonBox
|
||||
id: head
|
||||
!text: tr('Head')
|
||||
anchors.top: addon1.bottom
|
||||
anchors.left: addon1.left
|
||||
margin-top: 5
|
||||
anchors.top: type.top
|
||||
anchors.left: type.right
|
||||
margin-left: 5
|
||||
checked: true
|
||||
width: 76
|
||||
|
||||
ButtonBox
|
||||
id: primary
|
||||
!text: tr('Primary')
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 2
|
||||
width: 76
|
||||
|
||||
ButtonBox
|
||||
id: secondary
|
||||
!text: tr('Secondary')
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 2
|
||||
width: 76
|
||||
|
||||
ButtonBox
|
||||
id: detail
|
||||
!text: tr('Detail')
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
width: 76
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 2
|
||||
width: 76
|
||||
|
||||
// Color Panel
|
||||
ButtonBox
|
||||
id: randomizeButton
|
||||
!text: tr('Randomize')
|
||||
anchors.top: prev.bottom
|
||||
!tooltip: tr('Randomize characters outfit')
|
||||
anchors.left: prev.left
|
||||
margin-top: 2
|
||||
width: 76
|
||||
@onClick: modules.game_outfit.randomize()
|
||||
|
||||
Panel
|
||||
id: colorBoxPanel
|
||||
anchors.top: head.bottom
|
||||
anchors.left: head.left
|
||||
margin-top: 3
|
||||
margin-right: 20
|
||||
width: 302
|
||||
height: 119
|
||||
anchors.top: head.top
|
||||
anchors.left: head.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: type.bottom
|
||||
margin-left: 5
|
||||
margin-top: 2
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 14 14
|
||||
cell-size: 15 15
|
||||
cell-spacing: 2
|
||||
num-columns: 19
|
||||
num-lines: 7
|
||||
|
||||
Panel
|
||||
id: extensions
|
||||
height: 120
|
||||
margin-top: 5
|
||||
anchors.top: addon1.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
backgroud: red
|
||||
layout:
|
||||
type: horizontalBox
|
||||
fit-children: true
|
||||
spacing: 3
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
@@ -165,15 +164,6 @@ MainWindow
|
||||
margin-bottom: 5
|
||||
margin-top: 5
|
||||
|
||||
Button
|
||||
id: randomizeButton
|
||||
!text: tr('Randomize')
|
||||
!tooltip: tr('Randomize characters outfit')
|
||||
width: 75
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
@onClick: modules.game_outfit.randomize()
|
||||
|
||||
Button
|
||||
id: outfitOkButton
|
||||
!text: tr('Ok')
|
||||
|
20
modules/game_shaders/shaders.lua
Normal file
20
modules/game_shaders/shaders.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
function init()
|
||||
-- add manually your shaders from /data/shaders
|
||||
g_shaders.createOutfitShader("default", "/shaders/outfit_default_vertex", "/shaders/outfit_default_fragment")
|
||||
|
||||
--[[ g_shaders.createOutfitShader("stars", "/shaders/outfit_stars_vertex", "/shaders/outfit_stars_fragment")
|
||||
g_shaders.addTexture("stars", "/shaders/stars.png")
|
||||
|
||||
g_shaders.createOutfitShader("gold", "/shaders/outfit_gold_vertex", "/shaders/outfit_gold_fragment")
|
||||
g_shaders.addTexture("gold", "/data/shaders/gold.png")
|
||||
|
||||
g_shaders.createOutfitShader("rainbow", "/shaders/outfit_rainbow_vertex", "/shaders/outfit_rainbow_fragment")
|
||||
g_shaders.addTexture("rainbow", "/shaders/rainbow.png")
|
||||
|
||||
g_shaders.createOutfitShader("line", "/shaders/outfit_line_vertex", "/shaders/outfit_line_fragment")
|
||||
|
||||
g_shaders.createOutfitShader("outline", "/shaders/outfit_outline_vertex", "/shaders/outfit_outline_fragment") ]]--
|
||||
end
|
||||
|
||||
function terminate()
|
||||
end
|
9
modules/game_shaders/shaders.otmod
Normal file
9
modules/game_shaders/shaders.otmod
Normal file
@@ -0,0 +1,9 @@
|
||||
Module
|
||||
name: game_shaders
|
||||
description: Load shaders
|
||||
author: otclientv8
|
||||
website: http://otclient.ovh
|
||||
scripts: [ shaders ]
|
||||
sandboxed: true
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
@@ -147,9 +147,13 @@ function onStoreCategories(categories)
|
||||
if not shop or otcv8shop then return end
|
||||
local correctCategories = {}
|
||||
for i, category in ipairs(categories) do
|
||||
local image = ""
|
||||
if category.icon:len() > 0 then
|
||||
image = storeUrl .. category.icon
|
||||
end
|
||||
table.insert(correctCategories, {
|
||||
type = "image",
|
||||
image = storeUrl .. category.icon,
|
||||
image = image,
|
||||
name = category.name,
|
||||
offers = {}
|
||||
})
|
||||
@@ -176,10 +180,14 @@ function onStoreOffers(categoryName, offers)
|
||||
category.offers[offer] = nil
|
||||
end
|
||||
for i, offer in ipairs(offers) do
|
||||
local image = ""
|
||||
if offer.icon:len() > 0 then
|
||||
image = storeUrl .. offer.icon
|
||||
end
|
||||
table.insert(category.offers, {
|
||||
id=offer.id,
|
||||
type="image",
|
||||
image=storeUrl .. offer.icon,
|
||||
image=image,
|
||||
cost=offer.price,
|
||||
title=offer.name,
|
||||
description=offer.description
|
||||
@@ -397,7 +405,7 @@ function addCategory(data)
|
||||
end
|
||||
elseif data["type"] == "image" then
|
||||
category = g_ui.createWidget('ShopCategoryImage', shop.categories)
|
||||
if data["image"]:sub(1, 4):lower() == "http" then
|
||||
if data["image"] and data["image"]:sub(1, 4):lower() == "http" then
|
||||
HTTP.downloadImage(data['image'], function(path, err)
|
||||
if err then g_logger.warning("HTTP error: " .. err) return end
|
||||
category.image:setImageSource(path)
|
||||
@@ -446,7 +454,7 @@ function addOffer(category, data)
|
||||
end
|
||||
elseif data["type"] == "image" then
|
||||
offer = g_ui.createWidget('ShopOfferImage', shop.offers)
|
||||
if data["image"]:sub(1, 4):lower() == "http" then
|
||||
if data["image"] and data["image"]:sub(1, 4):lower() == "http" then
|
||||
HTTP.downloadImage(data['image'], function(path, err)
|
||||
if err then g_logger.warning("HTTP error: " .. err) return end
|
||||
if not offer.image then return end
|
||||
|
@@ -162,12 +162,15 @@ GameDoubleMagicLevel = 79
|
||||
|
||||
GameExtendedOpcode = 80
|
||||
GameMinimapLimitedToSingleFloor = 81
|
||||
GameSendWorldName = 82
|
||||
|
||||
GameDoubleLevel = 83
|
||||
GameDoubleSoul = 84
|
||||
GameDoublePlayerGoodsMoney = 85
|
||||
GameCreatureWalkthrough = 86 -- add Walkthrough for versions less than 854, unpass = msg->getU8(); in protocolgameparse.cpp
|
||||
GameDoubleTradeMoney = 87
|
||||
GameSequencedPackets = 88
|
||||
GameTibia12Protocol = 89
|
||||
|
||||
GameNewWalking = 90
|
||||
GameSlowerManualWalking = 91
|
||||
@@ -184,6 +187,7 @@ GameCenteredOutfits = 102
|
||||
GameSendIdentifiers = 103
|
||||
GameWingsAndAura = 104
|
||||
GamePlayerStateU32 = 105
|
||||
GameOutfitShaders = 106
|
||||
|
||||
GamePacketSizeU32 = 110
|
||||
GamePacketCompression = 111
|
||||
|
@@ -168,3 +168,9 @@ function Creature:onIconChange(iconId)
|
||||
self:setIconTexture(imagePath)
|
||||
end
|
||||
end
|
||||
|
||||
function Creature:setOutfitShader(shader)
|
||||
local outfit = self:getOutfit()
|
||||
outfit.shader = shader
|
||||
self:setOutfit(outfit)
|
||||
end
|
||||
|
Reference in New Issue
Block a user