饥荒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