Sorting objects based on a value(Or alternative methods for tracking a players kills)

TL;DR - How would you sort a table of Tags based on the Damage value.

Example of an object to be sorted

--Example of a table of tags (Objects with values)
local tags = {}

--Example of a Tag
local tag = Instance.new("BoolValue")
tag.Name = "Tag"
Instance.new("IntValue",tag).Name = "UserId"
Instance.new("IntValue",tag).Name = "Damage"


--Some tags
local Tag1 = tag:Clone()
print(unpack(Tag1:GetChildren()))
Tag1.UserId.Value = 1
Tag1.Damage.Value = 80

local Tag2 = tag:Clone()
Tag2.UserId.Value = 2
Tag2.Damage.Value = 15

local Tag3 = tag:Clone()
Tag3.UserId.Value = 3
Tag3.Damage.Value = 5

table.insert(tags,Tag3) --I added the tags to the table in lowest to highest order of damage
table.insert(tags,Tag2) --to give an example for them to be sorted.
table.insert(tags,Tag1)

--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
--TAGS TABLE NEEDS TO BE SORTED
--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

local highest = tags[1]
local secondHighest = tags[2]

print(highest.UserId.Value .. " got the kill")
print(secondHighest .UserId.Value .. " got the assist")

Here’s the long version
So as the title suggests I want to track player kills so I can reward the player who got the kill and people who assisted.
My current method for doing this is to store a “Tag” on the enemy players Humanoid when they are hit with the killers weapon. The Tag contains the Killers userId and is updated every time the enemy player is hit to store the killers total damage done. When the enemy player dies they could have a number of tags on them.
What I want to do is retrieve the tags and sort them by damage done (Highest to lowest) so I can reward the killers with a kill and the person with second most damage with an assist.
The problem is finding a way to sort the Tags based on damage since the table of retreived tags isn’t a table of int value but rather the int values are inside the Tags.

I’m also questioning if placing tags inside the Humanoid poses a secuirty risk. For example could a player destroy all tags that build up on their humanoid and stop their enemys from receiving rewards for killing them?

Additional inormation
My current solution to this problem is convoluted, I use a quick sort to sort the tags

The quick sort

function quickSort(list) --Table of tags is passed as list
	help(list,1,#list)
	return list
end

function help(list,first,last)
	if first < last then
		
		local mid = findMid(list,first,last)
		
		help(list,mid+1,last)
		help(list,first,mid-1)
	end
end

function findMid(list,first,last)
	local p = list[first]
	local l = first + 1
	local r = last
	local done = false
	while done == false do
		while l <= r and list[l].Damage.Value >= p.Damage.Value do
			l = l + 1
		end
		while r >= l and list[r].Damage.Value <= p.Damage.Value do
			r = r - 1
		end
		if l < r then
			local temp = list[r]
			list[r] = list[l]
			list[l] = temp
		else
			done = true
		end
	end
	list[first] = list[r]
	list[r] = p
	return r
end
1 Like

From shortest to largest or the other way around?

2 Likes

From largest to smallest. (Post must be at least 30 character long… I wrote this to meet the character limit)

1 Like

You don’t need to reverse it, you can inversely sort it in one call.

table.sort takes a predicate as its second parameter, you can feed an inverse sorting function there.

local values = {1, 4, 5, 2, 3}

table.sort(values, function(a, b) return a > b end)

for _, value in ipairs(values) do
  print(value)
end
--[[ prints:
5
4
3
2
1
--]]
3 Likes

I tried sorting the table but since the values stored are instances of objects and not int values it wont alow me to use table.sort since it would require comparing instances.
Sample script

--Example of a table of tags (Objects with values)
local tags = {}

--Tag
local tag = Instance.new("BoolValue")
tag.Name = "Tag"
Instance.new("IntValue",tag).Name = "UserId"
Instance.new("IntValue",tag).Name = "Damage"


--Some tags
local Tag1 = tag:Clone()
print(unpack(Tag1:GetChildren()))
Tag1.UserId.Value = 1
Tag1.Damage.Value = 80

local Tag2 = tag:Clone()
Tag2.UserId.Value = 2
Tag2.Damage.Value = 15

local Tag3 = tag:Clone()
Tag3.UserId.Value = 3
Tag3.Damage.Value = 5

table.insert(tags,Tag3) --I added the tags to the table in lowest to highest order of damage
table.insert(tags,Tag2) --to give an example for them to be sorted.
table.insert(tags,Tag1)


--Attempt to sort using table.sort
table.sort(tags, function(a, b) return a > b end) -- Triggers error attempt to compare instance

local highest = tag[1]
local secondHighest = tag[2]

print(highest.UserId.Value .. " got the kill")
print(highest.UserId.Value .. " got the assist")

You can make the predicate anything you want. It just compares 2 things in the array.

Based on your code earlier:

(...) list[l].Damage.Value >= p.Damage.Value

Your predicate would probably look like:

function(a, b) return a.Damage.Value > b.Damage.Value end

Just edit how a/b are indexed so it works with the types of values in your array.

2 Likes