Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Help with creating a Queue/Priority system?

Asked by 8 years ago

Hello-

I'm working on creating a basic GUI that lists a Queue of "Announcements" in this case that can be prioritized based on a value. When a new announcement is created, I'd like it to appear in the appropriate space(Like 4 appearing between 3 and 5). I don't have any experience with Queue-making and I am wondering what the most efficient way to do this would be.

Below is a really simple little program that kinda outlines the basis of what I'm trying to do, but I'm still a bit lost so any help provided is great, Thanks!

local Integer = 1
script.Parent.TextButton.MouseButton1Down:connect(function(hit)
    print("Creating New Announcement")

    local Announcement = script.Parent.TextBox:Clone()
    Announcement.Parent = script.Parent
    Announcement.Visible = true
    Announcement.Position = UDim2.new(0,0,0.1*Integer,0)
    Integer = Integer +1
    wait(5)--Destroys GUI after a while and reduces Integer again.
    Announcement:Destroy()
    Integer = Integer - 1
end)
0
I'm thinking along the lines of an Array that is updated with announcements and GUI is made to match it? lordrex12345 25 — 8y
0
What exactly do you mean by "queue"? Would it show the oldest, highest-priority message, then after a few seconds remove it from the queue and move onto the next one? BlueTaslem 18071 — 8y
0
Yes, that the basic idea except messages would stay put until an objective is met and would re-order themselves according to their priority. One example could be a standard Quest system, or a list of calendar-events re-ordering themselves by date. lordrex12345 25 — 8y

1 answer

Log in to vote
1
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago

You have Objectives. They stay open until they are somehow cleared.

Here's one way you can organize it.

There are two important functions:

-- Add a new objective with a given priority
function Add(objective, priority)
end

-- Display all unsolved objectives
function ShowAll()
end

We'll need a list of all of the objectives currently open, and we'll need Add to put into it something that has (1) the objective data, (2) something saying it's still open, and (3) the priority.

You might also want to add, e.g., a Frame so that you can do animations when there are updates, instead of just erasing and updating everything in ShowAll. I'll show that here.

local objectives = {} -- All open objectives
function Add(objective, priority)
    local o = { data = objective, priority = priority }
    o.gui = Instance.new("Frame", script.Parent)
    o.gui.Position = UDim2.new(0.5, 0, 0.5, 0)
    o.gui.Size = UDim2.new(0, 0, 0, 0)
    -- Add text labels or whatever:
    local label = Instance.new("TextLabel", o.gui)
    label.Text = objective
    label.TextScaled = true
    label.BackgroundTransparency = 1
    -- Update the view every time there's a new priority:
    ShowAll()
    return o
end

We can also add a Complete function which gets rid of the o.gui:

function Complete(objective)
    o.gui:TweenSize( UDim2.new(0,0,0,0), nil, nil, 1, true)
    delay(1, function() o.gui:Destroy() end)
end

Now we need ShowAll to (1) clear solved objectives, (2) sort current objectives, and (3) display the objectives.

table.remove can remove something at a given index. The simplest way to make this work is a for loop that moves from back to front (since table.remove shifts all the indices down, going up doesn't work).

Sorting is easy with table.sort. We can give a function telling how to compare to objects, which puts larger .priority fields first:

function ShowAll()
    for i = #objectives, 1, -1 do
        if objectives[i].cleared then
            Complete( table.remove(objectives, i) )
        end
    end
    table.sort(objectives, function(a,b) return a.priority > b.priority end)

You then should choose to display either the first or all objectives. Here I'll display the first, and the rest separately:

    if objectives[1] then
        objectives[1].gui:TweenPosition(UDim2.new(0,0,0,0))
        objectives[1].gui.TweenSize(UDim2.new(1, 0, 0, 72))
    end
    for i = 2, #objectives do
        objectives[i].gui:TweenPosition(UDim2.new(1, -100, 0, 72+(i-2)*36), nil, nil, 1, true)
        objectives[i].gui:TweenSize(UDim2.new(0, 100, 0, 36), nil, nil, 1, true)
    end
end

To finish an objective, you should add cleared onto the thing that Add returns:

local objective = Add("Wait 10 seconds", 1)
wait(10)
objective.cleared = true
ShowAll() -- update

It may be reasonable to simply ShowAll on a loop every one second instead. Note that if you interrupt Tweens, it will look a little strange, so if you have very frequent updates, you might run into some issues.

Also be aware that this is not fast. Sorting hundreds or thousands of elements when you add one thing isn't the fastest -- but if you have less than a few dozen it'll still be instant

1
Awesome stuff! Thanks a lot, it's just what I needed. I had to fix a minor syntax error and added in: table.insert(objectives, o) to make it work properly, but it was well done. Thanks again. lordrex12345 25 — 8y
0
Thanks for catching that, fixed BlueTaslem 18071 — 8y
Ad

Answer this question