score/mods/score/init.lua

471 lines
12 KiB
Lua

--
-- Content
--
local LEVEL_EXTENT = 300
local LEVEL_MAX = 100
for level = 1, LEVEL_MAX do
local image
if level % 2 == 1 then
image = 1
else
image = 2
end
minetest.register_node("score:stone_" .. level, {
description = "Stone Level " .. level,
tiles = { "score_stone_" .. image .. ".png" },
groups = { stone = level },
light_source = 1,
sounds = {
footstep = { name = "score_footstep", gain = 1.0 },
place = { name=" score_place ", gain = 1.0 },
dig = { name="score_dig", gain = 0.5 },
},
})
minetest.register_node("score:iron_" .. level, {
description = "Iron Level " .. level,
tiles = { "score_stone_" .. image .. ".png^score_iron.png" },
groups = { stone = level + 1 },
light_source = 1,
sounds = {
footstep = { name = "score_footstep", gain = 1.0 },
place = { name=" score_place ", gain = 1.0 },
dig = { name="score_dig", gain = 0.5 },
},
})
minetest.register_ore({
ore_type = "scatter",
ore = "score:iron_" .. level,
wherein = "score:stone_" .. level,
clust_scarcity = 8 * 8 * 8,
clust_num_ores = 5,
clust_size = 3,
})
minetest.register_node("score:coal_" .. level, {
description = "Coal Level " .. level,
tiles = { "score_stone_" .. image .. ".png^score_coal.png" },
groups = { stone = level + 1 },
light_source = 1,
sounds = {
footstep = { name = "score_footstep", gain = 1.0 },
place = { name=" score_place ", gain = 1.0 },
dig = { name="score_dig", gain = 0.5 },
},
})
minetest.register_ore({
ore_type = "scatter",
ore = "score:coal_" .. level,
wherein = "score:stone_" .. level,
clust_scarcity = 8 * 8 * 8,
clust_num_ores = 8,
clust_size = 4,
})
minetest.register_node("score:score_ore_" .. level, {
tiles = { "score_stone_" .. image .. ".png^score_score.png" },
groups = { stone = level + 1 },
drop = "score:score " .. level,
light_source = 1,
sounds = {
footstep = { name = "score_footstep", gain = 1.0 },
place = { name=" score_place ", gain = 1.0 },
dig = { name="score_dig", gain = 0.5 },
},
})
minetest.register_ore({
ore_type = "scatter",
ore = "score:score_ore_" .. level,
wherein = "score:stone_" .. level,
clust_scarcity = 12 * 12 * 12,
clust_num_ores = 1,
clust_size = 1,
})
local pick_capabilities = {
groupcaps = {
stone = { times = {}, uses = 0 },
},
}
for i = 1, level do
pick_capabilities.groupcaps.stone.times[i] = math.max(0.6 ^ (level - i), 0.2)
end
pick_capabilities.groupcaps.stone.times[level + 1] = 1.0
minetest.register_tool("score:pick_" .. level, {
description = "Pick Level " .. level,
inventory_image = "score_pick_" .. image .. ".png",
tool_capabilities = pick_capabilities,
on_drop = function(itemstack, dropper, pos)
return itemstack
end,
})
end
minetest.register_node("score:light", {
description = "Light",
tiles = { "score_light.png" },
groups = { dig_immediate = 3 },
light_source = 15,
sounds = {
footstep = { name = "score_footstep", gain = 1.0 },
place = { name=" score_dig ", gain = 0.5 },
dug = { name="score_dig", gain = 0.5 },
},
on_drop = function(itemstack, dropper, pos)
return itemstack
end,
})
minetest.register_craftitem("score:score", {
description = "Score",
})
minetest.register_tool(":", {
type = "none",
wield_image = "hand.png",
wield_scale = {x=1,y=1,z=1.5},
range = 4,
})
--
-- Player
--
local INV_PICK_INDEX = 1
local INV_LIGHT_INDEX = 2
local INV_SIZE = 2
local inventories = {
--[[
playername = {
itemname = count,
},
]]
}
local function save_inventories()
local file = io.open(minetest.get_worldpath() .. "/score_inventory", "w")
if not file then
minetest.log("error", "Can't save inventories")
return
end
file:write(minetest.serialize(inventories))
file:close()
end
local function load_inventories()
local file = io.open(minetest.get_worldpath() .. "/score_inventory", "r")
if not file then
minetest.log("error", "Can't load inventories")
return
end
inventories = minetest.deserialize(file:read("*all"))
file:close()
end
local function get_level(player)
local hud_inv = player:get_inventory()
local pick = hud_inv:get_stack("main", INV_PICK_INDEX)
local current_level = math.min(tonumber(pick:get_name():match("^score:pick_([%d]+)$")) or 1, LEVEL_MAX)
return current_level
end
local function get_pick_cost(level)
local cost = {}
cost["score:iron_" .. level] = math.ceil(45 * 1.1 ^ (level - 1))
return cost
end
local function get_light_cost(level)
local cost = {}
for i = level - 1, level do
if i > 0 then
cost["score:coal_" .. i] = math.ceil((50 + 5 * level) * 1.5 ^ (level - i))
end
end
return cost
end
local function update_formspec(player, not_enough_resources)
local inv = inventories[player:get_player_name()]
local hud_inv = player:get_inventory()
local formspec = "size[5,7]"
formspec = formspec .. "tableoptions[background=#00000000;border=false;highlight=#00000000]"
formspec = formspec .. "tablecolumns[text;text]"
formspec = formspec .. "table[0,0;5,5;;"
local pick = hud_inv:get_stack("main", INV_PICK_INDEX)
local light = hud_inv:get_stack("main", INV_LIGHT_INDEX)
formspec = formspec .. pick:get_definition().description .. ",1,"
formspec = formspec .. light:get_definition().description .. "," .. light:get_count() .. ","
local lines = {}
for itemname,count in pairs(inv) do
table.insert(lines, {
minetest.formspec_escape(minetest.registered_items[itemname].description),
count,
})
end
table.sort(lines, function(a, b)
if b[1] == "Score" then
return false
end
if a[1] == "Score" then
return true
end
local a_level = tonumber(a[1]:match(".* Level ([%d]+)$"))
local b_level = tonumber(b[1]:match(".* Level ([%d]+)$"))
if not a_level or not b_level or a_level == b_level then
return a[1] < b[1]
end
return a_level > b_level
end)
for _,line in ipairs(lines) do
formspec = formspec .. line[1] .. "," .. line[2] .. ","
end
-- remove trailing comma
if formspec:match(",$") then
formspec = formspec:sub(1, -2)
end
formspec = formspec .. ";0]"
formspec = formspec .. "button[0,5;2,1;btn_upgrade;Upgrade Pick]"
formspec = formspec .. "tableoptions[background=#00000000;border=false;highlight=#00000000]"
formspec = formspec .. "tablecolumns[color;text;text]"
if not_enough_resources == "pick" then
formspec = formspec .. "table[2,5;3,1;;#FF0000,Requires:,,"
else
formspec = formspec .. "table[2,5;3,1;;,Requires:,,"
end
local pick_cost = get_pick_cost(get_level(player))
for item, required in pairs(pick_cost) do
local name = minetest.registered_items[item].description
formspec = formspec .. "," .. name .. "," .. required .. ","
end
-- remove trailing comma
if formspec:match(",$") then
formspec = formspec:sub(1, -2)
end
formspec = formspec .. ";0]"
formspec = formspec .. "button[0,6;2,1;btn_light;Craft Light]"
formspec = formspec .. "tableoptions[background=#00000000;border=false;highlight=#00000000]"
formspec = formspec .. "tablecolumns[color;text;text]"
if not_enough_resources == "light" then
formspec = formspec .. "table[2,6;3,1;;#FF0000,Requires:,,"
else
formspec = formspec .. "table[2,6;3,1;;,Requires:,,"
end
local light_cost = get_light_cost(get_level(player))
for item, required in pairs(light_cost) do
local name = minetest.registered_items[item].description
formspec = formspec .. "," .. name .. "," .. required .. ","
end
-- remove trailing comma
if formspec:match(",$") then
formspec = formspec:sub(1, -2)
end
formspec = formspec .. ";0]"
if formspec ~= player:get_inventory_formspec() then
player:set_inventory_formspec(formspec)
end
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields["btn_upgrade"] then
local inv = inventories[player:get_player_name()]
local hud_inv = player:get_inventory()
local current_level = get_level(player)
local pick_cost = get_pick_cost(current_level)
for item, required in pairs(pick_cost) do
if not inv[item] or inv[item] < required then
update_formspec(player, "pick")
return true
end
end
for item, required in pairs(pick_cost) do
inv[item] = inv[item] - required
end
hud_inv:set_stack("main", INV_PICK_INDEX, ItemStack("score:pick_" .. (current_level + 1)))
update_formspec(player)
return true
end
if fields["btn_light"] then
local inv = inventories[player:get_player_name()]
local hud_inv = player:get_inventory()
local current_level = get_level(player)
local light_cost = get_light_cost(current_level)
for item, required in pairs(light_cost) do
if not inv[item] or inv[item] < required then
update_formspec(player, "light")
return true
end
end
for item, required in pairs(light_cost) do
inv[item] = inv[item] - required
end
local light = hud_inv:get_stack("main", INV_LIGHT_INDEX)
light:add_item(ItemStack("score:light"))
hud_inv:set_stack("main", INV_LIGHT_INDEX, light)
update_formspec(player)
return true
end
if fields["quit"] then
update_formspec(player)
end
end)
minetest.register_on_joinplayer(function(player)
player:set_properties({ textures = {} })
player:set_sky("0x000000", "plain", {})
player:hud_set_hotbar_itemcount(INV_SIZE)
local hud_inv = player:get_inventory()
hud_inv:set_size("main", INV_SIZE)
if not hud_inv:get_stack("main", INV_PICK_INDEX):get_name():match("^score:pick_") or
hud_inv:get_stack("main", INV_LIGHT_INDEX):get_name() ~= "score:light" then
hud_inv:set_stack("main", INV_PICK_INDEX, ItemStack("score:pick_1"))
hud_inv:set_stack("main", INV_LIGHT_INDEX, ItemStack("score:light 10"))
end
local inv = inventories[player:get_player_name()]
if not inv then
inventories[player:get_player_name()] = {
["score:score"] = 0
}
end
update_formspec(player)
end)
minetest.handle_node_drops = function(pos, drops, player)
for _, dropped_item in ipairs(drops) do
dropped_item = ItemStack(dropped_item)
local item_name = dropped_item:get_name()
if item_name == "score:light" then
local hud_inv = player:get_inventory()
local light = hud_inv:get_stack("main", INV_LIGHT_INDEX)
light:add_item(dropped_item)
hud_inv:set_stack("main", INV_LIGHT_INDEX, light)
else
local inv = inventories[player:get_player_name()]
if not inv[item_name] then
inv[item_name] = dropped_item:get_count()
else
inv[item_name] = inv[item_name] + dropped_item:get_count()
end
end
end
update_formspec(player)
end
local save_interval = tonumber(minetest.setting_get("server_map_save_interval")) or 5.3
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer > save_interval then
timer = 0
save_inventories()
end
end)
load_inventories()
minetest.setting_set("static_spawnpoint", "1,-80,0")
minetest.setting_set("enable_damage", "false")
--
-- Mapgen
--
local mg_params = minetest.get_mapgen_params()
local mg_noise_params = {
offset = 0.0,
scale = 1.0,
spread = { x = 25, y = 25, z = 25 },
seed = mg_params.seed,
octaves = 4,
persistence = 0.5,
}
minetest.set_mapgen_params({
mgname = "singlenode",
flags = "nolight",
})
local c_air
local c_stones = {}
minetest.register_on_generated(function(minp, maxp, seed)
local c_air = c_air or minetest.get_content_id("air")
local vox_manip, vox_minp, vox_maxp = minetest.get_mapgen_object("voxelmanip")
local vox_data = vox_manip:get_data()
local vox_area = VoxelArea:new({ MinEdge = vox_minp, MaxEdge = vox_maxp })
local noise_map = PerlinNoiseMap(mg_noise_params,
{ x = maxp.x - minp.x + 1, y = maxp.y - minp.y + 1, z = maxp.z - minp.z + 1 })
local noise_table = noise_map:get3dMap_flat(minp)
local noise_index = 0
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
for x = minp.x, maxp.x do
local vox_index = vox_area:index(x, y, z)
noise_index = noise_index + 1
local radius = math.sqrt(x * x + z * z)
local level = math.min(math.ceil(radius / LEVEL_EXTENT), LEVEL_MAX)
local noise = noise_table[noise_index] + math.abs((y + 50) / 32.0) - 0.8
if noise > 0.0 then
if not c_stones[level] then
c_stones[level] = minetest.get_content_id("score:stone_" .. level)
end
vox_data[vox_index] = c_stones[level]
else
vox_data[vox_index] = c_air
end
end
end
end
vox_manip:set_data(vox_data)
minetest.generate_ores(vox_manip, minp, maxp)
vox_manip:calc_lighting()
vox_manip:write_to_map()
end)
-- Some aliases to supress error messages
minetest.register_alias("mapgen_stone", "air")
minetest.register_alias("mapgen_", "air")
minetest.register_alias("mapgen_water_source", "air")
minetest.register_alias("mapgen_river_water_source", "air")