Tabletop Simulator

Tabletop Simulator

Gloomhaven - Fantasy Setup (Scripted UI)
Zeik Jun 8, 2020 @ 10:30pm
Updated the Sort Hand logic
I've been absolutely loving this mod for weeks. It's let our group continue our physical campaign in the digital world! One thing that's bothered me for a long time is that if you have non-attack cards in your hand when you use Sort Hand from the Battle Interface it'd fail with an error.

I think it's much nicer if it sorts the attack cards by number and then sorts everything else alphabetically AFTER them. That way you can have battle goals or whatever else you need in your hand and it won't break sorting. Not sure how contributing to this mod works (couldn't find any source code links) so this post is the best I can do.


function sortHand(player, value, id)
local handObjects
if id == nil then
handObjects = player.getHandObjects(1)
else
handObjects = Player[id].getHandObjects(1)
end

local cards = {}
local handPos = {}
for i, j in pairs(handObjects) do
table.insert(cards, {j, tonumber(string.match(j.getName(), "%s%((%d+)%)-$")) or j.getName() or 100})
table.insert(handPos, j.getPosition())
end
table.sort(cards, function(a, b)
local aTypeStr = type(a[2]) == "string"
local bTypeStr = type(b[2]) == "string"
if (aTypeStr or bTypeStr) and not (aTypeStr and bTypeStr) then
if aTypeStr then
return false
else
return true
end
end
return a[2] < b[2]
end)
for i, j in ipairs(cards) do
j[1].setPosition(handPos[i])
end
end

Alternatively, if you just want the code to not break when sorting then this code just sorts attack cards by number and then leaves everything else in the same order it was already in:


function sortHand(player, value, id)
local handObjects
if id == nil then
handObjects = player.getHandObjects(1)
else
handObjects = Player[id].getHandObjects(1)
end

local cards = {}
local handPos = {}
for i, j in pairs(handObjects) do
table.insert(cards, {j, tonumber(string.match(j.getName(), "%s%((%d+)%)-$")) or 100})
table.insert(handPos, j.getPosition())
end
table.sort(cards, function(a, b) return a[2] < b[2] end)
for i, j in ipairs(cards) do
j[1].setPosition(handPos[i])
end
end

I swapped the default substringing for pattern matching just because it felt more reliable if it was going to have to deal with more potential names. There might still be some other cards that fit the attack card pattern but it's been working for us thus far.
Last edited by Zeik; Jun 8, 2020 @ 10:37pm