7 Commits

Author SHA1 Message Date
fbb674a01c Réduit le spawn des pyramides 2019-04-04 16:29:07 +02:00
ea6f428e7d Ajoute message de chargement du mod dans le journal "action" 2019-01-19 19:35:58 +01:00
7b281bec47 Ajout de la régénération des items toutes les 30 minutes
- Les coffres deviennent indestructibles
- Ajout d'un timer de 30 minutes pour le régénération des items
2018-12-23 13:01:43 +01:00
99349cc616 Rend les pyramides indestructibles 2018-12-23 10:39:17 +01:00
57adec6576 Modifie la génération des objets dans les coffres 2018-12-22 11:17:04 +01:00
55f4a1f292 Pyramids spawn only in desert biomes with desert_sand.
There is 3 types of pyramids now:
Sand (default), desert_sand and silver_sand pyramids.
2018-03-28 01:39:54 +02:00
145a73188c Update falling nodes detection in order to avoid crash 2018-03-26 19:50:35 +02:00
19 changed files with 435 additions and 1940 deletions

View File

@ -1,13 +1,13 @@
# Pyramids (with Treasurer support) [`tsm_pyramids`] # Pyramids (with Treasurer support) [`tsm_pyramids`]
* Version: 1.0.2 * Version: 0.6
## Description ## Description
This is a mod for Minetest Game which adds randomly spawned pyramids in deserts and This mod adds randomly spawned pyramids in deserts. The pyramids are very rare
sandstone deserts. The pyramids are very rare and contain chests with stuff. and contain a chest with stuff. Also there are mummys inside, which attack
Also there are mummies inside, which attack the player if found in their radius. the player if found in their radius.
## Historic notes ## For users of the old `pyramids` mod
This mod is a fork of the old `pyramids` mod by BlockMen and intended to be a direct This mod is a fork of the old `pyramids` mod by BlockMen and intended to be a direct
(but unofficial) successor of it. (but unofficial) successor of it.
@ -17,12 +17,12 @@ the extent permitted by applicable law.
### Source code and textures ### Source code and textures
* [MIT License](https://mit-license.org/) * [WTFPL](http://www.wtfpl.net/txt/copying/)
* (c) Copyright BlockMen (2013) * (c) Copyright BlockMen (2013)
### Mummy model ### Mummy model
* MIT License * WTFPL
* (c) Copyright Pavel\_S (2013) * (c) Copyright Pavel\_S (2013)
### Textures ### Textures
@ -30,7 +30,7 @@ the extent permitted by applicable law.
* `tsm_pyramids_eye.png` by bas080, [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) * `tsm_pyramids_eye.png` by bas080, [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
* `tsm_pyramids_men.png` by bas080, CC-BY-SA 3.0 * `tsm_pyramids_men.png` by bas080, CC-BY-SA 3.0
* `tsm_pyramids_sun.png` by bas080, CC-BY-SA 3.0 * `tsm_pyramids_sun.png` by bas080, CC-BY-SA 3.0
* All other: BlockMen (MIT License) * All other: BlockMen, WTFPL
### Sounds ### Sounds
The authors are ([freesound.org](https://freesound.org)): The authors are ([freesound.org](https://freesound.org)):

17
TODO
View File

@ -1,17 +0,0 @@
Minibugs:
- Mummy doesn't avoid lava
Features:
- More random rooms!
- Man statue
- Falling traps from above
- More variety in pyramid exterior styles
- Different entrances
- Stairs leading to entrance
- Open roof? For sun room
- Multiple entries (temple-like pyramids)
- Different pyramid sizes
- Damaged pyramids
- Missing blocks
- Trap stones
- No mummies, traps or treasures

8
depends.txt Normal file
View File

@ -0,0 +1,8 @@
default
maptools
farming?
sandplus?
treasurer?
intllib?
doc_items?
awards?

517
init.lua
View File

@ -1,124 +1,51 @@
local S = minetest.get_translator("tsm_pyramids") pyramids = {}
pyramids.max_time = 60 * 30
-- Pyramid width (must be an odd number) local random = math.random
local PYRA_W = 23
-- Pyramid width minus 1
local PYRA_Wm = PYRA_W - 1
-- Half of (Pyramid width minus 1)
local PYRA_Wh = PYRA_Wm / 2
-- Minimum spawn height
local PYRA_MIN_Y = 3
tsm_pyramids = {}
dofile(minetest.get_modpath("tsm_pyramids").."/mummy.lua") dofile(minetest.get_modpath("tsm_pyramids").."/mummy.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/nodes.lua") dofile(minetest.get_modpath("tsm_pyramids").."/nodes.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/room.lua") dofile(minetest.get_modpath("tsm_pyramids").."/room.lua")
local mg_name = minetest.get_mapgen_setting("mg_name")
local chest_stuff = { local chest_stuff = {
normal = { {name="default:apple", max = 3},
{name="default:steel_ingot", max = 3}, {name="farming:bread", max = 3},
{name="default:copper_ingot", max = 3}, {name="default:steel_ingot", max = 2},
{name="default:gold_ingot", max = 2}, {name="default:gold_ingot", max = 2},
{name="default:diamond", max = 1}, {name="default:diamond", max = 1},
{name="default:pick_steel", max = 1}, {name="default:pick_steel", max = 1},
}, {name="default:pick_diamond", max = 1}
desert_stone = {
{name="default:mese_crystal", max = 4},
{name="default:gold_ingot", max = 10},
{name="default:pick_diamond", max = 1},
},
desert_sandstone = {
{name="default:apple", max = 1},
{name="default:stick", max = 64},
{name="default:acacia_bush_sapling", max = 1},
{name="default:paper", max = 9},
{name="default:shovel_bronze", max = 1},
{name="default:pick_mese", max = 1},
},
sandstone = {
{name="default:obsidian_shard", max = 5},
{name="default:apple", max = 3},
{name="default:blueberries", max = 9},
{name="default:glass", max = 64},
{name="default:bush_sapling", max = 1},
{name="default:pick_bronze", max = 1},
},
} }
if minetest.get_modpath("farming") then function pyramids.fill_chest(pos)
table.insert(chest_stuff.desert_sandstone, {name="farming:bread", max = 3})
table.insert(chest_stuff.sandstone, {name="farming:bread", max = 4})
table.insert(chest_stuff.normal, {name="farming:cotton", max = 32})
table.insert(chest_stuff.desert_sandstone, {name="farming:seed_cotton", max = 3})
table.insert(chest_stuff.desert_sandstone, {name="farming:hoe_stone", max = 1})
else
table.insert(chest_stuff.normal, {name="farming:apple", max = 8})
table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
end
if minetest.get_modpath("tnt") then
table.insert(chest_stuff.normal, {name="tnt:gunpowder", max = 6})
table.insert(chest_stuff.desert_stone, {name="tnt:gunpowder", max = 6})
else
table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
end
function tsm_pyramids.fill_chest(pos, stype, flood_sand, treasure_chance)
local sand = "default:sand"
local n = minetest.get_node(pos) local n = minetest.get_node(pos)
local meta = minetest.get_meta(pos) if n and n.name and n.name == "tsm_pyramids:chest" then
if not treasure_chance then
treasure_chance = 100
end
if meta:get_string("tsm_pyramids:stype") == "desert_sandstone" or
meta:get_string("tsm_pyramids:stype") == "desert_stone" or
stype == "desert_sandstone" or stype == "desert_stone" then
sand = "default:desert_sand"
end
local treasure_added = false
if n and n.name and n.name == "default:chest" then
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 8*4) inv:set_size("main", 8*4)
inv:set_list("main", { [1] = "", [32] = "" })
if random(1,10) < 7 then return end
local stacks = {} local stacks = {}
-- Fill with sand in sand-flooded pyramids if minetest.get_modpath("treasurer") ~= nil then
if meta:get_int("tsm_pyramids:sanded") == 1 or flood_sand then stacks = treasurer.select_random_treasures(3,1,5,{"armes", "armures", "precieux"})
table.insert(stacks, {name=sand, count = math.random(1,32)}) else
end for i=0,2,1 do
-- Add treasures local stuff = chest_stuff[random(1,#chest_stuff)]
if math.random(1,100) <= treasure_chance then if stuff.name == "farming:bread" and not minetest.get_modpath("farming") then stuff = chest_stuff[1] end
if minetest.get_modpath("treasurer") ~= nil then table.insert(stacks, {name=stuff.name, count = random(1,stuff.max)})
stacks = treasurer.select_random_treasures(3,1,5,{"armes", "armures", "precieux", "nourriture"})
else
for i=0,2,1 do
local stuff = chest_stuff.normal[math.random(1,#chest_stuff.normal)]
table.insert(stacks, {name=stuff.name, count = math.random(1,stuff.max)})
end
if math.random(1,100) <= 75 then
local stuff = chest_stuff[stype][math.random(1,#chest_stuff[stype])]
table.insert(stacks, {name=stuff.name, count = math.random(1,stuff.max)})
end
treasure_added = true
end end
end end
for s=1,#stacks do for s=1,#stacks do
if not inv:contains_item("main", stacks[s]) then if not inv:contains_item("main", stacks[s]) then
inv:set_stack("main", math.random(1,32), stacks[s]) inv:set_stack("main", random(1,32), stacks[s])
end end
end end
end end
return treasure_added
end end
local function add_spawner(pos, mummy_offset) local function add_spawner(pos)
minetest.set_node(pos, {name="tsm_pyramids:spawner_mummy"}) minetest.set_node(pos, {name="tsm_pyramids:spawner_mummy"})
if not minetest.settings:get_bool("only_peaceful_mobs") then if not minetest.setting_getbool("only_peaceful_mobs") then pyramids.spawn_mummy({x=pos.x,y=pos.y,z=pos.z-2},2) end
for i=1,2 do
tsm_pyramids.attempt_mummy_spawn(pos, false)
end
end
end end
local function can_replace(pos) local function can_replace(pos)
@ -132,116 +59,58 @@ local function can_replace(pos)
end end
end end
local function make_foundation_part(pos, set_to_stone) local function underground(pos, stone, sand)
local p2 = pos local p2 = pos
local cnt = 0 local cnt = 0
local mat = stone
p2.y = p2.y-1 p2.y = p2.y-1
while can_replace(p2)==true do while can_replace(p2)==true do
cnt = cnt+1 cnt = cnt+1
if cnt > 25 then if cnt > 25 then break end
break if cnt>random(2,4) then mat = stone end
end minetest.set_node(p2, {name=mat})
table.insert(set_to_stone, table.copy(p2))
p2.y = p2.y-1 p2.y = p2.y-1
end end
end end
local function make_entrance(pos, rot, brick, sand, flood_sand) local function make_entrance(pos, brick)
local roffset_arr = { local gang = {x=pos.x+10,y=pos.y, z=pos.z}
{ x=0, y=0, z=1 }, -- front for iy=2,3,1 do
{ x=-1, y=0, z=0 }, -- left for iz=0,6,1 do
{ x=0, y=0, z=-1 }, -- back minetest.remove_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz})
{ x=1, y=0, z=0 }, -- right if iz >=3 and iy == 3 then
} minetest.set_node({x=gang.x,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
local roffset = roffset_arr[rot + 1] minetest.set_node({x=gang.x+1,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
local way minetest.set_node({x=gang.x+2,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
if rot == 0 then
way = vector.add(pos, {x=PYRA_Wh, y=0, z=0})
elseif rot == 1 then
way = vector.add(pos, {x=PYRA_Wm, y=0, z=PYRA_Wh})
elseif rot == 2 then
way = vector.add(pos, {x=PYRA_Wh, y=0, z=PYRA_Wm})
else
way = vector.add(pos, {x=0, y=0, z=PYRA_Wh})
end
local max_sand_height = math.random(1,3)
for ie=0,6,1 do
local sand_height = math.random(1,max_sand_height)
for iy=2,3,1 do
-- dig hallway
local way_dir = vector.add(vector.add(way, {x=0,y=iy,z=0}), vector.multiply(roffset, ie))
if flood_sand and sand ~= "ignore" and iy <= sand_height and ie >= 3 then
minetest.set_node(way_dir, {name=sand})
else
minetest.remove_node(way_dir)
end
-- build decoration above entrance
if ie == 3 and iy == 3 then
local deco = {x=way_dir.x, y=way_dir.y+1,z=way_dir.z}
minetest.set_node(deco, {name=brick})
if rot == 0 or rot == 2 then
minetest.set_node(vector.add(deco, {x=-1, y=0, z=0}), {name=brick})
minetest.set_node(vector.add(deco, {x=1, y=0, z=0}), {name=brick})
else
minetest.set_node(vector.add(deco, {x=0, y=0, z=-1}), {name=brick})
minetest.set_node(vector.add(deco, {x=0, y=0, z=1}), {name=brick})
end
end end
end end
end end
end end
local function make_pyramid(pos, brick, sandstone, stone, sand) local function make(pos, brick, sandstone, stone, sand)
local set_to_brick = {} minetest.log("action", "Created pyramid at ("..pos.x..","..pos.y..","..pos.z..")")
local set_to_stone = {} for iy=0,10,1 do
-- Build pyramid for ix=iy,22-iy,1 do
for iy=0,math.random(10,PYRA_Wh),1 do for iz=iy,22-iy,1 do
for ix=iy,PYRA_W-1-iy,1 do if iy <1 then underground({x=pos.x+ix,y=pos.y,z=pos.z+iz}, stone, sand) end
for iz=iy,PYRA_W-1-iy,1 do minetest.set_node({x=pos.x+ix,y=pos.y+iy,z=pos.z+iz}, {name=brick})
if iy < 1 then for yy=1,10-iy,1 do
make_foundation_part({x=pos.x+ix,y=pos.y,z=pos.z+iz}, set_to_stone) local n = minetest.get_node({x=pos.x+ix,y=pos.y+iy+yy,z=pos.z+iz})
if n and n.name and n.name == stone then
minetest.set_node({x=pos.x+ix,y=pos.y+iy+yy,z=pos.z+iz},{name=sand})
end
end end
table.insert(set_to_brick, {x=pos.x+ix,y=pos.y+iy,z=pos.z+iz})
end end
end end
end end
minetest.bulk_set_node(set_to_stone , {name=stone})
minetest.bulk_set_node(set_to_brick, {name=brick})
end
local function make(pos, brick, sandstone, stone, sand, ptype, room_id) pyramids.make_room(pos)
local bpos = table.copy(pos) minetest.after(2, pyramids.make_traps, pos)
-- Build pyramid add_spawner({x=pos.x+11,y=pos.y+2, z=pos.z+17})
make_pyramid(bpos, brick, sandstone, stone, sand) make_entrance({x=pos.x,y=pos.y, z=pos.z}, brick)
local rot = math.random(0, 3)
-- Build room
local ok, msg, flood_sand = tsm_pyramids.make_room(bpos, ptype, room_id, rot)
-- Place mummy spawner
local r = math.random(1,3)
-- 4 possible spawner positions
local spawner_posses = {
-- front
{{x=bpos.x+PYRA_Wh,y=bpos.y+2, z=bpos.z+5}, {x=0, y=0, z=2}},
-- left
{{x=bpos.x+PYRA_Wm-5,y=bpos.y+2, z=bpos.z+PYRA_Wh}, {x=-2, y=0, z=0}},
-- back
{{x=bpos.x+PYRA_Wh,y=bpos.y+2, z=bpos.z+PYRA_W-5}, {x=0, y=0, z=-2}},
-- right
{{x=bpos.x+5,y=bpos.y+2, z=bpos.z+PYRA_Wh}, {x=2, y=0, z=0}},
}
-- Delete the spawner position in which the entrance will be placed
table.remove(spawner_posses, (rot % 4) + 1)
add_spawner(spawner_posses[r][1], spawner_posses[r][2])
-- Build entrance
make_entrance(bpos, rot, brick, sand, flood_sand)
-- Done
minetest.log("action", "[tsm_pyramids] Created pyramid at "..minetest.pos_to_string(bpos)..".")
return ok, msg
end end
local perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} -- Values should match minetest mapgen V6 desert noise. local perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} -- Values should match minetest mapgen V6 desert noise.
local perlin1 -- perlin noise buffer
local function hlp_fnct(pos, name) local function hlp_fnct(pos, name)
local n = minetest.get_node_or_nil(pos) local n = minetest.get_node_or_nil(pos)
@ -252,171 +121,98 @@ local function hlp_fnct(pos, name)
end end
end end
local function ground(pos, old) local function ground(pos, old)
local p2 = table.copy(pos) local p2 = pos
while hlp_fnct(p2, "air") do while hlp_fnct(p2, "air") do
p2.y = p2.y -1 p2.y = p2.y -1
end end
if p2.y < old.y then if p2.y < old.y then
return {x=old.x, y=p2.y, z=old.z} return p2
else else
return old return old
end end
end end
-- Select the recommended type of pyramid to use, based on the environment.
-- One of sandstone, desert sandstone, desert stone.
local select_pyramid_type = function(minp, maxp)
local mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
local sand minetest.register_on_generated(
local sands = {"default:sand", "default:desert_sand", "default:desert_stone"} function(minp, maxp, seed)
local p2 minetest.after(
local psand = {} 3, function(minp, maxp, seed)
local sand if maxp.y < 0 then return end
local cnt = 0 math.randomseed(seed)
local sand_cnt_max = 0 local cnt = 0
local sand_cnt_max_id
-- Look for sand or desert stone to place the pyramid on local perlin1 = minetest.env:get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
for s=1, #sands do local noise1 = perlin1:get2d({x=minp.x,y=minp.y})--,z=minp.z})
cnt = 0
local sand_cnt = 0 if noise1 > 0.75 or noise1 < -0.76 then
sand = sands[s] local mpos = {x=random(minp.x,maxp.x), y=random(minp.y,maxp.y), z=random(minp.z,maxp.z)}
psand[s] = minetest.find_node_near(mpos, 25, sand)
while cnt < 5 do local sands = {"default:desert_sand"}
cnt = cnt+1 local p2
mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)} local sand
local spos = minetest.find_node_near(mpos, 25, sand) for s=1, #sands do
if spos ~= nil then sand = sands[s]
sand_cnt = sand_cnt + 1 p2 = minetest.find_node_near(mpos, 25, sand)
if psand[s] == nil then while p2 == nil and cnt < 5 do
psand[s] = spos cnt = cnt+1
mpos = {x=random(minp.x,maxp.x), y=random(minp.y,maxp.y), z=random(minp.z,maxp.z)}
p2 = minetest.find_node_near(mpos, 25, sand)
end
if p2 ~= nil then
break
end
end
if p2 == nil then return end
if p2.y < 0 then return end
local off = 0
local opos1 = {x=p2.x+22,y=p2.y-1,z=p2.z+22}
local opos2 = {x=p2.x+22,y=p2.y-1,z=p2.z}
local opos3 = {x=p2.x,y=p2.y-1,z=p2.z+22}
local opos1_n = minetest.get_node_or_nil(opos1)
local opos2_n = minetest.get_node_or_nil(opos2)
local opos3_n = minetest.get_node_or_nil(opos3)
if opos1_n and opos1_n.name and opos1_n.name == "air" then
p2 = ground(opos1, p2)
end
if opos2_n and opos2_n.name and opos2_n.name == "air" then
p2 = ground(opos2, p2)
end
if opos3_n and opos3_n.name and opos3_n.name == "air" then
p2 = ground(opos3, p2)
end
p2.y = p2.y - 3
if p2.y < 0 then p2.y = 0 end
if minetest.find_node_near(p2, 25, {"default:water_source"}) ~= nil or
minetest.find_node_near(p2, 22, {"default:dirt_with_grass"}) ~= nil or
minetest.find_node_near(p2, 52, {"maptools:sandstone_brick"}) ~= nil or
minetest.find_node_near(p2, 52, {"maptools:desert_sandstone_brick"}) ~= nil or
minetest.find_node_near(p2, 52, {"maptools:silver_sandstone_brick"}) ~= nil or
minetest.find_node_near(p2, 52, {"sandplus:desert_sandstonebrick"}) ~= nil
then return end
if random(0,10) > 7 then
return
end
local p_type = random(1, 3)
local p_pot = {
[1] = {"maptools:sandstone_brick", "default:sandstone", "default:sandstone", "default:sand"},
[2] = {"maptools:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand"},
[3] = {"maptools:silver_sandstone_brick", "default:silver_sandstone", "default:silver_sandstone", "default:silver_sand"}
}
if sand == "default:desert_sand" then
if minetest.get_modpath("sandplus") then
minetest.after(0.8, make, p2, "sandplus:desert_sandstonebrick", "sandplus:desert_sandstone", "default:desert_stone", "default:desert_sand")
else
minetest.after(0.8, make, p2, p_pot[p_type][1], p_pot[p_type][2], p_pot[p_type][3], p_pot[p_type][4])
end
else
minetest.after(0.8, make, p2, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand")
end
end end
end end, minp, maxp, seed)
if sand_cnt > sand_cnt_max then end)
sand_cnt_max = sand_cnt
sand_cnt_max_id = s
p2 = psand[s]
end
end
end
-- Select the material type by the most prominent node type
-- E.g. if desert sand is most prominent, we place a desert sandstone pyramid
if sand_cnt_max_id then
sand = sands[sand_cnt_max_id]
else
sand = nil
p2 = nil
end
return sand, p2
end
-- Attempt to generate a pyramid in the generated area.
-- Up to one pyramid per mapchunk.
minetest.register_on_generated(function(minp, maxp, seed)
if maxp.y < PYRA_MIN_Y then return end
-- TODO: Use Minetests pseudo-random tools
math.randomseed(seed)
if not perlin1 then
perlin1 = minetest.get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
end
--[[ Make sure the pyramid doesn't bleed outside of maxp,
so it doesn't get placed incompletely by the mapgen.
This creates a bias somewhat, as this means there are some coordinates in
which pyramids cannot spawn. But it's still better to have broken pyramids.
]]
local limit = function(pos, maxp)
pos.x = math.min(pos.x, maxp.x - PYRA_W+1)
pos.y = math.min(pos.y, maxp.y - PYRA_Wh)
pos.z = math.min(pos.z, maxp.z - PYRA_W+1)
return pos
end
local noise1 = perlin1:get_2d({x=minp.x,y=minp.y})
if noise1 > 0.25 or noise1 < -0.26 then
-- Need a bit of luck to place a pyramid
if math.random(0,10) > 7 then
minetest.log("verbose", "[tsm_pyramids] Pyramid not placed, bad dice roll. minp="..minetest.pos_to_string(minp))
return
end
local sand, p2
sand, p2 = select_pyramid_type(minp, maxp)
if p2 == nil then
minetest.log("verbose", "[tsm_pyramids] Pyramid not placed, no suitable surface. minp="..minetest.pos_to_string(minp))
return
end
if p2.y < PYRA_MIN_Y then
minetest.log("info", "[tsm_pyramids] Pyramid not placed, too deep. p2="..minetest.pos_to_string(p2))
return
end
-- Now sink the pyramid until each corner of it is no longer floating in mid-air
p2 = limit(p2, maxp)
local oposses = {
{x=p2.x,y=p2.y-1,z=p2.z},
{x=p2.x+PYRA_Wm,y=p2.y-1,z=p2.z+PYRA_Wm},
{x=p2.x+PYRA_Wm,y=p2.y-1,z=p2.z},
{x=p2.x,y=p2.y-1,z=p2.z+PYRA_Wm},
}
for o=1, #oposses do
local opos = oposses[o]
local n = minetest.get_node_or_nil(opos)
if n and n.name and n.name == "air" then
local old = table.copy(p2)
p2 = ground(opos, p2)
end
end
-- Random bonus sinking
p2.y = math.max(p2.y - math.random(0,3), PYRA_MIN_Y)
-- Bad luck, we have hit the chunk border!
if p2.y < minp.y then
minetest.log("info", "[tsm_pyramids] Pyramid not placed, sunken too much. p2="..minetest.pos_to_string(p2))
return
end
-- Make sure the pyramid is not near a "killer" node, like water
local middle = vector.add(p2, {x=PYRA_Wh, y=0, z=PYRA_Wh})
if minetest.find_node_near(p2, 5, {"default:water_source"}) ~= nil or
minetest.find_node_near(vector.add(p2, {x=PYRA_W, y=0, z=0}), 5, {"default:water_source"}) ~= nil or
minetest.find_node_near(vector.add(p2, {x=0, y=0, z=PYRA_W}), 5, {"default:water_source"}) ~= nil or
minetest.find_node_near(vector.add(p2, {x=PYRA_W, y=0, z=PYRA_W}), 5, {"default:water_source"}) ~= nil or
minetest.find_node_near(middle, PYRA_W, {"default:dirt_with_grass"}) ~= nil or
minetest.find_node_near(middle, 52, {"default:sandstonebrick", "default:desert_sandstone_brick", "default:desert_stonebrick"}) ~= nil or
minetest.find_node_near(middle, PYRA_Wh + 3, {"default:cactus", "group:leaves", "group:tree"}) ~= nil then
minetest.log("info", "[tsm_pyramids] Pyramid not placed, inappropriate node nearby. p2="..minetest.pos_to_string(p2))
return
end
-- Bonus chance to spawn a sandstone pyramid in v6 desert because otherwise they would be too rare in v6
if (mg_name == "v6" and sand == "default:desert_sand" and math.random(1, 2) == 1) then
sand = "default:sand"
end
-- Desert stone pyramids only generate in areas with almost no sand
if sand == "default:desert_stone" then
local nodes = minetest.find_nodes_in_area(vector.add(p2, {x=-1, y=-2, z=-1}), vector.add(p2, {x=PYRA_W+1, y=PYRA_Wh, z=PYRA_W+1}), {"group:sand"})
if #nodes > 5 then
sand = "default:desert_sand"
end
end
-- Generate the pyramid!
if sand == "default:desert_sand" then
-- Desert sandstone pyramid
make(p2, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone")
elseif sand == "default:sand" then
-- Sandstone pyramid
make(p2, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone")
else
-- Desert stone pyramid
make(p2, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "ignore", "desert_stone")
end
end
end)
-- Add backwards-compability for nodes from the original pyramids mod -- Add backwards-compability for nodes from the original pyramids mod
if minetest.get_modpath("pyramids") == nil then if minetest.get_modpath("pyramids") == nil then
@ -427,42 +223,9 @@ if minetest.get_modpath("pyramids") == nil then
minetest.register_alias("pyramids:deco_stone2", "tsm_pyramids:deco_stone2") minetest.register_alias("pyramids:deco_stone2", "tsm_pyramids:deco_stone2")
minetest.register_alias("pyramids:deco_stone3", "tsm_pyramids:deco_stone3") minetest.register_alias("pyramids:deco_stone3", "tsm_pyramids:deco_stone3")
minetest.register_alias("pyramids:spawner_mummy", "tsm_pyramids:spawner_mummy") minetest.register_alias("pyramids:spawner_mummy", "tsm_pyramids:spawner_mummy")
-- FIXME: Entities are currently NOT backwards-compatible
-- TODO: Update README when full backwards-compability is achieved
end end
minetest.register_chatcommand("spawnpyramid", { minetest.log("action", "[tsm_pyramids] loaded.")
description = S("Generate a pyramid"),
params = S("[<room_type>]"),
privs = { server = true },
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then
return false, S("No player.")
end
local pos = player:get_pos()
pos = vector.round(pos)
local s = math.random(1,3)
local r = tonumber(param)
local room_id
if r then
room_id = r
end
local ok, msg
pos = vector.add(pos, {x=-PYRA_Wh, y=-1, z=0})
if s == 1 then
-- Sandstone
ok, msg = make(pos, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone", room_id)
elseif s == 2 then
-- Desert sandstone
ok, msg = make(pos, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone", room_id)
else
-- Desert stone
ok, msg = make(pos, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "ignore", "desert_stone", room_id)
end
if ok then
return true, S("Pyramid generated at @1.", minetest.pos_to_string(pos))
else
return false, msg
end
end,
}
)

14
locale/de.txt Normal file
View File

@ -0,0 +1,14 @@
Cracked sandstone brick = Rissiger Sandsteinziegel
Fallen cracked sandstone brick = Gefallener rissiger Sandsteinziegel
Mummy spawn-egg = Mumien-Spawn-Ei
Mummy spawner = Mumien-Spawner
Sandstone with eye engraving = Sandstein mit Augengravur
Sandstone with man engraving = Sandstein mit Manngravur
Sandstone with sun engraving = Sandstein mit Sonnengravur
A mummy spawner causes hostile mummies to appear in its vicinity as long it exists. = Ein Mumien-Spawner lässt feindliche Mumien in seiner näheren Umgebung auftauchen, solange er existiert.
Can be used to create a hostile mummy. = Kann benutzt werden, um eine feindliche Mumie zu erzeugen (auch »spawnen« genannt).
Place the egg to create a mummy on this spot. Careful, it will probably attack immediately! = Platzieren Sie das Ei, um dort eine Mumie zu erzeugen. Vorsicht, sie wird wahrscheinlich sofort angreifen!
This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it. = Dieser Ziegel ist alt, porös und instabil und kann sich so gerade noch selbst stützen. Man sollte vorsichtig sein, ihn nicht zu belasten.
This old and porous brick fell to the ground. It does not hold itself anymore. = Dieser alte und poröse Ziegel fiel zu Boden und wird durch nichts mehr gestützt.
No more mummies! = Keine Mumien mehr!
Destroy a mummy spawner by digging. = Zerstören Sie einen Mumien-Spawner, indem Sie ihn graben.

View File

@ -1,25 +1,14 @@
# textdomain:tsm_pyramids Cracked sandstone brick =
Cracked Desert Sandstone Brick= Fallen cracked sandstone brick =
Cracked Sandstone Brick= Mummy spawn-egg =
Desert Sandstone with Ankh Engraving= Mummy spawner =
Desert Sandstone with Cactus Engraving= Sandstone with eye engraving =
Desert Sandstone with Scarab Engraving= Sandstone with man engraving =
Falling Cracked Sandstone Brick= Sandstone with sun engraving =
Falling Cracked Desert Sandstone Brick= A mummy spawner causes hostile mummies to appear in its vicinity as long it exists. =
Mummy= Can be used to create a hostile mummy. =
Mummy Spawn Egg= Place the egg to create a mummy on this spot. Careful, it will probably attack immediately! =
Mummy Spawner= This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it. =
Sandstone with Eye Engraving= This old and porous brick fell to the ground. It does not hold itself anymore. =
Sandstone with Man Engraving= No more mummies! =
Sandstone with Sun Engraving= Destroy a mummy spawner by digging. =
A mummy spawner causes hostile mummies to appear in its vicinity as long it exists.=
Can be used to create a hostile mummy.=
Place the egg to create a mummy on this spot. Careful, it will probably attack immediately!=
This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it.=
This old porous brick falls under its own weight.=
No more mummies!=
Destroy a mummy spawner by digging.=
Generate a pyramid=
[<room_type>]
Pyramid generated at @1.
Incorrect room type ID: @1

View File

@ -1,25 +0,0 @@
# textdomain:tsm_pyramids
Cracked Desert Sandstone Brick=Rissiger Wüstensandsteinziegel
Cracked Sandstone Brick=Rissiger Sandsteinziegel
Desert Sandstone with Ankh Engraving=Wüstensandstein mit Ankh-Gravur
Desert Sandstone with Cactus Engraving=Wüstensandstein mit Kaktusgravur
Desert Sandstone with Scarab Engraving=Wüstensandstein mit Skarabäusgravur
Falling Cracked Sandstone Brick=Fallender rissiger Sandsteinziegel
Falling Cracked Desert Sandstone Brick=Fallender rissiger Wüstensandsteinziegel
Mummy=Mumie
Mummy Spawn Egg=Mumien-Spawn-Ei
Mummy Spawner=Mumien-Spawner
Sandstone with Eye Engraving=Sandstein mit Augengravur
Sandstone with Man Engraving=Sandstein mit Manngravur
Sandstone with Sun Engraving=Sandstein mit Sonnengravur
A mummy spawner causes hostile mummies to appear in its vicinity as long it exists.=Ein Mumien-Spawner lässt feindliche Mumien in seiner näheren Umgebung auftauchen, solange er existiert.
Can be used to create a hostile mummy.=Kann benutzt werden, um eine feindliche Mumie zu erzeugen (auch »spawnen« genannt).
Place the egg to create a mummy on this spot. Careful, it will probably attack immediately!=Platzieren Sie das Ei, um dort eine Mumie zu erzeugen. Vorsicht, sie wird wahrscheinlich sofort angreifen!
This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it.=Dieser Ziegel ist alt, porös und instabil und kann sich so gerade noch selbst stützen. Man sollte vorsichtig sein, ihn nicht zu belasten.
This old porous brick falls under its own weight.=Dieser alte poröse Ziegel fällt unter seinem eigenem Gewicht.
No more mummies!=Keine Mumien mehr!
Destroy a mummy spawner by digging.=Zerstören Sie einen Mumien-Spawner, indem Sie ihn graben.
Generate a pyramid=Eine Pyramide erzeugen
[<room_type>]=[<Raumtyp>]
Pyramid generated at @1.=Pyramide erzeugt bei @1.
Incorrect room type ID: @1=Ungültige Raumtyp-ID: @1

View File

@ -1,4 +0,0 @@
name = tsm_pyramids
description = Pyramids with treasures! You can find them in deserts and sandstone deserts.
depends = default
optional_depends = farming, tnt, treasurer, doc_items, awards, cmi

313
mummy.lua
View File

@ -1,6 +1,10 @@
local S = minetest.get_translator("tsm_pyramids") -- Boilerplate to support localized strings if intllib mod is installed.
local S
local mod_cmi = minetest.get_modpath("cmi") ~= nil if minetest.get_modpath("intllib") then
S = intllib.Getter()
else
S = function(s) return s end
end
local mummy_walk_limit = 1 local mummy_walk_limit = 1
local mummy_chillaxin_speed = 1 local mummy_chillaxin_speed = 1
@ -18,7 +22,7 @@ local sound_normal = "mummy"
local sound_hit = "mummy_hurt" local sound_hit = "mummy_hurt"
local sound_dead = "mummy_death" local sound_dead = "mummy_death"
local spawner_check_range = 17 local spawner_range = 17
local spawner_max_mobs = 6 local spawner_max_mobs = 6
local function get_animations() local function get_animations()
@ -49,25 +53,27 @@ local ANIM_WALK_MINE = 5
local ANIM_MINE = 6 local ANIM_MINE = 6
local function hit(self) local function hit(self)
self.object:set_texture_mod("^tsm_pyramids_hit.png") local prop = {
minetest.after(0.4, function(self) mesh = mummy_mesh,
local prop = {textures = mummy_texture,} textures = {"tsm_pyramids_mummy.png^tsm_pyramids_hit.png"},
if self ~= nil and self.object ~= nil then }
self.object:set_texture_mod("") self.object:set_properties(prop)
end minetest.after(0.4, function()
end, self) local prop = {textures = mummy_texture,}
self.object:set_properties(prop)
end)
end end
local function mummy_update_visuals_def(self) local function mummy_update_visuals_def(self)
npc_anim = 0 -- Animation will be set further below immediately npc_anim = 0 -- Animation will be set further below immediately
local prop = { local prop = {
mesh = mummy_mesh,
textures = mummy_texture, textures = mummy_texture,
} }
self.object:set_properties(prop) self.object:set_properties(prop)
end end
local MUMMY_DEF = { local MUMMY_DEF = {
hp_max = mummy_hp,
physical = true, physical = true,
collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4}, collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4},
visual = "mesh", visual = "mesh",
@ -85,21 +91,15 @@ local MUMMY_DEF = {
jump_timer = 0, jump_timer = 0,
punch_timer = 0, punch_timer = 0,
sound_timer = 0, sound_timer = 0,
envdmg_timer = 0,
attacker = "", attacker = "",
attacking_timer = 0, attacking_timer = 0,
mob_name = "mummy"
-- CMI stuff
-- Track last cause of damage for cmi.notify_die
last_damage_cause = { type = "unknown" },
_cmi_is_mob = true,
description = S("Mummy"),
} }
local spawner_DEF = { local spawner_DEF = {
hp_max = 1, hp_max = 1,
physical = false, physical = true,
pointable = false, collisionbox = {0,0,0,0,0,0},
visual = "mesh", visual = "mesh",
visual_size = {x=3.3,y=3.3}, visual_size = {x=3.3,y=3.3},
mesh = mummy_mesh, mesh = mummy_mesh,
@ -107,23 +107,23 @@ local spawner_DEF = {
makes_footstep_sound = false, makes_footstep_sound = false,
timer = 0, timer = 0,
automatic_rotate = math.pi * 2.9, automatic_rotate = math.pi * 2.9,
m_name = "dummy"
} }
spawner_DEF.on_activate = function(self) spawner_DEF.on_activate = function(self)
mummy_update_visuals_def(self) mummy_update_visuals_def(self)
self.object:set_velocity({x=0, y=0, z=0}) self.object:setvelocity({x=0, y=0, z=0})
self.object:set_acceleration({x=0, y=0, z=0}) self.object:setacceleration({x=0, y=0, z=0})
self.object:set_armor_groups({immortal=1}) self.object:set_armor_groups({immortal=1})
end end
spawner_DEF.on_step = function(self, dtime) spawner_DEF.on_step = function(self, dtime)
self.timer = self.timer + 0.01 self.timer = self.timer + 0.01
local n = minetest.get_node_or_nil(self.object:get_pos()) local n = minetest.get_node_or_nil(self.object:getpos())
if self.timer > 1 then if self.timer > 1 then
if n and n.name and n.name ~= "tsm_pyramids:spawner_mummy" then if n and n.name and n.name ~= "tsm_pyramids:spawner_mummy" then
self.object:remove() self.object:remove()
return
end end
end end
end end
@ -132,38 +132,30 @@ spawner_DEF.on_punch = function(self, hitter)
end end
MUMMY_DEF.on_activate = function(self, staticdata, dtime_s) MUMMY_DEF.on_activate = function(self)
if mod_cmi then
cmi.notify_activate(self, dtime_s)
end
mummy_update_visuals_def(self) mummy_update_visuals_def(self)
self.anim = get_animations() self.anim = get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, mummy_animation_speed, mummy_animation_blend) self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, mummy_animation_speed, mummy_animation_blend)
self.npc_anim = ANIM_STAND self.npc_anim = ANIM_STAND
self.object:set_acceleration({x=0,y=-20,z=0})--20 self.object:setacceleration({x=0,y=-20,z=0})--20
self.state = 1 self.state = 1
self.object:set_hp(mummy_hp)
self.object:set_armor_groups({fleshy=130}) self.object:set_armor_groups({fleshy=130})
end end
MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mod_cmi then
cmi.notify_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
end
self.attacker = puncher self.attacker = puncher
if damage > 0 then
self.last_damage = {
type = "punch",
puncher = puncher,
}
end
if puncher ~= nil then if puncher ~= nil then
minetest.sound_play(sound_hit, {pos = self.object:get_pos(), loop = false, max_hear_distance = 10, gain = 0.4}, true) local sound = sound_hit
if self.object:get_hp() == 0 then sound = sound_dead end
minetest.sound_play(sound, {to_player = puncher:get_player_name(), loop = false, gain = 0.3})
if time_from_last_punch >= 0.45 then if time_from_last_punch >= 0.45 then
hit(self) hit(self)
self.direction = {x=self.object:get_velocity().x, y=self.object:get_velocity().y, z=self.object:get_velocity().z} self.direction = {x=self.object:getvelocity().x, y=self.object:getvelocity().y, z=self.object:getvelocity().z}
self.punch_timer = 0 self.punch_timer = 0
self.object:set_velocity({x=dir.x*mummy_chillaxin_speed,y=5,z=dir.z*mummy_chillaxin_speed}) self.object:setvelocity({x=dir.x*mummy_chillaxin_speed,y=5,z=dir.z*mummy_chillaxin_speed})
if self.state == 1 then if self.state == 1 then
self.state = 8 self.state = 8
elseif self.state >= 2 then elseif self.state >= 2 then
@ -171,81 +163,40 @@ MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabili
end end
end end
end end
if self.object:get_hp() == 0 then
local obj = minetest.env:add_item(self.object:getpos(), mummy_drop.." "..math.random(0,3))
end
end end
MUMMY_DEF.on_death = function(self, killer) local cnt1 = 0
minetest.sound_play(sound_dead, {pos = self.object:get_pos(), max_hear_distance = 10 , gain = 0.3}, true) local cnt2 = 0
-- Drop item on death
local count = math.random(0,3)
if count > 0 then
local pos = self.object:get_pos()
pos.y = pos.y + 1.0
minetest.add_item(pos, mummy_drop .. " " .. count)
end
if mod_cmi then
cmi.notify_die(self, self.last_damage)
end
end
MUMMY_DEF.on_step = function(self, dtime) MUMMY_DEF.on_step = function(self, dtime)
if mod_cmi then
cmi.notify_step(self, dtime)
end
self.timer = self.timer + 0.01 self.timer = self.timer + 0.01
self.turn_timer = self.turn_timer + 0.01 self.turn_timer = self.turn_timer + 0.01
self.jump_timer = self.jump_timer + 0.01 self.jump_timer = self.jump_timer + 0.01
self.punch_timer = self.punch_timer + 0.01 self.punch_timer = self.punch_timer + 0.01
self.attacking_timer = self.attacking_timer + 0.01 self.attacking_timer = self.attacking_timer + 0.01
self.sound_timer = self.sound_timer + dtime + 0.01 self.sound_timer = self.sound_timer + 0.01
local current_pos = self.object:get_pos() local current_pos = self.object:getpos()
local current_node = minetest.get_node(current_pos) local current_node = minetest.env:get_node(current_pos)
if self.time_passed == nil then if self.time_passed == nil then
self.time_passed = 0 self.time_passed = 0
end end
-- Environment damage if self.object:get_hp() == 0 then
local def = minetest.registered_nodes[current_node.name] minetest.sound_play(sound_dead, {pos = current_pos, max_hear_distance = 10 , gain = 0.3})
local dps = def.damage_per_second self.object:remove()
local dmg = 0
local dmg_node, dmg_pos
if dps ~= nil and dps > 0 then
dmg = dps
end end
-- Damage from node if current_node.name == "default:water_source" or current_node.name == "default:water_flowing" or current_node.name == "default:lava_source" or current_node.name == "default:lava_flowing" then
if dmg < 4 and (minetest.get_item_group(current_node.name, "water") ~= 0 or minetest.get_item_group(current_node.name, "lava") ~= 0) then self.sound_timer = self.sound_timer + dtime
dmg = 4 if self.sound_timer >= 0.8 then
end self.sound_timer = 0
-- Damage by suffocation self.object:set_hp(self.object:get_hp()-5)
if (def.walkable == nil or def.walkable == true) hit(self)
and (def.drowning == nil or def.drowning == 0) minetest.sound_play(sound_hit, {pos = current_pos, max_hear_distance = 10, gain = 0.3})
and (def.damage_per_second == nil or def.damage_per_second <= 0)
and (def.collision_box == nil or def.collision_box.type == "regular")
and (def.node_box == nil or def.node_box.type == "regular")
and (def.groups and def.groups.disable_suffocation ~= 1) then
dmg = dmg + 1
end
self.envdmg_timer = self.envdmg_timer + dtime
if dmg > 0 then
if self.envdmg_timer >= 1 then
self.envdmg_timer = 0
self.object:set_hp(self.object:get_hp()-dmg)
self.last_damage = {
type = "environment",
pos = current_pos,
node = current_node,
}
if self.object:get_hp() <= 0 then
if self.on_death then
self.on_death(self)
end
self.object:remove()
return
else
hit(self)
self.sound_timer = 0
minetest.sound_play(sound_hit, {pos = current_pos, max_hear_distance = 10, gain = 0.4}, true)
end
end end
else else
self.time_passed = 0 self.time_passed = 0
@ -263,7 +214,7 @@ MUMMY_DEF.on_step = function(self, dtime)
--play sound --play sound
if self.sound_timer > math.random(5,35) then if self.sound_timer > math.random(5,35) then
minetest.sound_play(sound_normal, {pos = current_pos, max_hear_distance = 10, gain = 0.2}, true) minetest.sound_play(sound_normal, {pos = current_pos, max_hear_distance = 10, gain = 0.2})
self.sound_timer = 0 self.sound_timer = 0
end end
@ -271,10 +222,10 @@ MUMMY_DEF.on_step = function(self, dtime)
if self.state >= 8 then if self.state >= 8 then
if self.punch_timer > 0.15 then if self.punch_timer > 0.15 then
if self.state == 9 then if self.state == 9 then
self.object:set_velocity({x=self.direction.x*mummy_chillaxin_speed,y=-20,z=self.direction.z*mummy_chillaxin_speed}) self.object:setvelocity({x=self.direction.x*mummy_chillaxin_speed,y=-20,z=self.direction.z*mummy_chillaxin_speed})
self.state = 2 self.state = 2
elseif self.state == 8 then elseif self.state == 8 then
self.object:set_velocity({x=0,y=-20,z=0}) self.object:setvelocity({x=0,y=-20,z=0})
self.state = 1 self.state = 1
end end
end end
@ -284,29 +235,29 @@ MUMMY_DEF.on_step = function(self, dtime)
if self.state == 1 then if self.state == 1 then
self.yawwer = true self.yawwer = true
self.attacker = "" self.attacker = ""
for _,object in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 4)) do for _,object in ipairs(minetest.env:get_objects_inside_radius(self.object:getpos(), 4)) do
if object:is_player() then if object:is_player() then
self.yawwer = false self.yawwer = false
local NPC = self.object:get_pos() local NPC = self.object:getpos()
local PLAYER = object:get_pos() local PLAYER = object:getpos()
self.vec = {x=PLAYER.x-NPC.x, y=PLAYER.y-NPC.y, z=PLAYER.z-NPC.z} self.vec = {x=PLAYER.x-NPC.x, y=PLAYER.y-NPC.y, z=PLAYER.z-NPC.z}
self.yaw = math.atan(self.vec.z/self.vec.x)+math.pi^2 self.yaw = math.atan(self.vec.z/self.vec.x)+math.pi^2
if PLAYER.x > NPC.x then if PLAYER.x > NPC.x then
self.yaw = self.yaw + math.pi self.yaw = self.yaw + math.pi
end end
self.yaw = self.yaw - 2 self.yaw = self.yaw - 2
self.object:set_yaw(self.yaw) self.object:setyaw(self.yaw)
self.attacker = object self.attacker = object
end end
end end
if self.attacker == "" and self.turn_timer > math.random(1,4) then if self.attacker == "" and self.turn_timer > math.random(1,4) then
self.yaw = 360 * math.random() self.yaw = 360 * math.random()
self.object:set_yaw(self.yaw) self.object:setyaw(self.yaw)
self.turn_timer = 0 self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)} self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end end
self.object:set_velocity({x=0,y=self.object:get_velocity().y,z=0}) self.object:setvelocity({x=0,y=self.object:getvelocity().y,z=0})
if self.npc_anim ~= ANIM_STAND then if self.npc_anim ~= ANIM_STAND then
self.anim = get_animations() self.anim = get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, mummy_animation_speed, mummy_animation_blend) self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, mummy_animation_speed, mummy_animation_blend)
@ -321,11 +272,11 @@ MUMMY_DEF.on_step = function(self, dtime)
if self.state == 2 then if self.state == 2 then
if self.direction ~= nil then if self.direction ~= nil then
self.object:set_velocity({x=self.direction.x*mummy_chillaxin_speed,y=self.object:get_velocity().y,z=self.direction.z*mummy_chillaxin_speed}) self.object:setvelocity({x=self.direction.x*mummy_chillaxin_speed,y=self.object:getvelocity().y,z=self.direction.z*mummy_chillaxin_speed})
end end
if self.turn_timer > math.random(1,4) and not self.attacker then if self.turn_timer > math.random(1,4) and not self.attacker then
self.yaw = 360 * math.random() self.yaw = 360 * math.random()
self.object:set_yaw(self.yaw) self.object:setyaw(self.yaw)
self.turn_timer = 0 self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)} self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end end
@ -335,9 +286,9 @@ MUMMY_DEF.on_step = function(self, dtime)
self.npc_anim = ANIM_WALK self.npc_anim = ANIM_WALK
end end
if self.attacker ~= "" and minetest.settings:get_bool("enable_damage") then if self.attacker ~= "" and minetest.setting_getbool("enable_damage") then
local s = self.object:get_pos() local s = self.object:getpos()
local p = self.attacker:get_pos() local p = self.attacker:getpos()
if (s ~= nil and p ~= nil) then if (s ~= nil and p ~= nil) then
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
@ -360,42 +311,25 @@ minetest.register_entity("tsm_pyramids:mummy_spawner", spawner_DEF)
--spawn-egg/spawner --spawn-egg/spawner
minetest.register_craftitem("tsm_pyramids:spawn_egg", { minetest.register_craftitem("tsm_pyramids:spawn_egg", {
description = S("Mummy Spawn Egg"), description = S("Mummy spawn-egg"),
_doc_items_longdesc = S("Can be used to create a hostile mummy."), _doc_items_longdesc = S("Can be used to create a hostile mummy."),
_doc_items_usagehelp = S("Place the egg to create a mummy on this spot. Careful, it will probably attack immediately!"), _doc_items_usagehelp = S("Place the egg to create a mummy on this spot. Careful, it will probably attack immediately!"),
inventory_image = "tsm_pyramids_mummy_egg.png", inventory_image = "tsm_pyramids_mummy_egg.png",
liquids_pointable = false, liquids_pointable = false,
stack_max = 99, stack_max = 99,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then if pointed_thing.type == "node" then
minetest.env:add_entity(pointed_thing.above,"tsm_pyramids:mummy")
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack return itemstack
end end
-- am I clicking on something with existing on_rightclick function?
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
minetest.add_entity(pointed_thing.above,"tsm_pyramids:mummy")
if not minetest.settings:get_bool("creative_mode") then
itemstack:take_item()
end
return itemstack
end, end,
}) })
-- Spawn a mummy at position function pyramids.spawn_mummy (pos, number)
function tsm_pyramids.spawn_mummy_at(pos, number) for i=0,number do
local node = minetest.get_node(pos) minetest.env:add_entity(pos,"tsm_pyramids:mummy")
if node.name ~= "air" then
return
end
for _=1, number do
minetest.add_entity(pos,"tsm_pyramids:mummy")
end end
end end
@ -407,7 +341,7 @@ else
end end
minetest.register_node("tsm_pyramids:spawner_mummy", { minetest.register_node("tsm_pyramids:spawner_mummy", {
description = S("Mummy Spawner"), description = S("Mummy spawner"),
_doc_items_longdesc = S("A mummy spawner causes hostile mummies to appear in its vicinity as long it exists."), _doc_items_longdesc = S("A mummy spawner causes hostile mummies to appear in its vicinity as long it exists."),
paramtype = "light", paramtype = "light",
tiles = {"tsm_pyramids_spawner.png"}, tiles = {"tsm_pyramids_spawner.png"},
@ -417,12 +351,12 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
drop = "", drop = "",
on_construct = function(pos) on_construct = function(pos)
pos.y = pos.y - 0.28 pos.y = pos.y - 0.28
minetest.add_entity(pos,"tsm_pyramids:mummy_spawner") minetest.env:add_entity(pos,"tsm_pyramids:mummy_spawner")
end, end,
on_destruct = function(pos) on_destruct = function(pos)
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, 1)) do
if not obj:is_player() then if not obj:is_player() then
if obj ~= nil and obj:get_luaentity().name == "tsm_pyramids:mummy_spawner" then if obj ~= nil and obj:get_luaentity().m_name == "dummy" then
obj:remove() obj:remove()
end end
end end
@ -430,80 +364,31 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
end, end,
sounds = spawnersounds, sounds = spawnersounds,
}) })
if not minetest.setting_getbool("only_peaceful_mobs") then
-- Attempt to spawn a mummy at a random appropriate position around pos.
-- Criteria:
-- * Must be close to pos
-- * Not in sunlight
-- * Must be air on top of a non-air block
-- * No more than 6 mummies in area
-- * Player must be near is player_near_required is true
function tsm_pyramids.attempt_mummy_spawn(pos, player_near_required)
local player_near = false
local mobs = 0
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, spawner_check_range)) do
if obj:is_player() then
player_near = true
else
if obj:get_luaentity() and obj:get_luaentity().name == "tsm_pyramids:mummy" then
mobs = mobs + 1
end
end
end
if player_near or (not player_near_required) then
if mobs < spawner_max_mobs then
local offset = {x=5,y=2,z=5}
local nposses = minetest.find_nodes_in_area(vector.subtract(pos, offset), vector.add(pos,offset), "air")
local tries = math.min(6, #nposses)
for i=1, tries do
local r = math.random(1, #nposses)
local npos = nposses[r]
-- Check if mummy has 2 nodes of free space
local two_space = false
-- Check if mummy has something to walk on
local footing = false
-- Find the lowest node
for y=-1, -5, -1 do
npos.y = npos.y - 1
local below = minetest.get_node(npos)
if minetest.registered_items[below.name].liquidtype ~= "none" then
break
end
if below.name ~= "air" then
if y < -1 then
two_space = true
end
npos.y = npos.y + 1
footing = true
break
end
end
local light = minetest.get_node_light(npos, 0.5)
if not two_space then
local above = minetest.get_node({x=npos.x, y=npos.y+1, z=npos.z})
if above.name == "air" then
two_space = true
end
end
if footing and two_space and light < 15 then
tsm_pyramids.spawn_mummy_at(npos, 1)
break
else
table.remove(nposses, r)
end
end
end
end
end
if not minetest.settings:get_bool("only_peaceful_mobs") then
minetest.register_abm({ minetest.register_abm({
nodenames = {"tsm_pyramids:spawner_mummy"}, nodenames = {"tsm_pyramids:spawner_mummy"},
interval = 2.0, interval = 2.0,
chance = 20, chance = 20,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
tsm_pyramids.attempt_mummy_spawn(pos, true) local player_near = false
end, local mobs = 0
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, spawner_range)) do
if obj:is_player() then
player_near = true
else
if obj:get_luaentity() and obj:get_luaentity().mob_name == "mummy" then
mobs = mobs + 1
end
end
end
if player_near then
if mobs < spawner_max_mobs then
pos.x = pos.x+1
local p = minetest.find_node_near(pos, 5, {"air"})
minetest.env:add_entity(p,"tsm_pyramids:mummy")
end
end
end
}) })
end end

189
nodes.lua
View File

@ -1,126 +1,117 @@
local S = minetest.get_translator("tsm_pyramids") -- Boilerplate to support localized strings if intllib mod is installed.
local S
if minetest.get_modpath("intllib") then
S = intllib.Getter()
else
S = function(s) return s end
end
local img = { local desc = {S("Sandstone with eye engraving"), S("Sandstone with man engraving"), S("Sandstone with sun engraving")}
"eye", "men", "sun", local img = {"eye", "men", "sun"}
"ankh", "scarab", "cactus"
}
local desc = {
S("Sandstone with Eye Engraving"), S("Sandstone with Man Engraving"), S("Sandstone with Sun Engraving"),
S("Desert Sandstone with Ankh Engraving"), S("Desert Sandstone with Scarab Engraving"), S("Desert Sandstone with Cactus Engraving")
}
local decodesc = "" local decodesc = ""
if minetest.get_modpath("doc_items") then if minetest.get_modpath("doc_items") then
decodesc = doc.sub.items.temp.deco decodesc = doc.sub.items.temp.deco
end end
for i=1, #img do for i=1,3 do
local sandstone_img, basenode
if i > 3 then
sandstone_img = "default_desert_sandstone.png"
basenode = "default:desert_sandstone"
else
sandstone_img = "default_sandstone.png"
basenode = "default:sandstone"
end
minetest.register_node("tsm_pyramids:deco_stone"..i, { minetest.register_node("tsm_pyramids:deco_stone"..i, {
description = desc[i], description = desc[i],
_doc_items_longdesc = decodesc, _doc_items_longdesc = decodesc,
tiles = {"default_sandstone.png", "default_sandstone.png", "default_sandstone.png^tsm_pyramids_"..img[i]..".png"},
is_ground_content = false, is_ground_content = false,
tiles = {sandstone_img, sandstone_img, sandstone_img.."^tsm_pyramids_"..img[i]..".png"}, groups = {unbreakable=1},
groups = minetest.registered_nodes[basenode].groups, sounds = default.node_sound_stone_defaults(),
sounds = minetest.registered_nodes[basenode].sounds,
}) })
end end
local trap_on_timer = function(pos, elapsed) local trap_on_timer = function (pos, elapsed)
local n = minetest.get_node(pos) local objs = minetest.env:get_objects_inside_radius(pos, 2)
if not (n and n.name) then
return true
end
-- Drop trap stone when player is nearby
local objs = minetest.get_objects_inside_radius(pos, 2)
for i, obj in pairs(objs) do for i, obj in pairs(objs) do
if obj:is_player() then if obj:is_player() then
if minetest.registered_nodes[n.name]._tsm_pyramids_crack and minetest.registered_nodes[n.name]._tsm_pyramids_crack < 2 then local n = minetest.get_node(pos)
-- 70% chance to ignore player to make the time of falling less predictable if n and n.name then
if math.random(1, 10) >= 3 then if minetest.registered_nodes[n.name]._tsm_pyramids_crack and minetest.registered_nodes[n.name]._tsm_pyramids_crack < 2 then
return true
end
if n.name == "tsm_pyramids:trap" then
minetest.set_node(pos, {name="tsm_pyramids:trap_2"}) minetest.set_node(pos, {name="tsm_pyramids:trap_2"})
minetest.check_for_falling(pos) minetest.check_for_falling(pos)
elseif n.name == "tsm_pyramids:desert_trap" then
minetest.set_node(pos, {name="tsm_pyramids:desert_trap_2"})
minetest.check_for_falling(pos)
end end
return true
end end
end end
end end
return true return true
end end
local register_trap_stone = function(basename, desc_normal, desc_falling, base_tile, drop) minetest.register_node("tsm_pyramids:trap", {
minetest.register_node("tsm_pyramids:"..basename, { description = S("Cracked sandstone brick"),
description = desc_normal, _doc_items_longdesc = S("This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it."),
_doc_items_longdesc = S("This brick is old, porous and unstable and is barely able to hold itself. One should be careful not to disturb it."), tiles = {"default_sandstone_brick.png^tsm_pyramids_crack.png"},
tiles = { base_tile .. "^tsm_pyramids_crack.png" }, is_ground_content = false,
is_ground_content = false, groups = {crumbly=3,cracky=3},
groups = {crumbly=3,cracky=3}, sounds = default.node_sound_stone_defaults(),
sounds = default.node_sound_stone_defaults(), on_construct = function(pos)
on_construct = function(pos) minetest.env:get_node_timer(pos):start(0.1)
minetest.get_node_timer(pos):start(0.1) end,
end, _tsm_pyramids_crack = 1,
_tsm_pyramids_crack = 1, on_timer = trap_on_timer,
on_timer = trap_on_timer, drop = "",
drop = drop,
})
minetest.register_node("tsm_pyramids:"..basename.."_2", {
description = desc_falling,
_doc_items_longdesc = S("This old porous brick falls under its own weight."),
tiles = { base_tile .. "^tsm_pyramids_crack2.png" },
is_ground_content = false,
groups = {crumbly=3,cracky=3,falling_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_stone_defaults(),
drop = drop,
})
end
register_trap_stone("trap",
S("Cracked Sandstone Brick"), S("Falling Cracked Sandstone Brick"),
"default_sandstone_brick.png",
{ items = { { items = { "default:sand" }, rarity = 1 }, { items = { "default:sand" }, rarity = 2 }, } })
register_trap_stone("desert_trap",
S("Cracked Desert Sandstone Brick"), S("Falling Cracked Desert Sandstone Brick"),
"default_desert_sandstone_brick.png",
{ items = { { items = { "default:desert_sand" }, rarity = 1 }, { items = { "default:desert_sand" }, rarity = 2 }, } })
local chest = minetest.registered_nodes["default:chest"]
local def_on_rightclick = chest.on_rightclick
local def_on_timer = chest.on_timer
minetest.override_item(
"default:chest",
{
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if minetest.get_meta(pos):get_string("tsm_pyramids:stype") ~= "" then
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1800) -- remplissages des coffres toutes les 30 minutes
end
end
return def_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
end,
on_timer = function(pos, elapsed)
if minetest.get_meta(pos):get_string("tsm_pyramids:stype") ~= "" then
minetest.log("action", "[DEBUG] chest refilling")
tsm_pyramids.fill_chest(pos)
return false
else
if def_on_timer then return def_on_timer(pos, elapsed) else return false end
end
end,
}) })
minetest.register_alias("tsm_pyramids:chest", "default:chest") minetest.register_node("tsm_pyramids:trap_2", {
description = S("Fallen cracked sandstone brick"),
_doc_items_longdesc = S("This old and porous brick fell to the ground. It does not hold itself anymore."),
tiles = {"default_sandstone_brick.png^tsm_pyramids_crack.png^[transformR90"},
is_ground_content = false,
groups = {crumbly=3,cracky=3,falling_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_stone_defaults(),
drop = "",
})
local function get_chest_formspec(pos)
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
local formspec =
"size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"listring[nodemeta:" .. spos .. ";main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
return formspec
end
local chestdef = minetest.registered_nodes["default:chest"]
minetest.register_node(
"tsm_pyramids:chest", {
description = "tsm_pyramids Chest auto refilled",
tiles = chestdef.tiles,
stack_max = 1000,
paramtype2 = "facedir",
is_ground_content = false,
on_construct = function(pos)
chestdef.on_construct(pos)
minetest.get_node_timer(pos):start(pyramids.max_time)
pyramids.fill_chest(pos)
end,
on_metadata_inventory_move = chestdef.on_metadata_inventory_move,
on_metadata_inventory_put = chestdef.on_metadata_inventory_put,
on_metadata_inventory_take = chestdef.on_metadata_inventory_take,
groups = {unbreakable = 1, not_in_creative_inventory = 1},
on_timer = function(pos, elapsed)
pyramids.fill_chest(pos)
return true
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if not default.can_interact_with_node(clicker, pos) then
return itemstack
end
minetest.after(
0.2,
minetest.show_formspec,
clicker:get_player_name(),
"default:chest", get_chest_formspec(pos))
end,
})

1233
room.lua

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B