123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806 |
- -- mod check
- local def = minetest.get_modpath("default")
- local mcl = minetest.get_modpath("mcl_core")
- -- global
- lucky_block = {
- mod_def = def,
- mod_mcl = mcl,
- snd_stone = def and default.node_sound_stone_defaults(),
- snd_wood = def and default.node_sound_wood_defaults(),
- snd_glass = def and default.node_sound_glass_defaults(),
- snd_pop = "default_hard_footstep",
- snd_pop2 = "default_place_node",
- def_item = "default:coal_lump",
- def_node = mcl and "mcl_core:dirt" or "default:dirt",
- def_flame = mcl and "mcl_fire:fire" or "fire:basic_flame",
- def_gold = mcl and "mcl_core:goldblock" or "default:goldblock",
- def_glass = mcl and "mcl_core:glass" or "default:glass",
- green = minetest.get_color_escape_sequence("#1eff00")
- }
- lucky_schems = {}
- -- quick sound setup
- if mcl then
- lucky_block.snd_glass = mcl_sounds.node_sound_glass_defaults()
- lucky_block.snd_wood = mcl_sounds.node_sound_wood_defaults()
- lucky_block.snd_stone = mcl_sounds.node_sound_stone_defaults()
- end
- -- translation support
- local S
- if minetest.get_translator ~= nil then
- S = minetest.get_translator("lucky_block") -- 5.x translation function
- else
- if minetest.get_modpath("intllib") then
- dofile(minetest.get_modpath("intllib") .. "/init.lua")
- if intllib.make_gettext_pair then
- gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
- else
- gettext = intllib.Getter() -- old text file method
- end
- S = gettext
- else -- boilerplate function
- S = function(str, ...)
- local args = {...}
- return str:gsub("@%d+", function(match)
- return args[tonumber(match:sub(2))]
- end)
- end
- end
- end
- lucky_block.intllib = S
- -- default blocks
- local lucky_list = {
- {"nod", "lucky_block:super_lucky_block", 0}
- }
- -- ability to add new blocks to list
- function lucky_block:add_blocks(list)
- for s = 1, #list do
- table.insert(lucky_list, list[s])
- end
- end
- -- call to purge the block list
- function lucky_block:purge_block_list()
- lucky_list = {
- {"nod", "lucky_block:super_lucky_block", 0}
- }
- end
- -- add schematics to global list
- function lucky_block:add_schematics(list)
- for s = 1, #list do
- table.insert(lucky_schems, list[s])
- end
- end
- -- for random colour selection
- local all_colours = {
- "grey", "black", "red", "yellow", "green", "cyan", "blue", "magenta",
- "orange", "violet", "brown", "pink", "dark_grey", "dark_green", "white"
- }
- if lucky_block.mcl then
- all_colours = {
- "red", "blue", "cyan", "grey", "silver", "black", "yellow", "green", "magenta",
- "orange", "purple", "brown", "pink", "lime", "light_blue", "white"
- }
- end
- -- default chests items
- local chest_stuff = {}
- -- call to purge the chest item list
- function lucky_block:purge_chest_items()
- chest_stuff = {}
- end
- -- ability to add to chest item list
- function lucky_block:add_chest_items(list)
- for s = 1, #list do
- table.insert(chest_stuff, list[s])
- end
- end
- -- particle effects
- local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow)
- radius = radius or 2
- gravity = gravity or -10
- minetest.add_particlespawner({
- amount = amount,
- time = 0.25,
- minpos = pos,
- maxpos = pos,
- minvel = {x = -radius, y = -radius, z = -radius},
- maxvel = {x = radius, y = radius, z = radius},
- minacc = {x = 0, y = gravity, z = 0},
- maxacc = {x = 0, y = gravity, z = 0},
- minexptime = 0.1,
- maxexptime = 1,
- minsize = min_size or 0.5,
- maxsize = max_size or 1.0,
- texture = texture,
- glow = glow
- })
- end
- -- temp entity for mob damage
- minetest.register_entity("lucky_block:temp", {
- physical = true,
- collisionbox = {0, 0, 0, 0, 0, 0},
- visual_size = {x = 0, y = 0},
- visual = "sprite",
- textures = {"tnt_smoke.png"},
- _is_arrow = true,
- on_step = function(self, dtime)
- self.timer = (self.timer or 0) + dtime
- if self.timer > 0.5 then
- self.object:remove()
- end
- end
- })
- -- modified from TNT mod to deal entity damage only
- local function entity_physics(pos, radius)
- radius = radius * 2
- local objs = minetest.get_objects_inside_radius(pos, radius)
- local obj_pos, dist
- -- add temp entity to cause damage
- local tmp_ent = minetest.add_entity(pos, "lucky_block:temp")
- for n = 1, #objs do
- obj_pos = objs[n]:get_pos()
- dist = vector.distance(pos, obj_pos)
- if dist < 1 then dist = 1 end
- local damage = math.floor((4 / dist) * radius)
- local ent = objs[n]:get_luaentity()
- objs[n]:punch(tmp_ent, 1.0, {
- full_punch_interval = 1.0,
- damage_groups = {fleshy = damage}
- }, pos)
- end
- end
- -- function to fill chest at position
- local function fill_chest(pos, items)
- local stacks = items or chest_stuff
- local meta = minetest.get_meta(pos)
- local inv = meta and meta:get_inventory()
- local size = inv and inv:get_size("main")
- local stack
- if not inv then return end
- -- loop through inventory
- for _, def in ipairs(stacks) do
- if math.random((def.chance or 1)) == 1 then
- -- only add if item existd
- if minetest.registered_items[def.name] then
- stack = ItemStack(def.name .. " " .. math.random((def.max or 1)))
- -- if wear levels found choose random wear between both values
- if def.max_wear and def.min_wear then
- stack:set_wear(65535 - (math.random(def.max_wear, def.min_wear)))
- end
- -- set stack in random position
- inv:set_stack("main", math.random(size), stack)
- end
- end
- end
- end
- -- explosion with protection check
- local function explode(pos, radius, sound)
- sound = sound or "tnt_explode"
- if minetest.get_modpath("tnt") and tnt and tnt.boom
- and not minetest.is_protected(pos, "") then
- tnt.boom(pos, {radius = radius, damage_radius = radius, sound = sound})
- else
- minetest.sound_play(sound, {pos = pos, gain = 1.0, max_hear_distance = 32}, true)
- entity_physics(pos, radius)
- effect(pos, 32, "tnt_smoke.png", radius * 3, radius * 5, radius, 1, 0)
- end
- end
- local lb_schematic = function(pos, digger, def)
- if #lucky_schems == 0 then
- print ("[lucky block] No schematics")
- return
- end
- local schem = def[2]
- local switch = def[3] or 0
- local force = def[4]
- local reps = def[5] or {}
- if switch == 1 then
- pos = vector.round(digger:get_pos())
- end
- 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], "", reps, force)
- break
- end
- end
- if switch == 1 then
- digger:set_pos(pos, false)
- end
- end
- local lb_node = function(pos, digger, def)
- local nod = def[2]
- local switch = def[3]
- local items = def[4]
- if switch == 1 then
- pos = digger:get_pos()
- end
- if not minetest.registered_nodes[nod] then
- nod = lucky_block.def_node
- end
- effect(pos, 25, "tnt_smoke.png", 8, 8, 2, 1, 0)
- minetest.set_node(pos, {name = nod})
- if nod == "default:chest"
- or nod == "mcl_chests:chest_small" then
- fill_chest(pos, items)
- end
- end
- local lb_spawn = function(pos, digger, def)
- local pos2 = {}
- local num = def[3] or 1
- local tame = def[4]
- local own = def[5]
- local range = def[6] or 5
- local name = def[7]
- for i = 1, num do
- pos2.x = pos.x + math.random(-range, range)
- pos2.y = pos.y + 1
- pos2.z = pos.z + math.random(-range, range)
- local nod = minetest.get_node(pos2)
- local nodef = minetest.registered_nodes[nod.name]
- if nodef and nodef.walkable == false then
- local entity
- -- select between random or single entity
- if type(def[2]) == "table" then
- entity = def[2][math.random(#def[2])]
- else
- entity = def[2]
- end
- -- coloured sheep
- if entity == "mobs:sheep" then
- local colour = "_" .. all_colours[math.random(#all_colours)]
- entity = "mobs:sheep" .. colour
- end
- if entity == "mobs_animal:sheep" then
- local colour = "_" .. all_colours[math.random(#all_colours)]
- entity = "mobs_animal:sheep" .. colour
- end
- -- has entity been registered?
- if minetest.registered_entities[entity] then
- local obj = minetest.add_entity(pos2, entity)
- if obj then
- local ent = obj:get_luaentity()
- if tame then
- ent.tamed = true
- end
- 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
- print ("[lucky_block] " .. entity .. " could not be spawned")
- end
- end
- end
- end
- end
- local lb_explode = function(pos, def)
- local rad = def[2] or 2
- local snd = def[3] or "tnt_explode"
- explode(pos, rad, snd)
- end
- local lb_teleport = function(pos, digger, def)
- local xz_range = def[2] or 10
- local y_range = def[3] or 5
- pos.x = pos.x + math.random(-xz_range, xz_range)
- pos.y = pos.y + math.random(-y_range, y_range)
- pos.z = pos.z + math.random(-xz_range, xz_range)
- effect(pos, 25, "tnt_smoke.png", 8, 8, 1, -10, 0)
- digger:set_pos(pos, false)
- effect(pos, 25, "tnt_smoke.png", 8, 8, 1, -10, 0)
- minetest.chat_send_player(digger:get_player_name(),
- lucky_block.green .. S("Random Teleport!"))
- end
- local lb_drop = function(pos, digger, def)
- local num = def[3] or 1
- local colours = def[4]
- local items = #def[2]
- -- drop multiple different items or colours
- if items > 1 or colours then
- for i = 1, num do
- local item = def[2][math.random(items)]
- if colours then
- item = item .. all_colours[math.random(#all_colours)]
- end
- if not minetest.registered_items[item] then
- item = lucky_block.def_item
- end
- local obj = minetest.add_item(pos, item)
- if obj then
- obj:set_velocity({
- x = math.random(-10, 10) / 9,
- y = 5,
- z = math.random(-10, 10) / 9
- })
- end
- end
- else -- drop single item in a stack
- local item = def[2][1]
- if not minetest.registered_items[item] then
- item = ItemStack(lucky_block.def_item .. " " .. tonumber(num))
- else
- item = ItemStack(item .. " " .. tonumber(num))
- end
- local obj = minetest.add_item(pos, item)
- if obj then
- obj:set_velocity({
- x = math.random(-10, 10) / 9,
- y = 5,
- z = math.random(-10, 10) / 9
- })
- end
- end
- end
- local lb_lightning = function(pos, digger, def)
- local nod = def[2]
- if not minetest.registered_nodes[nod] then
- nod = lucky_block.def_flame
- end
- pos = digger:get_pos()
- local bnod = minetest.get_node_or_nil(pos)
- local bref = bnod and minetest.registered_items[bnod.name]
- if bref and bref.buildable_to then
- minetest.set_node(pos, {name = nod})
- end
- minetest.add_particle({
- pos = pos,
- velocity = {x = 0, y = 0, z = 0},
- acceleration = {x = 0, y = 0, z = 0},
- expirationtime = 1.0,
- collisiondetection = false,
- texture = "lucky_lightning.png",
- size = math.random(100, 150),
- glow = 15
- })
- entity_physics(pos, 2)
- minetest.sound_play("lightning", {
- pos = pos, gain = 1.0, max_hear_distance = 25}, true)
- end
- local lb_falling = function(pos, digger, def)
- local nods = def[2]
- local switch = def[3]
- local spread = def[4]
- local range = def[5] or 5
- if switch == 1 then
- pos = digger:get_pos()
- end
- if spread then
- pos.y = pos.y + 10
- else
- pos.y = pos.y + #nods
- end
- minetest.remove_node(pos)
- local pos2 = {x = pos.x, y = pos.y, z = pos.z}
- for s = 1, #nods do
- minetest.after(0.5 * s, function()
- if spread then
- pos2.x = pos.x + math.random(-range, range)
- pos2.z = pos.z + math.random(-range, range)
- end
- local n = table.copy(minetest.registered_nodes[nods[s]])
- if n then
- local obj = minetest.add_entity(pos2, "__builtin:falling_node")
- if obj then
- local ent = obj:get_luaentity()
- if ent then
- n.param2 = 1 -- set default rotation
- ent:set_node(n)
- end
- end
- end
- end)
- end
- end
- local lb_troll = function(pos, def)
- local nod = def[2]
- local snd = def[3]
- local exp = def[4]
- if not minetest.registered_nodes[nod] then
- nod = lucky_block.def_gold
- end
- minetest.set_node(pos, {name = nod})
- if snd then
- minetest.sound_play(snd, {pos = pos, gain = 1.0, max_hear_distance = 10}, true)
- end
- minetest.after(2.0, function()
- if exp then
- minetest.set_node(pos, {name = "air"})
- explode(pos, 2)
- else
- minetest.set_node(pos, {name = "air"})
- minetest.sound_play(lucky_block.snd_pop, {
- pos = pos, gain = 1.0, max_hear_distance = 10}, true)
- end
- end)
- end
- local lb_floor = function(pos, def)
- local size = def[2] or 1
- local nods = def[3] or {lucky_block.def_node}
- local offs = def[4] or 0
- local num = 1
- for x = 0, size - 1 do
- for z = 0, size - 1 do
- minetest.after(0.5 * num, function()
- local nod = nods[math.random(#nods)]
- local def = minetest.registered_nodes[nod]
- local snd = def and def.sounds and def.sounds.place
- minetest.set_node({
- x = (pos.x + x) - offs,
- y = pos.y - 1,
- z = (pos.z + z) - offs}, {name = nod})
- minetest.sound_play(snd, {
- pos = pos, gain = 1.0, max_hear_distance = 10}, true)
- end)
- num = num + 1
- end
- end
- end
- -- this is what happens when you dig a lucky block
- function lucky_block:open(pos, digger, blocks_list)
- -- check for custom blocks list or use default
- blocks_list = blocks_list or lucky_list
- -- make sure it's really random
- math.randomseed(minetest.get_timeofday() + pos.x + pos.z - os.time())
- local luck = math.random(#blocks_list) ; -- luck = 1
- local result = blocks_list[luck]
- local action = result[1]
- -- print ("luck ["..luck.." of "..#blocks_list.."]", action)
- -- place schematic
- if action == "sch" then lb_schematic(pos, digger, result)
- -- place node (if chest then fill chest)
- elseif action == "nod" then lb_node(pos, digger, result)
- -- place entity
- elseif action == "spw" then lb_spawn(pos, digger, result)
- -- explosion
- elseif action == "exp" then lb_explode(pos, result)
- -- teleport
- elseif action == "tel" then lb_teleport(pos, digger, result)
- -- drop items
- elseif action == "dro" then lb_drop(pos, digger, result)
- -- lightning strike
- elseif action == "lig" then lb_lightning(pos, digger, result)
- -- falling nodes
- elseif action == "fal" then lb_falling(pos, digger, result)
- -- troll block, disappears or explodes after 2 seconds
- elseif action == "tro" then lb_troll(pos, result)
- -- floor paint
- elseif action == "flo" then lb_floor(pos, result)
- -- custom function
- elseif action == "cus" then
- if result[2] then result[2](pos, digger, result[3]) end
- end
- end
- -- lucky block itself
- minetest.register_node("lucky_block:lucky_block", {
- description = S("Lucky Block"),
- tiles = {{
- name = "lucky_block_animated.png",
- animation = {
- type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 1
- }
- }},
- inventory_image = minetest.inventorycube("lucky_block.png"),
- sunlight_propagates = false,
- is_ground_content = false,
- paramtype = "light",
- light_source = 3,
- groups = {handy = 2, oddly_breakable_by_hand = 3, unbreakable = 1},
- drop = {},
- sounds = lucky_block.snd_wood,
- on_dig = function(pos, node, digger)
- minetest.set_node(pos, {name = "air"})
- lucky_block:open(pos, digger)
- end,
- on_blast = function() end,
- _mcl_hardness = 1,
- _mcl_blast_resistance = 1200
- })
- local gitem = mcl and "mcl_core:gold_ingot" or "default:gold_ingot"
- local citem = mcl and "mcl_chests:chest" or "default:chest"
- minetest.register_craft({
- output = "lucky_block:lucky_block",
- recipe = {
- {gitem, gitem, gitem},
- {gitem, citem, gitem},
- {gitem, gitem, gitem}
- }
- })
- local grp = {cracky = 1, level = 2, unbreakable = 1}
- -- change super lucky block groups for mineclone
- if mcl then
- grp.handy = 5
- grp.level = nil
- end
- -- super lucky block
- minetest.register_node("lucky_block:super_lucky_block", {
- description = S("Super Lucky Block (use pick)"),
- tiles = {{
- name = "lucky_block_super_animated.png",
- animation = {
- type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 1
- }
- }},
- inventory_image = minetest.inventorycube("lucky_block_super.png"),
- sunlight_propagates = false,
- is_ground_content = false,
- paramtype = "light",
- groups = grp,
- drop = {},
- sounds = lucky_block.snd_stone,
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_string("infotext", "Super Lucky Block")
- end,
- on_dig = function(pos)
- if math.random(10) < 8 then
- minetest.set_node(pos, {name = "air"})
- effect(pos, 25, "tnt_smoke.png", 8, 8, 1, -10, 0)
- minetest.sound_play("fart1", {
- pos = pos, gain = 1.0, max_hear_distance = 10}, true)
- if math.random(5) == 1 then
- pos.y = pos.y + 0.5
- minetest.add_item(pos, lucky_block.def_gold .. " " .. math.random(5))
- end
- else
- minetest.set_node(pos, {name = "lucky_block:lucky_block"})
- end
- end,
- on_blast = function() end,
- _mcl_hardness = 8,
- _mcl_blast_resistance = 1200
- })
- local path = minetest.get_modpath("lucky_block")
- -- import schematics
- dofile(path .. "/lb_schems.lua")
- -- wishing well & drops
- dofile(path .. "/lb_well.lua")
- -- lucky block special items and blocks
- dofile(path .. "/lb_special.lua")
- -- if mineclone detected then load specific lucky blocks
- if mcl then
- dofile(path .. "/lb_mineclone.lua")
- else
- dofile(path .. "/lb_default.lua")
- end
- -- 3rd party mod lucky blocks
- dofile(path .. "/lb_other.lua")
- minetest.after(0, function()
- print("[MOD] Lucky Blocks loaded: ", #lucky_list)
- end)
|