HGK Flexible Quest System

Hello!! :wave:(˶ᵔ ᵕ ᵔ˶)
This time I’m sharing a simple but flexible quest system for HGK. It’s flexible because it’s reusable, each quest can have any number of tasks and a custom required amount for completion. The design is simple, but it works great for lots of small horror games.

I’ve included a step-by-step video tutorial showing how I built it, plus the script you can use in your project.

:movie_camera: Video

:memo: Script

local UIField = script.fields.UIField
local TaskTextList = script.fields.TaskTextList
local TaskCountList = script.fields.TaskCountList
local TaskProgressObj = script.fields.TaskProgressObj
local QuestCompleteObj = script.fields.QuestCompleteObj
local TaskCompleteList = script.fields.TaskCompleteList

local YaResourceManager = YahahaMiddleLayerSlim.Resource.YaResourceManager 

local mainPanel
local packageName

local UITextComp
local UICountComp

local taskProgress = {}
local self = script.gameObject

script.OnStart(function ()
    LoadResource()
end)

function LoadResource()
    YaResourceManager.LoadResourceByUIPackageField(UIField, function(state, name)
        if state == AssetStatus.AllAssetCompleted then
            packageName = name
            CreateMainPanel()
        end
    end)
end

function CreateMainPanel()
    mainPanel = UIPackage.CreateObject(packageName, "TaskUI")
    GRoot.inst:SetContentScaleFactor(2436, 1125)
    GRoot.inst:AddChild(mainPanel)
    mainPanel.size = GRoot.inst.size
    mainPanel:AddRelation(GRoot.inst, RelationType.Size)

    UITextComp = {
        mainPanel:GetChild("Task1Text"),
        mainPanel:GetChild("Task2Text"),
        mainPanel:GetChild("Task3Text"),
    }
    UICountComp = {
        mainPanel:GetChild("Task1Count"),
        mainPanel:GetChild("Task2Count"),
        mainPanel:GetChild("Task3Count"),
    }
    for i = 1, #TaskTextList do
        taskProgress[i] = 0
    end
    UpdateTaskUI()
end

function UpdateTaskUI()
    for i = 1, #UITextComp do
        if TaskTextList[i] then
            UITextComp[i].visible = true
            UICountComp[i].visible = true
            UITextComp[i].text = TaskTextList[i]
            UICountComp[i].text = tostring(taskProgress[i] or 0) .. "/" .. tostring(TaskCountList[i] or 0)
        else
            UITextComp[i].visible = false
            UICountComp[i].visible = false
            UITextComp[i].text = ""
        end
    end

    local allComplete = true
    for i = 1, #TaskCountList do
        local current = taskProgress[i] or 0
        local required = TaskCountList[i] or 0

        if required == 0 then
        elseif current >= required then
            if TaskCompleteList[i] then
                TaskCompleteList[i]:SetActive(true)
            end
            taskProgress[i] = required
        else
            allComplete = false
        end
    end

    if allComplete and QuestCompleteObj then
        print("Quest Complete!")
        QuestCompleteObj:SetActive(true)
        OnDispose()
    end
end


script.OnUpdate(function ()
    for i, obj in ipairs(TaskProgressObj) do
        if obj.activeInHierarchy then
            taskProgress[i] = (taskProgress[i] or 0) + 1
            UpdateTaskUI()
            obj:SetActive(false)
        end
    end
end)

function OnDispose()
    if mainPanel then
        mainPanel:Dispose()
    end
    self:SetActive(false)
    YaResourceManager.RemoveResourceByUIPackageField(UIField)
end

:memo: Editor

local fieldDefs = {
    {
        name = "UIField",
        label = "UI Field",
        hint = "UI Field",
        description = "UI Field",
        type = "UIPackageFile"
    },
    {
        name = "TaskTextList",
        type = {
            type = "list",
            items = {
                name = "TaskText",
                type = "string"
            }
        }
    },
    {
        name = "TaskCountList",
        type = {
            type = "list",
            items = {
                name = "TaskCount",
                type = "integer"
            }
        }
    },
    {
        name = "TaskProgressObj",
        type = {
            type = "list",
            items = {
                name = "TaskProgress",
                type = "GameObject",
            }
        }
    },
    {
        name = "TaskCompleteList",
        type = {
            type = "list",
            items = {
                name = "TaskComplete",
                type = "GameObject",
            }
        }
    },
    { name ="QuestCompleteObj", type = "GameObject" }
}
script.DefineFields(fieldDefs)
1 Like