353 lines
8.5 KiB
Lua
353 lines
8.5 KiB
Lua
|
|
local HUD_POSITION = {x = missions.hud.posx, y = missions.hud.posy }
|
|
local HUD_ALIGNMENT = {x = 1, y = 0}
|
|
|
|
|
|
local hud = {} -- playerName -> {}
|
|
local remainingItems = {} -- playerName -> ItemStack: the target item and count, eg, "default:stone 50"
|
|
local remainingCount = {} -- playerName -> count: the player put items in chest
|
|
|
|
local function cleanItemInChest(inv, stackItem, inv_name)
|
|
stackItem:set_count(1)
|
|
local maxRun = 99
|
|
while inv:contains_item(inv_name, stackItem) and maxRun > 0 do
|
|
stackItem:set_count(100*100)
|
|
inv:remove_item(inv_name, stackItem)
|
|
maxRun = maxRun - 1
|
|
end
|
|
|
|
--[[
|
|
if inv_name == nil then inv_name = "main" end
|
|
for i = 1, inv:get_size(inv_name) do
|
|
local vStack = inv:get_stack(inv_name, i)
|
|
if vStack:get_name() == stack:get_name() then
|
|
vStack:set_count(0)
|
|
-- inv:set_stack(inv_name, i)
|
|
end
|
|
end
|
|
--]]
|
|
end
|
|
|
|
missions.register_step({
|
|
|
|
type = "chestput",
|
|
name = "Put in chest",
|
|
|
|
create = function()
|
|
return {stack="", pos=nil, name="", visible=1, resetChest=false, showCount=false}
|
|
end,
|
|
|
|
get_status = function(ctx)
|
|
local player = ctx.player
|
|
local stepdata = ctx.step.data
|
|
|
|
local count = remainingCount[player:get_player_name()]
|
|
if type(count) == "number" then
|
|
local stack = ItemStack(stepdata.stack)
|
|
if not stepdata.showCount then count = "n" end
|
|
return "Put " .. count .. " x " .. stack:get_name() .. " into the chest"
|
|
else
|
|
return ""
|
|
end
|
|
end,
|
|
|
|
validate = function(ctx)
|
|
local meta = minetest.get_meta(ctx.pos)
|
|
local stepdata = ctx.step.data
|
|
|
|
local inv = meta:get_inventory()
|
|
|
|
local removeStack = ItemStack(stepdata.stack)
|
|
|
|
if stepdata.pos == nil then
|
|
return {
|
|
success=false,
|
|
failed=true,
|
|
msg="No position defined"
|
|
}
|
|
end
|
|
|
|
if inv:room_for_item("main", removeStack) then
|
|
return {success=true}
|
|
else
|
|
return {
|
|
success=false,
|
|
failed=true,
|
|
msg="Chest has no space for items: " .. stepdata.stack ..
|
|
" chest-location: " .. stepdata.pos.x .. "/" .. stepdata.pos.y .. "/" .. stepdata.pos.z
|
|
}
|
|
end
|
|
|
|
end,
|
|
|
|
allow_inv_stack_put = function(listname, index, stack)
|
|
-- allow position wand on pos 1 of main inv
|
|
if listname == "main" then
|
|
if index == 2 and stack:get_name() == "missions:wand_chest" then
|
|
return true
|
|
end
|
|
|
|
if index == 1 then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end,
|
|
|
|
edit_formspec = function(ctx)
|
|
local stepdata = ctx.step.data
|
|
local pos = ctx.pos
|
|
local resetChest = "false"
|
|
local showCount = "false"
|
|
if stepdata.resetChest then resetChest = "true" end
|
|
if stepdata.showCount then showCount = "true" end
|
|
|
|
ctx.inv:set_stack("main", 1, ItemStack(stepdata.stack))
|
|
|
|
local name = ""
|
|
|
|
if stepdata.pos then
|
|
local distance = vector.distance(ctx.pos, stepdata.pos)
|
|
name = name .. "Position(" .. stepdata.pos.x .. "/" ..
|
|
stepdata.pos.y .. "/" .. stepdata.pos.z ..") " ..
|
|
"Distance: " .. math.floor(distance) .. " m"
|
|
end
|
|
|
|
if stepdata.name then
|
|
name = name .. " with name '" .. stepdata.name .. "'"
|
|
end
|
|
|
|
local visibleText
|
|
|
|
if stepdata.visible == 1 then
|
|
visibleText = "Waypoint: Visible"
|
|
else
|
|
visibleText = "Waypoint: Hidden"
|
|
end
|
|
|
|
local formspec = "size[8,8;]" ..
|
|
"label[0,0;Put items in chest]" ..
|
|
"checkbox[4,-0.2;showCount;Show Count;".. showCount .. "]" ..
|
|
|
|
"label[0,1;Items]" ..
|
|
"list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main;2,1;1,1;0]" ..
|
|
|
|
"label[3,1;Target]" ..
|
|
"list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main;4,1;1,1;1]" ..
|
|
|
|
"label[0,2;" .. name .. "]" ..
|
|
|
|
"button_exit[0,6.5;8,1;togglevisible;" .. visibleText .. "]" ..
|
|
|
|
"list[current_player;main;0,2.5;8,4;]listring[]" ..
|
|
"button[0,7.3;4,1;save;Save]" ..
|
|
"checkbox[4.5,7.3;resetChest;Reset Chest;".. resetChest .. "]"
|
|
|
|
return formspec;
|
|
end,
|
|
|
|
update = function(ctx)
|
|
|
|
local fields = ctx.fields
|
|
local inv = ctx.inv
|
|
local stepdata = ctx.step.data
|
|
|
|
if fields.resetChest == "true" then
|
|
stepdata.resetChest = true
|
|
elseif fields.resetChest == "false" then
|
|
stepdata.resetChest = false
|
|
end
|
|
|
|
if fields.showCount == "true" then
|
|
stepdata.showCount = true
|
|
elseif fields.showCount == "false" then
|
|
stepdata.showCount = false
|
|
end
|
|
|
|
if fields.togglevisible then
|
|
if stepdata.visible == 1 then
|
|
stepdata.visible = 0
|
|
else
|
|
stepdata.visible = 1
|
|
end
|
|
|
|
ctx.show_editor()
|
|
end
|
|
|
|
if fields.save then
|
|
local stack = inv:get_stack("main", 1)
|
|
|
|
if not stack:is_empty() then
|
|
stepdata.stack = stack:to_string()
|
|
end
|
|
|
|
stack = inv:get_stack("main", 2)
|
|
|
|
if not stack:is_empty() then
|
|
local meta = stack:get_meta()
|
|
local pos = minetest.string_to_pos(meta:get_string("pos"))
|
|
local name = meta:get_string("name")
|
|
|
|
stepdata.pos = pos
|
|
stepdata.name = name
|
|
end
|
|
|
|
ctx.show_mission()
|
|
end
|
|
end,
|
|
|
|
on_step_enter = function(ctx)
|
|
|
|
local stepdata = ctx.step.data
|
|
local player = ctx.player
|
|
local playerName = player:get_player_name()
|
|
|
|
-- set stack
|
|
remainingItems[playerName] = stepdata.stack
|
|
local stack =ItemStack(stepdata.stack)
|
|
remainingCount[playerName] = stack:get_count()
|
|
if stepdata.resetChest then
|
|
local meta = minetest.get_meta(stepdata.pos)
|
|
local inv = meta:get_inventory()
|
|
local removeStack = ItemStack(stepdata.stack)
|
|
cleanItemInChest(inv, removeStack, "main")
|
|
end
|
|
|
|
local hud_data = {}
|
|
hud[playerName] = hud_data;
|
|
|
|
hud_data.counter = player:hud_add({
|
|
hud_elem_type = "text",
|
|
position = HUD_POSITION,
|
|
offset = {x = 0, y = 140},
|
|
text = "",
|
|
alignment = HUD_ALIGNMENT,
|
|
scale = {x = 100, y = 100},
|
|
number = 0x00FF00
|
|
})
|
|
|
|
hud_data.image = player:hud_add({
|
|
hud_elem_type = "image",
|
|
position = HUD_POSITION,
|
|
offset = {x = 32, y = 140},
|
|
text = missions.get_image(stack:get_name()),
|
|
alignment = HUD_ALIGNMENT,
|
|
scale = {x = 0.5, y = 0.5},
|
|
})
|
|
|
|
-- set waypoint, if enabled
|
|
if stepdata.visible == 1 then
|
|
hud_data.target = player:hud_add({
|
|
hud_elem_type = "waypoint",
|
|
name = "Chest: " .. stepdata.name,
|
|
text = "m",
|
|
number = 0xFF0000,
|
|
world_pos = stepdata.pos
|
|
})
|
|
end
|
|
end,
|
|
|
|
on_step_interval = function(ctx)
|
|
local player = ctx.player
|
|
local playerName = player:get_player_name()
|
|
local stepdata = ctx.step.data
|
|
|
|
local count = remainingCount[playerName]
|
|
if type(count) == "number" then
|
|
if count == 0 then
|
|
ctx.on_success()
|
|
end
|
|
|
|
local hud_data = hud[player:get_player_name()]
|
|
if not stepdata.showCount then count = "n " end
|
|
player:hud_change(hud_data.counter, "text", count .. "x")
|
|
else
|
|
ctx.on_success()
|
|
end
|
|
end,
|
|
|
|
on_step_exit = function(ctx)
|
|
local player = ctx.player
|
|
local playerName = player:get_player_name()
|
|
|
|
remainingItems[playerName] = ""
|
|
remainingCount[playerName] = nil
|
|
local hud_data = hud[playerName]
|
|
|
|
if hud_data and hud_data.image then
|
|
player:hud_remove(hud_data.image)
|
|
end
|
|
|
|
if hud_data and hud_data.counter then
|
|
player:hud_remove(hud_data.counter)
|
|
end
|
|
|
|
if hud_data and hud_data.target then
|
|
player:hud_remove(hud_data.target)
|
|
end
|
|
|
|
hud[playerName] = nil
|
|
end
|
|
|
|
|
|
})
|
|
|
|
local intercept_chest = function(name)
|
|
local def = minetest.registered_nodes[name]
|
|
|
|
if def ~= nil then
|
|
local delegate_put = def.on_metadata_inventory_put
|
|
local delegate_take = def.on_metadata_inventory_take
|
|
|
|
def.on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
if player and player:is_player() then
|
|
local playerName = player:get_player_name()
|
|
local remStack = ItemStack(remainingItems[playerName])
|
|
|
|
if remStack:get_name() == stack:get_name() then
|
|
local count = remainingCount[playerName] or remStack:get_count()
|
|
count = count - stack:get_count()
|
|
remainingCount[playerName] = count
|
|
end
|
|
|
|
--print("Put Stack: " .. stack:get_name())
|
|
end
|
|
|
|
--delegate
|
|
delegate_put(pos, listname, index, stack, player)
|
|
end
|
|
|
|
def.on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
if player and player:is_player() then
|
|
local playerName = player:get_player_name()
|
|
local remStack = ItemStack(remainingItems[playerName])
|
|
|
|
if remStack:get_name() == stack:get_name() then
|
|
local count = remainingCount[playerName] or remStack:get_count()
|
|
count = count + stack:get_count()
|
|
remainingCount[playerName] = count
|
|
end
|
|
--print("Take Stack: " .. stack:get_name())
|
|
end
|
|
|
|
--delegate
|
|
delegate_take(pos, listname, index, stack, player)
|
|
end
|
|
else
|
|
print("Definition not found: " .. name)
|
|
end
|
|
end
|
|
|
|
local has_more_chests_mod = minetest.get_modpath("more_chests")
|
|
|
|
intercept_chest("default:chest")
|
|
intercept_chest("default:chest_open")
|
|
|
|
if has_more_chests_mod then
|
|
intercept_chest("more_chests:dropbox")
|
|
end
|
|
-- TODO: technic-chests
|
|
|
|
|