lucky_block/init.lua

673 lines
14 KiB
Lua
Raw Normal View History

2015-09-21 12:55:29 +02:00
lucky_block = {}
lucky_schems = {}
lucky_block.seed = PseudoRandom(os.time())
2016-09-30 14:25:00 +02:00
-- example custom function (punches player with 5 damage)
local function punchy(pos, player)
player:punch(player, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 5}
}, nil)
2016-12-08 20:42:54 +01:00
minetest.chat_send_player(player:get_player_name(), "Stop hitting yourself!")
end
local function drop(pos, itemstack)
local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count()))
if obj then
obj:setvelocity({
x = math.random(-10, 10) / 9,
y = 5,
z = math.random(-10, 10) / 9,
})
end
end
-- custom function to drop player inventory and replace with dry shrubs
local function bushy(pos, player)
local player_inv = player:get_inventory()
for i = 1, player_inv:get_size("main") do
drop(pos, player_inv:get_stack("main", i))
player_inv:set_stack("main", i, "default:dry_shrub")
end
minetest.chat_send_player(player:get_player_name(), "Dry Shrub Takeover!")
2016-09-30 14:25:00 +02:00
end
2015-11-23 17:12:39 +01:00
-- default blocks
2015-09-21 12:55:29 +02:00
local lucky_list = {
2016-12-08 20:42:54 +01:00
{"cus", bushy},
2016-09-30 14:25:00 +02:00
{"cus", punchy},
2015-09-21 12:55:29 +02:00
{"fal", {"default:wood", "default:gravel", "default:sand", "default:desert_sand", "default:stone", "default:dirt", "default:goldblock"}, 0},
{"lig"},
{"nod", "lucky_block:super_lucky_block", 0},
2015-11-05 12:43:56 +01:00
{"exp"},
2015-09-21 12:55:29 +02:00
}
-- ability to add new blocks to list
function lucky_block:add_blocks(list)
2016-06-06 16:11:55 +02:00
2015-09-21 12:55:29 +02:00
for s = 1, #list do
table.insert(lucky_list, list[s])
end
end
2015-09-30 12:19:47 +02:00
-- call to purge the block list
function lucky_block:purge_block_list()
2015-11-23 17:12:39 +01:00
lucky_list = {
{"nod", "lucky_block:super_lucky_block", 0}
}
2015-09-30 12:19:47 +02:00
end
-- add schematics to global list
function lucky_block:add_schematics(list)
2016-06-06 16:11:55 +02:00
for s = 1, #list do
table.insert(lucky_schems, list[s])
end
end
2016-02-01 19:55:23 +01:00
-- import schematics and default blocks
2016-06-06 16:11:55 +02:00
dofile(minetest.get_modpath("lucky_block") .. "/schems.lua")
dofile(minetest.get_modpath("lucky_block") .. "/blocks.lua")
2015-09-21 12:55:29 +02:00
-- for random colour selection
local all_colours = {
"grey", "black", "red", "yellow", "green", "cyan", "blue", "magenta",
"orange", "violet", "brown", "pink", "dark_grey", "dark_green", "white"
}
-- default items in chests
local chest_stuff = {
{name = "default:apple", max = 3},
{name = "default:steel_ingot", max = 2},
{name = "default:gold_ingot", max = 2},
{name = "default:diamond", max = 1},
{name = "default:pick_steel", max = 1}
}
2015-09-30 12:19:47 +02:00
-- call to purge the chest items list
function lucky_block:purge_chest_items()
chest_stuff = {}
end
-- ability to add chest items
function lucky_block:add_chest_items(list)
2016-06-06 16:11:55 +02:00
2015-09-30 12:19:47 +02:00
for s = 1, #list do
table.insert(chest_stuff, list[s])
end
end
2015-09-21 12:55:29 +02:00
-- particle effects
function effect(pos, amount, texture, max_size)
2016-06-06 16:11:55 +02:00
2015-09-21 12:55:29 +02:00
minetest.add_particlespawner({
amount = amount,
time = 0.5,
minpos = {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
maxpos = {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
minvel = {x = -5, y = -5, z = -5},
maxvel = {x = 5, y = 5, z = 5},
minacc = {x = -4, y = -4, z = -4},
maxacc = {x = 4, y = 4, z = 4},
minexptime = 1,
maxexptime = 3,
minsize = 0.5,
maxsize = (max_size or 1),
texture = texture,
})
end
-- modified from TNT mod to deal entity damage only
2015-09-21 12:55:29 +02:00
function entity_physics(pos, radius)
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
radius = radius * 2
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local objs = minetest.get_objects_inside_radius(pos, radius)
2015-11-05 12:43:56 +01:00
local obj_pos, dist
2016-06-06 16:11:55 +02:00
for n = 1, #objs do
2015-11-05 12:43:56 +01:00
2016-06-06 16:11:55 +02:00
obj_pos = objs[n]:getpos()
2016-06-06 16:11:55 +02:00
dist = vector.distance(pos, obj_pos)
if dist < 1 then dist = 1 end
2015-11-05 12:43:56 +01:00
local damage = math.floor((4 / dist) * radius)
2016-06-06 16:11:55 +02:00
local ent = objs[n]:get_luaentity()
2016-06-06 16:11:55 +02:00
if objs[n]:is_player() then
objs[n]:set_hp(objs[n]:get_hp() - damage)
else --if ent.health then
2016-06-06 16:11:55 +02:00
objs[n]:punch(objs[n], 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = damage},
}, nil)
end
2015-09-21 12:55:29 +02:00
end
end
2015-11-05 12:43:56 +01:00
-- get node but use fallback for nil or unknown
function node_ok(pos, fallback)
fallback = fallback or "default:dirt"
local node = minetest.get_node_or_nil(pos)
if not node then
return minetest.registered_nodes[fallback]
end
local nodef = minetest.registered_nodes[node.name]
if nodef then
return node
end
return minetest.registered_nodes[fallback]
end
-- set content id's
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local c_obsidian = minetest.get_content_id("default:obsidian")
local c_brick = minetest.get_content_id("default:obsidianbrick")
local c_chest = minetest.get_content_id("default:chest_locked")
2015-09-21 12:55:29 +02:00
-- explosion
function explosion(pos, radius)
2015-11-05 12:43:56 +01:00
-- play explosion sound
2015-09-21 12:55:29 +02:00
minetest.sound_play("tnt_explode", {
pos = pos,
gain = 1.0,
max_hear_distance = 16
})
-- if area protected then no blast damage
if minetest.is_protected(pos, "") then
return
end
2015-11-05 12:43:56 +01:00
local vm = VoxelManip()
local minp, maxp = vm:read_from_map(vector.subtract(pos, radius), vector.add(pos, radius))
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm:get_data()
local p = {}
local pr = PseudoRandom(os.time())
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
for z = -radius, radius do
for y = -radius, radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
for x = -radius, radius do
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
p.x = pos.x + x
p.y = pos.y + y
p.z = pos.z + z
2015-11-05 12:43:56 +01:00
if (x * x) + (y * y) + (z * z) <= (radius * radius) + pr:next(-radius, radius)
and data[vi] ~= c_air
2015-09-21 12:55:29 +02:00
and data[vi] ~= c_ignore
and data[vi] ~= c_obsidian
and data[vi] ~= c_brick
and data[vi] ~= c_chest then
2015-11-05 12:43:56 +01:00
local n = node_ok(p).name
local on_blast = minetest.registered_nodes[n].on_blast
if on_blast then
return on_blast(p)
else
2015-09-21 12:55:29 +02:00
minetest.set_node(p, {name = "air"})
2015-09-21 12:55:29 +02:00
effect(p, 2, "tnt_smoke.png", 5)
end
end
2015-09-21 12:55:29 +02:00
vi = vi + 1
end
end
end
end
function fill_chest(pos, items)
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local stacks = items or {}
2016-06-06 16:11:55 +02:00
local inv = minetest.get_meta(pos):get_inventory()
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
inv:set_size("main", 8 * 4)
for i = 0, 2, 1 do
local stuff = chest_stuff[math.random(1, #chest_stuff)]
table.insert(stacks, {name = stuff.name, count = math.random(1, stuff.max)})
end
for s = 1, #stacks do
if not inv:contains_item("main", stacks[s]) then
inv:set_stack("main", math.random(1, 32), stacks[s])
end
end
end
-- this is what happens when you dig a lucky block
local lucky_block = function(pos, digger)
2015-11-05 12:43:56 +01:00
local luck = math.random(1, #lucky_list) ; -- luck = 1
2015-09-21 12:55:29 +02:00
local action = lucky_list[luck][1]
local schem
print ("luck ["..luck.." of "..#lucky_list.."]", action)
-- place schematic
if action == "sch" then
2015-11-05 12:43:56 +01:00
if #lucky_schems == 0 then
print ("[lucky block] No schematics")
return
end
2015-09-21 12:55:29 +02:00
local schem = lucky_list[luck][2]
local switch = lucky_list[luck][3] or 0
local force = lucky_list[luck][4]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if switch == 1 then
pos = vector.round( digger:getpos() )
2015-09-21 12:55:29 +02:00
end
2015-11-05 12:43:56 +01:00
for i = 1, #lucky_schems do
if schem == lucky_schems[i][1] then
local p1 = vector.subtract(pos, lucky_schems[i][3])
minetest.place_schematic(p1, lucky_schems[i][2], "", {}, force)
break
end
end
2015-09-21 12:55:29 +02:00
if switch == 1 then
digger:setpos(pos, false)
end
2015-09-21 12:55:29 +02:00
-- place node (if chest then fill chest)
elseif action == "nod" then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local nod = lucky_list[luck][2]
local switch = lucky_list[luck][3]
local items = lucky_list[luck][4]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if switch == 1 then
pos = digger:getpos()
end
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if not minetest.registered_nodes[nod] then
print (nod)
nod = "default:goldblock"
end
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
effect(pos, 25, "tnt_smoke.png", 8)
2016-06-06 16:11:55 +02:00
2015-09-21 12:55:29 +02:00
minetest.set_node(pos, {name = nod})
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if nod == "default:chest" then
fill_chest(pos, items)
end
-- place entity
elseif action == "spw" then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local pos2 = {}
2015-11-05 12:43:56 +01:00
local num = lucky_list[luck][3] or 1
2015-09-21 12:55:29 +02:00
local tame = lucky_list[luck][4]
local own = lucky_list[luck][5]
local range = lucky_list[luck][6] or 5
local name = lucky_list[luck][7]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
for i = 1, num do
2015-11-05 12:43:56 +01:00
pos2.x = pos.x + lucky_block.seed:next(-range, range)
2015-09-21 12:55:29 +02:00
pos2.y = pos.y + 1
pos2.z = pos.z + lucky_block.seed:next(-range, range)
2015-11-05 12:43:56 +01:00
if minetest.registered_nodes[node_ok(pos2).name].walkable == false then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local entity = lucky_list[luck][2]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
-- coloured sheep
if entity == "mobs:sheep" then
local colour = "_" .. all_colours[math.random(#all_colours)]
entity = "mobs:sheep" .. colour
end
local mob = minetest.add_entity(pos2, entity)
2015-11-05 12:43:56 +01:00
if mob and mob:get_luaentity() then
local ent = mob:get_luaentity()
if tame then
ent.tamed = true
end
2015-11-05 12:43:56 +01:00
if own then
ent.owner = digger:get_player_name()
end
if name then
ent.nametag = name
ent.object:set_properties({
nametag = name,
nametag_color = "#FFFF00"
})
end
else
mob:remove()
print ("[lucky_block] " .. entity .. " could not be spawned")
2015-09-21 12:55:29 +02:00
end
end
end
-- explosion
elseif action == "exp" then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
explosion(pos, 2)
entity_physics(pos, 2)
-- teleport
elseif action == "tel" then
2015-11-05 12:43:56 +01:00
local xz_range = lucky_list[luck][2] or 10
local y_range = lucky_list[luck][3] or 5
pos.x = pos.x + lucky_block.seed:next(-xz_range, xz_range)
pos.x = pos.y + lucky_block.seed:next(-y_range, y_range)
pos.x = pos.z + lucky_block.seed:next(-xz_range, xz_range)
effect(pos, 25, "tnt_smoke.png", 8)
2015-11-05 12:43:56 +01:00
digger:setpos(pos, false)
2015-09-21 12:55:29 +02:00
-- drop items
elseif action == "dro" then
2015-11-05 12:43:56 +01:00
local num = lucky_list[luck][3] or 1
2015-09-21 12:55:29 +02:00
local colours = lucky_list[luck][4]
local items = #lucky_list[luck][2]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
for i = 1, num do
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local item = lucky_list[luck][2][math.random(1, items)]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if colours then
item = item .. all_colours[math.random(#all_colours)]
end
2015-11-05 12:43:56 +01:00
2016-10-30 22:41:22 +01:00
if not minetest.registered_nodes[item]
and not minetest.registered_craftitems[item]
and not minetest.registered_tools[item] then
item = "default:coal_lump"
end
local obj = minetest.add_item(pos, item)
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if obj then
obj:setvelocity({
2016-06-06 16:11:55 +02:00
x = math.random(-10, 10) / 9,
y = 5,
2016-06-06 16:11:55 +02:00
z = math.random(-10, 10) / 9,
2015-09-21 12:55:29 +02:00
})
end
end
-- lightning strike
elseif action == "lig" then
2015-11-05 12:43:56 +01:00
local nod = lucky_list[luck][2]
if nod and not minetest.registered_nodes[nod] then
print (nod)
nod = "fire:basic_flame"
end
2015-09-21 12:55:29 +02:00
pos = digger:getpos()
2015-11-05 12:43:56 +01:00
if nod then
minetest.set_node(pos, {name = nod})
end
2015-11-05 12:43:56 +01:00
minetest.add_particle({
pos = pos,
velocity = {x = 0, y = 0, z = 0},
acceleration = {x = 0, y = 0, z = 0},
expirationtime = 1.0,
collisiondetection = false,
2015-09-21 12:55:29 +02:00
texture = "lucky_lightning.png",
size = math.random(100, 150),
glow = 15,
2015-09-21 12:55:29 +02:00
})
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
entity_physics(pos, 2)
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
minetest.sound_play("lightning", {
pos = pos,
gain = 1.0,
max_hear_distance = 25
})
-- falling nodes
elseif action == "fal" then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local nods = lucky_list[luck][2]
local switch = lucky_list[luck][3]
local spread = lucky_list[luck][4]
local range = lucky_list[luck][5] or 5
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if switch == 1 then
pos = digger:getpos()
end
2015-11-05 12:43:56 +01:00
if spread then
pos.y = pos.y + 10
else
pos.y = pos.y + #nods
end
2015-11-05 12:43:56 +01:00
minetest.remove_node(pos)
local pos2 = {x = pos.x, y = pos.y, z = pos.z}
2015-09-21 12:55:29 +02:00
for s = 1, #nods do
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
minetest.after(0.5 * s, function()
2015-11-05 12:43:56 +01:00
if spread then
pos2.x = pos.x + lucky_block.seed:next(-range, range)
pos2.z = pos.z + lucky_block.seed:next(-range, range)
end
2015-09-21 12:55:29 +02:00
local n = minetest.registered_nodes[nods[s]]
local obj = minetest.add_entity(pos2, "__builtin:falling_node")
2015-11-05 12:43:56 +01:00
2016-10-02 12:33:14 +02:00
if obj and n then
2016-06-06 16:11:55 +02:00
obj:get_luaentity():set_node(n)
else
obj:remove()
end
2015-09-21 12:55:29 +02:00
end)
end
-- troll block, disappears or explodes after 2 seconds
elseif action == "tro" then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
local nod = lucky_list[luck][2]
local snd = lucky_list[luck][3]
local exp = lucky_list[luck][4]
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
minetest.set_node(pos, {name = nod})
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if snd then
minetest.sound_play(snd, {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
end
2015-11-05 12:43:56 +01:00
2016-10-30 22:41:22 +01:00
if not minetest.registered_nodes[nod] then
print (nod)
nod = "default:goldblock"
end
2015-09-21 12:55:29 +02:00
minetest.after(2.0, function()
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
if exp then
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
explosion(pos, 2)
entity_physics(pos, 2)
else
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
minetest.set_node(pos, {name = "air"})
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
minetest.sound_play("default_hard_footstep", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
end
end)
2016-09-30 14:25:00 +02:00
-- custom function
elseif action == "cus" then
local func = lucky_list[luck][2]
func(pos, digger)
2015-09-21 12:55:29 +02:00
end
end
-- lucky block itself
minetest.register_node('lucky_block:lucky_block', {
description = "Lucky Block",
2015-11-25 13:09:19 +01:00
tiles = {{
2016-06-06 16:11:55 +02:00
name = "lucky_block_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1
},
2015-11-25 13:09:19 +01:00
}},
2015-09-21 12:55:29 +02:00
inventory_image = minetest.inventorycube("lucky_block.png"),
sunlight_propagates = false,
is_ground_content = false,
2016-06-06 16:11:55 +02:00
paramtype = "light",
2015-09-21 12:55:29 +02:00
light_source = 3,
groups = {oddly_breakable_by_hand = 3},
sounds = default.node_sound_wood_defaults(),
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
on_dig = function(pos, node, digger)
minetest.set_node(pos, {name = "air"})
lucky_block(pos, digger)
end,
})
minetest.register_craft({
output = "lucky_block:lucky_block",
recipe = {
{"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"},
{"default:gold_ingot", "default:chest", "default:gold_ingot"},
{"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"}
}
})
-- super lucky block
minetest.register_node('lucky_block:super_lucky_block', {
description = "Super Lucky Block (use Pick)",
2015-11-25 13:09:19 +01:00
tiles = {{
name="lucky_block_super_animated.png",
2016-06-06 16:11:55 +02:00
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1
},
2015-11-25 13:09:19 +01:00
}},
2015-09-21 12:55:29 +02:00
inventory_image = minetest.inventorycube("lucky_block_super.png"),
sunlight_propagates = false,
is_ground_content = false,
2016-06-06 16:11:55 +02:00
paramtype = "light",
2015-09-21 12:55:29 +02:00
groups = {cracky = 1, level = 2},
sounds = default.node_sound_stone_defaults(),
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Super Lucky Block")
end,
2015-11-05 12:43:56 +01:00
2015-09-21 12:55:29 +02:00
on_dig = function(pos)
2015-11-05 12:43:56 +01:00
2016-06-06 16:11:55 +02:00
if math.random(1, 10) < 8 then
2015-11-05 12:43:56 +01:00
2016-06-06 16:11:55 +02:00
minetest.set_node(pos, {name = "air"})
2015-11-05 12:43:56 +01:00
2016-06-06 16:11:55 +02:00
effect(pos, 25, "tnt_smoke.png", 8)
minetest.sound_play("fart1", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
else
minetest.set_node(pos, {name = "lucky_block:lucky_block"})
end
2015-09-21 12:55:29 +02:00
end,
})
-- used to drop items inside a chest or container
local drop_items = function(pos, invstring)
2016-06-06 16:11:55 +02:00
local meta = minetest.get_meta(pos) ; if not meta then return end
local inv = meta:get_inventory()
for i = 1, inv:get_size(invstring) do
local m_stack = inv:get_stack(invstring, i)
local obj = minetest.add_item(pos, m_stack)
if obj then
obj:setvelocity({
x = math.random(-10, 10) / 9,
y = 3,
z = math.random(-10, 10) / 9
})
end
end
end
-- override chest node so it drops items on explode
minetest.override_item("default:chest", {
on_blast = function(p)
minetest.after(0, function()
drop_items(p, "main")
2016-06-06 16:11:55 +02:00
minetest.set_node(p, {name = "air"})
end)
end,
})
minetest.after(0, function()
print ("[MOD] Lucky Blocks loaded (" .. #lucky_list .. " in total)")
end)