Started work on ingame clans interface several days ago, it will be included in next Toribash build after forum clans update is made public.
2 tabs available now, clan view and clan roster.
To launch the script, either run "/ls clans.lua" chat command (will open clanid = 1), alternatively you can run "/ls clans.lua [username]" command to open specific player's clan. Note that public Toribash builds don't support clans yet so you'll need to add "CLAN 0;clanid" line there. Also note that the attached data files only contain info for clanids 1 and 19, so if you try any other clanid you'll get an error.
Version 0.1.2 screenshots ►
v 0.2 source ►
clans.lua ►
Lua code:
-- clans view script
-- made by sir
CLANVIEWLASTPOS = CLANVIEWLASTPOS or nil
CLANLISTLASTPOS = { scroll = {}, list = {} }
FREEJOINENABLED = true
-- Creates clan class
function Clan:create(player)
local cln = {}
setmetatable(cln, Clan)
if (player == "" or nil) then
cln.clanid = nil
--player = get_master().master.nick
--end
else
cln.clanid = getClanId(player)
end
return cln
end
-- Populates clan data table
-- clans/clan.txt is fetched from server
function Clan:getClanData()
local entries = 0
local clans = {}
local data_types = { "clanname", "clantag", "isofficial", "rank", "clanlevel", "clanxp", "memberstotal", "isfreeforall", "clantopach", "isactive", "members", "leaders" }
local file = io.open("clans/clans.txt")
if (file == nil) then
err(ERR.clanDataEmpty)
file:close()
return false
end
for ln in file:lines() do
if string.match(ln, "^CLAN") then
local segments = 14
local data_stream = { ln:match(("([^\t]*)\t"):rep(segments)) }
if (data_stream[12] == "2") then
local clanid = tonumber(data_stream[2])
for i = 5, 12 do
data_stream[i] = tonumber(data_stream[i])
end
for i, v in ipairs(data_types) do
ClanData[clanid][v] = data_stream[i + 2]
end
entries = entries + 1
clans[entries] = clanid
end
end
end
file:close()
return clans
end
function Clan:getLevelData()
local data_types = { "minxp", "maxmembers", "officialonly" }
local file = io.open("clans/clanlevels.txt")
if (file == nil) then
err(ERR.clanLevelDataEmpty)
file:close()
return false
end
for ln in file:lines() do
if string.match(ln, "^LEVEL") then
local segments = 5
local data_stream = { ln:match(("([^\t]*)\t"):rep(segments)) }
local level = tonumber(data_stream[2])
LevelData[level] = {}
for i, v in ipairs(data_types) do
LevelData[level][v] = tonumber(data_stream[i + 2])
end
end
end
file:close()
return entries
end
function Clan:getAchievementData()
local data_types = { "achname", "achdesc" }
local file = io.open("clans/clanachievements.txt")
if (file == nil) then
err(ERR.clanAchievementDataEmpty)
file:close()
return false
end
for ln in file:lines() do
if string.match(ln, "^ACHIEVEMENT") then
local segments = 4
local data_stream = { ln:match(("([^\t]*)\t"):rep(segments)) }
local level = tonumber(data_stream[2])
AchievementData[level] = {}
for i, v in ipairs(data_types) do
AchievementData[level][v] = data_stream[i + 2]
end
end
end
--Displays clan list
function Clan:showClanList()
local clanListView = UIElement:new( { parent = clanView,
pos = { 0, clanTopBar.size.h },
size = {clanView.size.w, clanView.size.h - clanTopBar.size.h - 40} } )
local clanListClan = {}
local clanListClanRank = {}
local clanListClanTag = {}
local clanListClanName = {}
local clanListClanMembers = {}
local clanListClanOfficial = {}
local clanListClanJoinMode = {}
local listEntryHeight = 40
-- run replacement draw function to ensure proper scroll work
clanListClan[i]:addCustomDisplay(false, function()
-- Draw clan info
local textScaleMod = 0.82
local clanRank = ClanData[allClans[i]].rank
if (clanRank == 0) then
clanRank = "-"
end
set_color(1,1,1,1)
clanListClanRank[i]:uiText(clanRank, nil, nil, FONTS.MEDIUM, CENTER, textScaleMod)
local clanTag = "(" .. ClanData[allClans[i]].clantag .. ")"
if (ClanData[allClans[i]].isofficial == 1) then
clanTag = "[" .. ClanData[allClans[i]].clantag .. "]"
end
clanListClanTag[i]:uiText(clanTag, nil, nil, FONTS.MEDIUM, RIGHT, textScaleMod)
draw_quad(clanListClanName[i].pos.x - 5.5, clanListClanName[i].pos.y + 10, 1, 20)
local clanName = ClanData[allClans[i]].clanname
if (get_string_length(clanName, FONTS.MEDIUM) * textScaleMod > clanListClanName[i].size.w) then
clanListClanName[i]:uiText(clanName, clanListClanName[i].pos.x, clanListClanName[i].pos.y, FONTS.MEDIUM, LEFT, textScaleMod)
else
clanListClanName[i]:uiText(clanName, clanListClanName[i].pos.x, clanListClanName[i].pos.y + 9, FONTS.MEDIUM, LEFT, textScaleMod)
end
if (ClanData[allClans[i]].isofficial == 1) then
clanListClanOfficial[i]:uiText("Official", clanListClanOfficial[i].pos.x, clanListClanOfficial[i].pos.y, FONTS.MEDIUM, CENTER, textScaleMod)
else
clanListClanOfficial[i]:uiText("Unofficial", clanListClanOfficial[i].pos.x, clanListClanOfficial[i].pos.y, FONTS.MEDIUM, CENTER, textScaleMod)
end
if (ClanData[allClans[i]].isfreeforall == 1) then
clanListClanJoinMode[i]:uiText("Free for all", clanListClanJoinMode[i].pos.x, clanListClanJoinMode[i].pos.y, FONTS.MEDIUM, CENTER, textScaleMod)
else
clanListClanJoinMode[i]:uiText("Invite Only", clanListClanJoinMode[i].pos.x, clanListClanJoinMode[i].pos.y, FONTS.MEDIUM, CENTER, textScaleMod)
end
if (i ~= #allClans) then
draw_line(clanListClan[i].pos.x, clanListClan[i].pos.y + clanListClan[i].size.h - 1, clanListClan[i].pos.x + clanListClan[i].size.w, clanListClan[i].pos.y + clanListClan[i].size.h - 1, 1)
end
end)
clanListClan[i]:addMouseHandlers(function() end,
function()
CLANLISTLASTPOS = { scroll = clanListScrollBar:getPos(), list = clanListClanArea:getPos() }
clanListView:kill()
Clan:showClan(allClans[i])
end, function() end)
end
clanViewBackButton:addMouseHandlers(function() end, function() end, function() end)
clanViewBackButton:hide()
tabName:addCustomDisplay(false, function()
set_color(1,1,1,1)
tabName:uiText("Clan List", tabName.pos.x, tabName.pos.y, FONTS.BIG, CENTER, 0.7)
end)
end
-- Displays single clan data
function Clan:showClan(clanid)
local clanLevelValue = ClanData[clanid].clanlevel
local clanTopAch = ClanData[clanid].clantopach
local xpBarProgress = (ClanData[clanid].clanxp - LevelData[clanLevelValue].minxp) / (LevelData[clanLevelValue + 1].minxp - LevelData[clanLevelValue].minxp)
clanViewBackButton:addMouseHandlers(function() end,
function()
Clan:showClan(clanid)
clanLeadersView:kill()
clanMembersView:kill()
end, function() end)
tabName:addCustomDisplay(false, function()
local clanNameStr = nil
if (ClanData[clanid].isofficial == 1) then
clanNameStr = "[" .. ClanData[clanid].clantag .. "] Clan Roster"
else
clanNameStr = "(" .. ClanData[clanid].clantag .. ") Clan Roster"
end
set_color(1,1,1,1)
tabName:uiText(clanNameStr, tabName.pos.x, tabName.pos.y, FONTS.BIG, CENTER, 0.7)
end)
end
function getClanId(player)
local str = "[)\]]"
local strMatch = string.find(player, str)
if (strMatch) then
player = string.sub(player, strMatch + 1)
end
local file = io.open("custom/" .. player .. "/item.dat", 'r', 60)
if (file == nil) then
err(ERR.playerFolderPerms)
file:close()
return false
end
for ln in file:lines() do
if string.match(ln, "CLAN 0;") then
local clanid = string.gsub(ln, "CLAN 0;", "")
clanid = tonumber(clanid)
file:close()
return clanid
end
end
err(ERR.playerFolderClan)
file:close()
return false
end
function Clan:drawVisuals()
for i, v in pairs(UIElementManager) do
v:updatePos()
end
for i, v in pairs(UIVisualManager) do
v:display()
end
end
end
do
UIElementManager = {}
UIVisualManager = {}
UIMouseHandler = {}
UIElement = {}
UIElement.__index = UIElement
-- Spawns new UI Element
function UIElement:new(o)
local elem = { parent = nil,
child = {},
text = nil,
pos = { x = nil, y = nil },
shift = { x = nil, y = nil },
size = { w = nil, h = nil },
bgColor = { 1, 1, 1, 0 },
bgImage = nil,
shapeType = SQUARE,
customDisplayTrue = false,
customDisplay = function() end,
interactive = false,
}
setmetatable(elem, UIElement)
o = o or nil
if (o) then
if (o.parent) then
elem.parent = o.parent
table.insert(elem.parent.child, elem)
elem.shift.x = o.pos[1]
elem.shift.y = o.pos[2]
else
elem.pos.x = o.pos[1]
elem.pos.y = o.pos[2]
end
elem.size.w = o.size[1]
elem.size.h = o.size[2]
if (o.text) then elem.text = o.text end
if (o.bgColor) then
elem.bgColor = o.bgColor
end
if (o.bgImage) then
local tempicon = io.open(o.bgImage)
if (tempicon == nil) then
elem.bgImage = load_texture(DEFAULTITEXTURE)
else
elem.bgImage = load_texture(o.bgImage)
io.close(tempicon)
end
end
if (o.shapeType) then
elem.shapeType = o.shapeType
if (o.rounded * 2 > elem.size.w or o.rounded * 2 > elem.size.h) then
if (elem.size.w > elem.size.h) then
elem.rounded = elem.size.h / 2
else
elem.rounded = elem.size.w / 2
end
else
elem.rounded = o.rounded
end
end
if (o.interactive) then
elem.interactive = o.interactive
elem.scrollEnabled = o.scrollEnabled or nil
elem.hoverColor = o.hoverColor or nil
elem.pressedColor = o.pressedColor or nil
elem.hoverState = false
elem.pressedPos = { x = nil, y = nil }
elem.btnDown = function() end
elem.btnUp = function() end
elem.btnHover = function() end
table.insert(UIMouseHandler, elem)
end
end
table.insert(UIElementManager, elem)
table.insert(UIVisualManager, elem) -- Display is enabled by default, comment this line out to disable
return elem
end
function UIElement:addMouseHandlers(btnDown, btnUp, btnHover)
if (btnDown) then
self.btnDown = btnDown
end
if (btnUp) then
self.btnUp = btnUp
end
if (btnHover) then
self.btnHover = btnHover
end
end
function UIElement:addScrollFor(list, listElements, topBorder, botBorder, shiftPosList, shiftPosScroll, speed)
local shiftPosList = shiftPosList or 0
local shiftPosScroll = shiftPosScroll or 0
local speed = speed or 1
local elHeight = listElements[1].size.h
local scrollMin = self.shift.y
local scrollMax = self.parent.size.h - scrollMin - self.size.h
local minHeight = list.shift.y
local maxHeight = #listElements * elHeight
local enabled = nil
if (shiftPosList ~= 0) then
enabled = list:getEnabled(listElements, -shiftPosList + minHeight)
else
enabled = list:getEnabled(listElements, 0)
end
self:addMouseHandlers(
function(s, x, y)
if (s < 4) then
self.pressedPos = self:getLocalPos(x,y)
self.hoverState = BTN_DN
else
self:mouseScroll(list, elHeight, scrollMin, scrollMax, minHeight, maxHeight, y * speed)
enabled = self:scrollElements(listElements, topBorder, botBorder, enabled)
end
end, nil,
function(x, y)
if (self.hoverState == BTN_DN) then
local lPos = self:getLocalPos(x,y)
local posY = lPos.y - self.pressedPos.y + self.shift.y
self:barScroll(list, elHeight, scrollMin, scrollMax, minHeight, maxHeight, posY)
enabled = self:scrollElements(listElements, topBorder, botBorder, enabled)
end
end)
if (shiftPosScroll ~= 0 and shiftPosList ~= 0) then
self:moveTo(nil, shiftPosScroll)
list:moveTo(nil, shiftPosList)
end
end
function UIElement:getEnabled(elements, shiftPos)
local enabled = {}
local elHeight = elements[1].size.h
for i = 1, #elements do
if (i * elHeight - shiftPos > self.size.h or i * elHeight - shiftPos < 0) then
elements[i]:hide()
enabled[i] = false
else
enabled[i] = true
end
end
return enabled
end
function UIElement:mouseScroll(list, elHeight, scrollMin, scrollMax, minHeight, maxHeight, speed)
if (list.shift.y + speed * elHeight >= minHeight) then
self:moveTo(self.shift.x, scrollMin)
list:moveTo(list.shift.x, minHeight)
elseif (list.shift.y + speed * elHeight <= -maxHeight) then
self:moveTo(self.shift.x, scrollMax)
list:moveTo(list.shift.x, -maxHeight)
else
list:moveTo(list.shift.x, list.shift.y + speed * elHeight)
local scrollProgress = -(list.shift.y - minHeight) / (maxHeight + minHeight)
self:moveTo(self.shift.x, scrollMin + (self.parent.size.h - self.size.h - scrollMin * 2) * scrollProgress)
end
end
function UIElement:barScroll(list, elHeight, scrollMin, scrollMax, minHeight, maxHeight, posY)
local sizeH = math.floor(self.size.h / 4)
local scrollScale = (self.parent.size.h - (scrollMin * 2 + self.size.h)) / maxHeight
if (posY <= scrollMin) then
if (self.pressedPos.y < sizeH) then
self.pressedPos.y = sizeH
end
self:moveTo(self.shift.x, scrollMin)
list:moveTo(list.shift.x, minHeight)
elseif (posY >= scrollMax) then
if (self.pressedPos.y > self.parent.size.h - sizeH) then
self.pressedPos.y = self.parent.size.h - sizeH
end
function UIElement:scrollElements(list, topBorder, botBorder, enabled)
for i = 1, #list do
lPos = list[i]:getLocalPos(0,0)
if (-lPos.y <= topBorder.pos.y or -lPos.y >= botBorder.pos.y) then
if (enabled[i] == true) then
list[i]:hide()
enabled[i] = false
end
else
if (enabled[i] == false) then
list[i]:show()
enabled[i] = true
end
end
end
topBorder:hide()
botBorder:hide()
topBorder:show()
botBorder:show()
return enabled
end
function UIElement:addCustomDisplay(funcTrue, func)
self.customDisplayTrue = funcTrue
self.customDisplay = func
end
function UIElement:kill()
for i,v in pairs(self.child) do
v:kill()
end
self:hide()
self = { pos = { x = nil, y = nil },
size = { w = nil, h = nil },
bgColor = { 1, 1, 1, 0 }
}
if (self.bgImage) then unload_texture(self.bgImage) end
end
function UIElement:updatePos()
if (self.parent) then
self:updateChildPos()
end
end
function UIElement:display()
if (not self.customDisplayTrue) then
if (self.hoverState == BTN_HVR and self.hoverColor) then
set_color(unpack(self.hoverColor))
elseif (self.hoverState == BTN_DN and self.pressedColor) then
set_color(unpack(self.pressedColor))
else
set_color(unpack(self.bgColor))
end
if (self.shapeType == ROUNDED) then
draw_disk(self.pos.x + self.rounded, self.pos.y + self.rounded, 0, self.rounded, 500, 1, -180, 90, 0)
draw_disk(self.pos.x + self.rounded, self.pos.y + self.size.h - self.rounded, 0, self.rounded, 500, 1, -90, 90, 0)
draw_disk(self.pos.x + self.size.w - self.rounded, self.pos.y + self.rounded, 0, self.rounded, 500, 1, 90, 90, 0)
draw_disk(self.pos.x + self.size.w - self.rounded, self.pos.y + self.size.h - self.rounded, 0, self.rounded, 500, 1, 0, 90, 0)
draw_quad(self.pos.x + self.rounded, self.pos.y, self.size.w - self.rounded * 2, self.rounded)
draw_quad(self.pos.x, self.pos.y + self.rounded,self.size.w, self.size.h - self.rounded * 2)
draw_quad(self.pos.x + self.rounded, self.pos.y + self.size.h - self.rounded, self.size.w - self.rounded * 2, self.rounded)
else
draw_quad(self.pos.x, self.pos.y, self.size.w, self.size.h)
end
if (self.bgImage) then
draw_quad(self.pos.x, self.pos.y, self.size.w, self.size.h, self.bgImage)
end
end
self.customDisplay()
end
function UIElement:show()
local num = nil
for i,v in pairs(UIVisualManager) do
if (self == v) then
num = i
break
end
end
if (not num) then
table.insert(UIVisualManager, self)
if (self.interactive) then
table.insert(UIMouseHandler, self)
end
end
end
function UIElement:hide()
local num = nil
for i,v in pairs(self.child) do
v:hide()
end
if (self.interactive) then
for i,v in pairs(UIMouseHandler) do
if (self == v) then
num = i
break
end
end
if (num) then
table.remove(UIMouseHandler, num)
else
err(UIMouseHandlerEmpty)
end
end
for i,v in pairs(UIVisualManager) do
if (self == v) then
num = i
break
end
end
if (num) then
table.remove(UIVisualManager, num)
else
err(UIElementEmpty)
end
end
function UIElement:handleMouseDn(s, x, y)
for i, v in pairs(UIMouseHandler) do
if (x > v.pos.x and x < v.pos.x + v.size.w and y > v.pos.y and y < v.pos.y + v.size.h and s < 4) then
v.hoverState = BTN_DN
v.btnDown(s, x, y)
elseif (s >= 4 and v.scrollEnabled == true) then
v.btnDown(s, x, y)
end
end
end
function UIElement:handleMouseUp(s, x, y)
for i, v in pairs(UIMouseHandler) do
if (v.hoverState == BTN_DN) then
v.hoverState = nil
v.btnUp(s, x, y)
end
end
end
function UIElement:handleMouseHover(x, y)
for i, v in pairs(UIMouseHandler) do
if (x > v.pos.x and x < v.pos.x + v.size.w and y > v.pos.y and y < v.pos.y + v.size.h) then
if (v.hoverState ~= BTN_DN) then
v.hoverState = BTN_HVR
end
v.btnHover(x,y)
elseif (v.hoverState == BTN_DN) then
v.btnHover(x,y)
else
v.hoverState = false
end
end
end
function UIElement:moveTo(x, y)
if (self.parent) then
if (x) then self.shift.x = x end
if (y) then self.shift.y = y end
else
if (x) then self.pos.x = x end
if (y) then self.pos.y = y end
end
end
function UIElement:updateChildPos()
if (self.shift.x < 0) then
self.pos.x = self.parent.pos.x + self.parent.size.w + self.shift.x
else
self.pos.x = self.parent.pos.x + self.shift.x
end
if (self.shift.y < 0) then
self.pos.y = self.parent.pos.y + self.parent.size.h + self.shift.y
else
self.pos.y = self.parent.pos.y + self.shift.y
end
end
function UIElement:uiText(str, x, y, font, align, scale, angle)
local font = font or FONTS.SMALL
local x = x or self.pos.x
local y = y or self.pos.y
local font_mod = font
local scale = scale or 1
local angle = angle or 0
local pos = 0
local align = align or LEFT
if (font == FONTS.BIG) then
font_mod = 4.5
elseif (font == 4) then
font_mod = 2.4
elseif (font == FONTS.SMALL) then
font_mod = 1.5
end
str = textAdapt(str, font, scale, self.size.w)
for i = 1, #str do
if (align == CENTER) then
xPos = x + self.size.w / 2 - get_string_length(str[i], font) * scale / 2
elseif (align == RIGHT) then
xPos = x + self.size.w - get_string_length(str[i], font) * scale
else
xPos = x
end
if (self.size.h > (pos + 1) * font_mod * 10 * scale + font_mod * 10) then
draw_text_angle_scale(str[i], xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
if (font == FONTS.BIG or font == FONTS.MEDIUM) then
draw_text_angle_scale(str[i], xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
end
pos = pos + 1
elseif (i ~= #str) then
draw_text_angle_scale(str[i]:gsub(".$", "..."), xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
if (font == FONTS.BIG or font == FONTS.MEDIUM) then
draw_text_angle_scale(str[i]:gsub(".$", "..."), xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
end
break
else
draw_text_angle_scale(str[i], xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
if (font == FONTS.BIG or font == FONTS.MEDIUM) then
draw_text_angle_scale(str[i], xPos, y + (pos * font_mod * 10 * scale), angle, scale, font)
end
end
end
end
function UIElement:setButtonColor()
if (self.hoverState == BTN_DN) then
set_color(unpack(self.pressedColor))
elseif (self.hoverState == BTN_HVR) then
set_color(unpack(self.hoverColor))
else
set_color(unpack(self.bgColor))
end
end
function UIElement:getPos()
local pos = {self.shift.x, self.shift.y}
return pos
end
function UIElement:getLocalPos(xPos, yPos, pos)
local pos = pos or { x = xPos, y = yPos}
if (self.parent) then
pos = self.parent:getLocalPos(xPos, yPos, pos)
if (self.shift.x < 0) then
pos.x = pos.x - self.parent.size.w - self.shift.x
else
pos.x = pos.x - self.shift.x
end
if (self.shift.y < 0) then
pos.y = pos.y - self.parent.size.h - self.shift.y
else
pos.y = pos.y - self.shift.y
end
else
pos.x = xPos - self.pos.x
pos.y = yPos - self.pos.y
end
return pos
end
function textAdapt(str, font, scale, maxWidth)
local destStr = {}
while ((get_string_length(str, font) * scale) > maxWidth) do
local newStr = string.match(str, "[^%s]+[%s]*")
str = str:gsub(strEsc(newStr), "")
if (str == "") then
table.insert(destStr, newStr)
return destStr
end
str = addWord(destStr, str, newStr, font, scale, maxWidth)
end
table.insert(destStr, str)
return destStr
end
function addWord(destStr, str, newStr, font, scale, maxWidth)
local word = string.match(str, "%a+.")
if ((get_string_length(newStr .. word, font) * scale) < maxWidth) then
str = str:gsub(word, "")
newStr = newStr..word
str = addWord(destStr, str, newStr, font, scale, maxWidth)
return str
else
table.insert(destStr, newStr)
return str
end
end
function strEsc(str)
return (str:gsub('%(', '%%(')
:gsub('%)', '%%)')
:gsub('%[', '%%[')
:gsub('%]', '%%]'))
end
end
clans/errors.lua ►
Lua code:
-- errors class
do
ERR = { playerFolderPerms = "^36Clans ^07:: Failed to load player's clan, please download player's customs first ^07and verify folder permissions",
playerFolderClan = "^36Clans ^07:: Failed to read player's clan, please verify you're using the latest ^07version of Toribash",
clanDataEmpty = "^36Clans ^07:: Failed to load clans' info, please verify cache integrity and folder permissions",
clanLevelDataEmpty = "^36Clans ^07:: Failed to load levels data, please verify cache integrity and folder permissions",
clanAchievementDataEmpty = "^36Clans ^07:: Failed to load clan achievements data, please verify cache integrity and folder permissions",
UIElementEmpty = "^36UIManager ^07:: Element not found",
UIMouseHandlerEmpty = "^36UIMouseHandler ^07:: Element not found",
}
function err(str)
local errors = false
echo(str)
--[[add_hook("console", "error", function(s, i)
if (s:match("^Error")) then
errors = true
return 1
elseif (errors) then
remove_hooks("errors")
end
end)--]]
end
end
Had some other stuff to work on lately, got back to this few days ago.
Updated with v 0.2, see changelog below:
Changelog ►
clandatamanager.lua
- Added clan list view
- Press and drag topbar to move window
- getClanData() now returns a table with loaded clanids (active clans only)
- Some fixes for showClan()
- drawVisuals() now updates position for all visible elements
uielement.lua
- show() - check if already shown
- handleMouseUp() - hover state nil
- handleMouseHover() - fix to avoid losing hover while mouse down
- moveTo() - fix to work with child items
- Added addScrollFor() to create a scrollable list (requires a scrollbar, works with both mouse scroll and scrollbar dragging)
- Added misc methods used by addScrollFor() - getEnabled(), mouseScroll(), barScroll(), scrollElements()
- Added getPos() and getLocalPos()
- create() now checks whether bgImage exists first before loading
errors.lua
- removed console hook for now
Steam client should download clan/level/achievement info to data/script/clans but grezet messed memberinfo up so it's not accurate for now. Will fix in coming days.
Not updating source/attachments for now, you can download a new version from github.
Had some other stuff to work on lately, got back to this few days ago.
Updated with v 0.2, see changelog below:
Changelog ►
clandatamanager.lua
- Added clan list view
- Press and drag topbar to move window
- getClanData() now returns a table with loaded clanids (active clans only)
- Some fixes for showClan()
- drawVisuals() now updates position for all visible elements
uielement.lua
- show() - check if already shown
- handleMouseUp() - hover state nil
- handleMouseHover() - fix to avoid losing hover while mouse down
- moveTo() - fix to work with child items
- Added addScrollFor() to create a scrollable list (requires a scrollbar, works with both mouse scroll and scrollbar dragging)
- Added misc methods used by addScrollFor() - getEnabled(), mouseScroll(), barScroll(), scrollElements()
- Added getPos() and getLocalPos()
- create() now checks whether bgImage exists first before loading
errors.lua
- removed console hook for now
Steam client should download clan/level/achievement info to data/script/clans but grezet messed memberinfo up so it's not accurate for now. Will fix in coming days.
Not updating source/attachments for now, you can download a new version from github.
When trying to do /ls clans.lua in game it gives me an error do i need to do /ls clans.lua <username> or should it work as-is?
[Solus] Leader | Mod Creator | Graphic Artist | Programmer Like Coding, Design, Gaming, Or More?Join Mesh
Think You're Unique? Apply to Solus!
When trying to do /ls clans.lua in game it gives me an error do i need to do /ls clans.lua <username> or should it work as-is?
Forgot we added more data to clan info file, updated it with what Steam client currently uses.
Same download link should work.
-----
Updated OP with latest version's source, replaced attachments with download link from github.
Last edited by sir; Oct 25, 2017 at 08:12 PM..
Reason: <24 hour edit/bump