饥荒Mod 开发(九):物品栏排列

饥荒Mod 开发(八):游戏所有食材和食物
饥荒Mod 开发(十):制作一把AOE武器
物品栏排序这个功能还是很重要的,比如一到晚上我们要到处找火把,一紧张找不到就被搞死了。切换武器装备的时候也是经常找不到东西,想要某个物品的时候盯着很久都找不到,所以针对物品排序是很重要的,可以帮助快速找到物品,那如何针对物品进行排序呢

新建脚本文件

在scripts 目录下新建一个arrange.lua代码文件在这里插入图片描述

获取物品

我们需要先获取物品栏的物品,也可以获取背包中的物品,如果物品可以堆叠的花我们可以把物品堆叠在一起,避免占用太多格子。下面的代码可以将容器中的物品保存到result中,并且将物品删掉

local prefabId = 1
-- 定义一个函数,用于从容器中收集物品
-- 参数 container 是要收集物品的容器
-- 参数 result 是用于存储收集到的物品的表
local function CollectItems(container, result) 
    -- 获取容器的插槽数量
    local num =  container:GetNumSlots()

    -- 遍历每个插槽
    for i = 1, num, 1 do
       -- 获取插槽中的物品
       local item = container:GetItemInSlot(i)
       -- 如果插槽中有物品
       if item ~= nil then
            -- 判断物品是否可以堆叠
            if item.components.stackable then
                -- 如果物品可以堆叠,判断这个物品是否已经存在于结果表中
                if not result[item.prefab] then
                    -- 如果这是第一次遇到这个物品,直接将它和它的数量放入结果表中
                    result[item.prefab] = {item = item, count = item.components.stackable:StackSize()}
                else
                    -- 如果这个物品已经存在于结果表中,增加它的数量
                    local inst = result[item.prefab]
                    inst.item.components.stackable:SetStackSize(inst.item.components.stackable:StackSize() + item.components.stackable:StackSize())
                    inst.count = inst.item.components.stackable:StackSize()
                end  
            else
                -- 如果物品不可以堆叠,生成一个新的 ID 并将物品放入结果表中
                prefabId = prefabId + 1
                result[tostring(prefabId)] = {item = item, count = 0}
            end

          -- 从容器中删除这个物品
          container:RemoveItemBySlot(i)
       end
    end
end

定义排列的函数

在这个脚本中定义一个Arrange函数,并将这个函数返回,我们简单的按照数量从大到小排序

-- 定义一个Arrange函数,用于整理物品
local function Arrange()
    -- 创建一个空的items表
    local items = {}
    -- 获取当前玩家
    local player = GetPlayer()
    
    -- 调用CollectItems函数,将玩家的物品收集到items表中
    CollectItems(player.components.inventory, items)
    
    -- 创建一个空的itemsArray表,用于存放items的值
    local itemsArray = {}
    -- 遍历items表,将每个值插入到itemsArray中
    for k, v in pairs(items) do
        table.insert(itemsArray, v)
    end
    -- 对itemsArray进行排序
    -- 如果两个物品的数量相同,则按照物品的prefab属性进行字母排序
    -- 如果两个物品的数量不同,则数量多的物品排在前面
    table.sort(itemsArray, function (left, right)
        if (left.count == right.count) then
            return left.item.prefab < right.item.prefab
        end
        return left.count > right.count 
    end)
    -- 定义一个slot变量,用于记录当前的物品槽位
    local slot = 1
    -- 获取玩家的物品栏
    local inventory = player.components.inventory
    -- 遍历itemsArray,将每个物品放入物品栏的对应槽位
    for i = 1, #itemsArray, 1 do       
        inventory:GiveItem(itemsArray[i].item, slot)
        slot = slot + 1
    end
end

return Arrange

测试功能

在modmian.lua中增加一个调用,当按下F2 键的时候整理物品


GLOBAL.TheInput:AddKeyHandler(function(key, down)
    if (key == GLOBAL.KEY_F2 and not down) then
        -- 调用Arrange函数,整理玩家的物品栏
        arrange()
    end
end)

整理之前
整理之后
整理之后

按照物品的类型来排序

我们还可以按照优先级来排序,食物优先级最高,装备优先级最低等,可以先把物品的优先级设置一下,然后调用table.sort进行排序即可。

1.1 定义个获取优先级函数

这个函数可以根据 预制物设置 优先级,可以根据自己条件设置

--定义一个获取优先级的函数,这里可以自定义物品的优先级
local function GetPriority(item)
    --如果是食物,则优先级位1
    if (item.components.edible) then
        return 1
    end
    --如果是装备,则优先级位1
    if (item.components.equippable) then
        return 100
    end
    return 10
end

1.2 设置物品优先级

修改下 CollectItems 函数,给表中的物品设置优先级

local function CollectItems(container, result) 
    -- 获取容器的插槽数量
    local num =  container:GetNumSlots()

    -- 遍历每个插槽
    for i = 1, num, 1 do
       -- 获取插槽中的物品
       local item = container:GetItemInSlot(i)
       -- 如果插槽中有物品
       if item ~= nil then
            -- 判断物品是否可以堆叠
            if item.components.stackable then
                -- 如果物品可以堆叠,判断这个物品是否已经存在于结果表中
                if not result[item.prefab] then
                    -- 如果这是第一次遇到这个物品,直接将它和它的数量放入结果表中
                    result[item.prefab] = {item = item, count = item.components.stackable:StackSize(), priority = GetPriority(item)}
                else
                    -- 如果这个物品已经存在于结果表中,增加它的数量
                    local inst = result[item.prefab]
                    inst.item.components.stackable:SetStackSize(inst.item.components.stackable:StackSize() + item.components.stackable:StackSize())
                    inst.count = inst.item.components.stackable:StackSize()
                end  
            else
                -- 如果物品不可以堆叠,生成一个新的 ID 并将物品放入结果表中
                prefabId = prefabId + 1
                result[tostring(prefabId)] = {item = item, count = 0, priority = GetPriority(item)}
            end

          -- 从容器中删除这个物品
          container:RemoveItemBySlot(i)
       end
    end
end

1.3 重新修改sort函数


-- 定义一个Arrange函数,用于整理物品
local function Arrange()
    -- 创建一个空的items表
    local items = {}
    -- 获取当前玩家
    local player = GetPlayer()
    
    -- 调用CollectItems函数,将玩家的物品收集到items表中
    CollectItems(player.components.inventory, items)
    
    -- 创建一个空的itemsArray表,用于存放items的值
    local itemsArray = {}
    -- 遍历items表,将每个值插入到itemsArray中
    for k, v in pairs(items) do
        table.insert(itemsArray, v)
    end
    -- 对itemsArray进行排序
    table.sort(itemsArray, function (left, right)
        if left.priority == right.priority then
            if left.count == right.count then
                return left.item.prefab < right.item.prefab
            else
                return left.count > right.count
            end
        else
            return left.priority > right.priority
        end
    end)
    -- 定义一个slot变量,用于记录当前的物品槽位
    local slot = 1
    -- 获取玩家的物品栏
    local inventory = player.components.inventory
    -- 遍历itemsArray,将每个物品放入物品栏的对应槽位
    for i = 1, #itemsArray, 1 do       
        inventory:GiveItem(itemsArray[i].item, slot)
        slot = slot + 1
    end
end

return Arrange

源码下载

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值