Compare commits

..

No commits in common. "main" and "desert_stone" have entirely different histories.

17 changed files with 755 additions and 1421 deletions

23
.gitattributes vendored
View File

@ -1,5 +1,22 @@
# Improve language detection of repo by ignoring x files.
*.x -linguist-detectable
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

215
.gitignore vendored Normal file
View File

@ -0,0 +1,215 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg

View File

@ -1,2 +0,0 @@
Wuzzy <Wuzzy@disroot.org> <Wuzzy2@mail.ru>
Wuzzy <Wuzzy@disroot.org> <almikes@aol.com>

View File

@ -1,56 +1,41 @@
# minetest-mod-tsm_pyramids
# Pyramids (with Treasurer support) [`tsm_pyramids`]
BUILDINGS of pyramids with treasures!
## Information
Constructions of pyramids with treasures! You can find them in deserts and sandstone deserts.
* Version: 0.7
## Description
This is a mod for Minetest Game which adds randomly spawned pyramids in deserts and
sandstone deserts. The pyramids are very rare and contain chests with stuff.
Also there are mummies inside, which attack the player if found in their radius.
![screenshot.png](screenshot.png)
## Technical info
This mod must be named `tsm_pyramids` and is a forked improved version of wuzzy one,
that is a fork of the old `pyramids` mod by BlockMen and intended to be a direct
## Historic notes
This mod is a fork of the old `pyramids` mod by BlockMen and intended to be a direct
(but unofficial) successor of it.
We recommended to use the modernized `pyramids` mod at minenux or oldcoder continuation,
due to the low availability of the developer to solve problems and his inclination towards
the obsolescence of minetests and does not help to solve any problem. This mod fork
is fully compatible with any engine version from 0.4.16 to 5.9.0 version.
The mod will override the default chest and this fork specially will refill the chests
at every pyramid created. Each pyramid will have a special mob named mummy, and the blocks
used in the pyramids are only few used (those with pictures).
The mod will register alias if the older mod "pyramid" is detected.
The mod provides a command, `spawnpyramid` will created a new pyramid and it receives
an optional argumwent as room type, there are 3 rooms types. Such command requirest
the server privilegie to use it.
## Licensing
This program is free software. It comes without any warranty, to
the extent permitted by applicable law.
* Source code and textures
* [MIT License](https://mit-license.org/)
* (c) Copyright BlockMen (2013)
* Mummy model
* MIT License
* (c) Copyright Pavel\_S (2013)
* Textures
* `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_sun.png` by bas080, CC-BY-SA 3.0
* Sounds from ([freesound.org](https://freesound.org)):
* `mummy.1.ogg` by Raventhornn, [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
* `mummy.2.ogg` by Raventhornn, CC0
* `mummy_hurt.1.ogg` by Under7dude, CC0
* `mummy_death.1.ogg` by scorpion67890 (modified by Wuzzy), CC0
### Source code and textures
* [MIT License](https://mit-license.org/)
* (c) Copyright BlockMen (2013)
### Mummy model
* MIT License
* (c) Copyright Pavel\_S (2013)
### Textures
* `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_sun.png` by bas080, CC-BY-SA 3.0
* All other: BlockMen (MIT License)
### Sounds
The authors are ([freesound.org](https://freesound.org)):
* `mummy.1.ogg` by Raventhornn, [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
* `mummy.2.ogg` by Raventhornn, CC0
* `mummy_hurt.1.ogg` by Under7dude, CC0
* `mummy_death.1.ogg` by scorpion67890 (modified by Wuzzy), CC0

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

View File

@ -1,7 +0,0 @@
default
tnt
farming
treasurer?
doc_items?
awards?
cmi?

View File

@ -1 +0,0 @@
BUILDINGS of pyramids with treasures! You can find them in deserts and sandstone deserts.

508
init.lua
View File

@ -1,160 +1,77 @@
local modpath = minetest.get_current_modname() or "tsm_pyramids"
-- support for i18n
local S
-- Intllib or native translator
if minetest.get_translator ~= nil then
S = minetest.get_translator(modpath)
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
-- Pyramid width (must be an odd number)
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 = 1
-- Maximun spawn height
local PYRA_MAX_Y = 1000
-- minetest 5.x check
local is_50 = minetest.has_feature("object_use_texture_alpha")
-- minetest 5.5 check
local is_54 = minetest.has_feature("use_texture_alpha_string_modes") or nil
-- get mapgen cos perlin noise must match mapgen choice and nodes
local mgname = minetest.get_mapgen_setting("mg_name") or "v7"
-- also perlin noise must be in sync for simplev7 mod
local mgsimp = minetest.get_modpath("simplev7") or nil
local S = minetest.get_translator("tsm_pyramids")
tsm_pyramids = {}
tsm_pyramids.is_50 = is_50
tsm_pyramids.is_54 = is_54
tsm_pyramids.S = S
tsm_pyramids.perlin1 = nil -- perlin noise buffer, make it global cos we need to acess in 5.0 after load all the rest of mods
dofile(minetest.get_modpath(modpath).."/mummy.lua")
dofile(minetest.get_modpath(modpath).."/nodes.lua")
dofile(minetest.get_modpath(modpath).."/room.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/mummy.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/nodes.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/room.lua")
local mg_name = minetest.get_mapgen_setting("mg_name")
local chest_stuff = {
normal = {
{name="default:steel_ingot", max = 3},
{name="default:copper_ingot", max = 3},
{name="default:gold_ingot", max = 2},
{name="default:diamond", max = 1},
{name="default:pick_steel", 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},
},
{name="default:apple", max = 3},
{name="default:steel_ingot", max = 3},
{name="default:copper_ingot", max = 3},
{name="default:gold_ingot", max = 2},
{name="default:diamond", max = 1},
{name="default:pick_steel", max = 1},
{name="default:pick_diamond", max = 1},
{name="default:papyrus", max = 9},
}
if minetest.get_modpath("farming") then
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})
table.insert(chest_stuff, {name="farming:bread", max = 3})
table.insert(chest_stuff, {name="farming:cotton", max = 8})
else
table.insert(chest_stuff.normal, {name="farming:apple", max = 8})
table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
table.insert(chest_stuff, {name="farming:apple", max = 8})
table.insert(chest_stuff, {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})
table.insert(chest_stuff, {name="tnt:gunpowder", max = 6})
else
table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
table.insert(chest_stuff, {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 meta = minetest.get_meta(pos)
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 inv = meta:get_inventory()
inv:set_size("main", 8*4)
local stacks = {}
-- Fill with sand in sand-flooded pyramids
if meta:get_int("tsm_pyramids:sanded") == 1 or flood_sand then
table.insert(stacks, {name=sand, count = math.random(1,32)})
function tsm_pyramids.fill_chest(pos, stype, flood_sand)
minetest.after(2, function()
local sand = "default:sand"
if stype == "desert_sandstone" or stype == "desert_stone" then
sand = "default:desert_sand"
end
-- Add treasures
if math.random(1,100) <= treasure_chance then
if minetest.get_modpath("treasurer") ~= nil then
stacks = treasurer.select_random_treasures(3,1,5,{"minetool", "food", "crafting_component"})
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
local n = minetest.get_node(pos)
if n and n.name and n.name == "default:chest" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
local stacks = {}
-- Fill with sand in sand-flooded pyramids
if flood_sand then
table.insert(stacks, {name=sand, count = math.random(1,32)})
end
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])
-- Add treasures
if math.random(1,10) >= 7 then
if minetest.get_modpath("treasurer") ~= nil then
stacks = treasurer.select_random_treasures(3,7,9,{"minetool", "food", "crafting_component"})
else
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
end
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
end
return treasure_added
end)
end
local function add_spawner(pos, mummy_offset)
minetest.set_node(pos, {name="tsm_pyramids:spawner_mummy"})
if not minetest.settings:get_bool("only_peaceful_mobs") then
for i=1,2 do
tsm_pyramids.attempt_mummy_spawn(pos, false)
end
end
if not minetest.settings:get_bool("only_peaceful_mobs") then tsm_pyramids.spawn_mummy(vector.add(pos, mummy_offset),2) end
end
local function can_replace(pos)
@ -182,124 +99,82 @@ local function make_foundation_part(pos, set_to_stone)
end
end
local function make_entrance(pos, rot, brick, sand, flood_sand)
local roffset_arr = {
{ x=0, y=0, z=1 }, -- front
{ x=-1, y=0, z=0 }, -- left
{ x=0, y=0, z=-1 }, -- back
{ x=1, y=0, z=0 }, -- right
}
local roffset = roffset_arr[rot + 1]
local way
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 function make_entrance(pos, brick, sand, flood_sand)
local gang = {x=pos.x+10,y=pos.y, z=pos.z}
local max_sand_height = math.random(1,3)
for ie=0,6,1 do
for iz=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})
if flood_sand and sand ~= "ignore" and iy <= sand_height and iz >= 3 then
minetest.set_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz}, {name=sand})
else
minetest.remove_node(way_dir)
minetest.remove_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz})
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
if iz >=3 and iy == 3 then
minetest.set_node({x=gang.x,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
minetest.set_node({x=gang.x+1,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
minetest.set_node({x=gang.x+2,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
end
end
end
end
local wa_bulk_set_node
if not minetest.bulk_set_node then
wa_bulk_set_node = function(poslist, nodename)
for _, pos in ipairs(poslist) do
minetest.set_node(pos, nodename)
end
end
else
wa_bulk_set_node = minetest.bulk_set_node
end
local function make_pyramid(pos, brick, sandstone, stone, sand)
local set_to_brick = {}
local set_to_sand = {}
local set_to_stone = {}
-- Build pyramid
for iy=0,math.random(10,PYRA_Wh),1 do
for ix=iy,PYRA_W-1-iy,1 do
for iz=iy,PYRA_W-1-iy,1 do
for iy=0,math.random(10,11),1 do
for ix=iy,22-iy,1 do
for iz=iy,22-iy,1 do
if iy < 1 then
make_foundation_part({x=pos.x+ix,y=pos.y,z=pos.z+iz}, set_to_stone)
end
table.insert(set_to_brick, {x=pos.x+ix,y=pos.y+iy,z=pos.z+iz})
if sand ~= "ignore" then
for yy=1,10-iy,1 do
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
table.insert(set_to_sand, {x=pos.x+ix,y=pos.y+iy+yy,z=pos.z+iz})
end
end
end
end
end
end
wa_bulk_set_node(set_to_stone, {name=stone})
wa_bulk_set_node(set_to_brick, {name=brick})
minetest.bulk_set_node(set_to_stone , {name=stone})
minetest.bulk_set_node(set_to_brick, {name=brick})
if sand ~= "ignore" then
minetest.bulk_set_node(set_to_sand, {name=sand})
end
end
local function make(pos, brick, sandstone, stone, sand, ptype, room_id)
local bpos = table.copy(pos)
-- Build pyramid
make_pyramid(bpos, brick, sandstone, stone, sand)
local rot = math.random(0, 3)
make_pyramid(pos, brick, sandstone, stone, sand)
-- Build room
local ok, msg, flood_sand = tsm_pyramids.make_room(bpos, ptype, room_id, rot)
local ok, msg, flood_sand = tsm_pyramids.make_room(pos, ptype, room_id)
-- Place mummy spawner
local r = math.random(1,3)
-- 4 possible spawner positions
local spawner_posses = {
if r == 1 then
-- 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}},
add_spawner({x=pos.x+11,y=pos.y+2, z=pos.z+17}, {x=0, y=0, z=-2})
elseif r == 2 then
-- 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])
add_spawner({x=pos.x+17,y=pos.y+2, z=pos.z+11}, {x=-2, y=0, z=0})
else
-- left
add_spawner({x=pos.x+5,y=pos.y+2, z=pos.z+11}, {x=2, y=0, z=0})
end
-- Build entrance
make_entrance(bpos, rot, brick, sand, flood_sand)
make_entrance({x=pos.x,y=pos.y, z=pos.z}, brick, sand, flood_sand)
-- Done
minetest.log("action", "[tsm_pyramids] Created pyramid at "..minetest.pos_to_string(bpos)..".")
minetest.log("action", "Created pyramid at ("..pos.x..","..pos.y..","..pos.z..")")
return ok, msg
end
local perl1 -- perlin noise / it depends of the mapgen, upstream do not set property
if mgname == "v6" then perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} end -- Values should match minetest mapgen V6 desert noise.
if mgname == "v7p" then perl1 = {SEED1 = 9130, OCTA1 = 1, PERS1 = 0.5, SCAL1 = 25} end -- The multicraft v7plus desert noise are not knowwed.
if mgname == "v7" then perl1 = {SEED1 = 9130, OCTA1 = 1, PERS1 = 0.5, SCAL1 = 25} end -- Values should match minetest mapgen V7 desert noise.
if mgsimp ~= nil then perl1 = {SEED1 = 5349, OCTA1 = 3, PERS1 = 0.7, SCAL1 = 500} end -- must match to find some desert sand
-- get_perlin can only call it after the environment is created so wrap code for older engines into minetest.after(0, ...) and only call it once
if tsm_pyramids.is_50 then
tsm_pyramids.perlin1 = minetest.get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
else
tsm_pyramids.perlin1 = PerlinNoise(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
end
local perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} -- Values should match minetest mapgen V6 desert noise.
local perlin1
local function hlp_fnct(pos, name)
local n = minetest.get_node_or_nil(pos)
@ -309,181 +184,95 @@ local function hlp_fnct(pos, name)
return false
end
end
local function ground(pos, old)
local p2 = table.copy(pos)
local p2 = pos
while hlp_fnct(p2, "air") do
p2.y = p2.y -1
end
if p2.y < old.y then
return {x=old.x, y=p2.y, z=old.z}
return p2
else
return old
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
local sands = {"default:sand", "default:desert_sand", "default:desert_stone"}
local p2
local psand = {}
local sand
local cnt = 0
local sand_cnt_max = 0
local sand_cnt_max_id
-- Look for sand or desert stone to place the pyramid on
for s=1, #sands do
cnt = 0
local sand_cnt = 0
sand = sands[s]
psand[s] = minetest.find_node_near(mpos, 25, sand)
while cnt < 5 do
cnt = cnt+1
mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
local spos = minetest.find_node_near(mpos, 25, sand)
if spos ~= nil then
sand_cnt = sand_cnt + 1
if psand[s] == nil then
psand[s] = spos
end
end
if sand_cnt > sand_cnt_max then
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 or maxp.y > PYRA_MAX_Y then return end
-- TODO: Use Minetests pseudo-random tools
if maxp.y < 0 then return end
math.randomseed(seed)
--[[ 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 than 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 = nil
if not tsm_pyramids.perlin1 or tsm_pyramids.perlin1 == nil then
if tsm_pyramids.is_50 then
tsm_pyramids.perlin1 = minetest.get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
noise1 = tsm_pyramids.perlin1:get_2d({x=minp.x,y=minp.y})
else
tsm_pyramids.perlin1 = PerlinNoise(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
noise1 = tsm_pyramids.perlin1:get2d({x=minp.x,y=minp.y})
end
end
if not tsm_pyramids.perlin1 or tsm_pyramids.perlin1 == nil or not noise1 or noise1 == nil then
return
if not perlin1 then
perlin1 = minetest.get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
end
local noise1 = perlin1:get_2d({x=minp.x,y=minp.y})--,z=minp.z})
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)
local mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
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 or p2.y > PYRA_MAX_Y then
minetest.log("info", "[tsm_pyramids] Pyramid not placed, too deep or too high. 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)
local sands = {"default:sand", "default:desert_sand", "default:desert_stone"}
local p2
local psand = {}
local sand
local cnt = 0
local cnt_min = 100
for s=1, #sands do
cnt = 0
sand = sands[s]
psand[s] = minetest.find_node_near(mpos, 25, sand)
while psand == nil and cnt < 5 do
cnt = cnt+1
mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
psand[s] = minetest.find_node_near(mpos, 25, sand)
end
if psand[s] ~= nil then
if cnt < cnt_min then
cnt_min = cnt
p2 = psand[s]
end
end
end
-- Random bonus sinking
p2.y = math.max(p2.y - math.random(0,3), PYRA_MIN_Y)
if p2 == nil then return end
if p2.y < 0 then return end
-- 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))
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, {"default:sandstonebrick"}) ~= nil or
minetest.find_node_near(p2, 52, {"default:desert_sandstone_brick"}) ~= nil then
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))
if math.random(0,10) > 7 then
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")
minetest.after(0.8, 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")
minetest.after(0.8, 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")
minetest.after(0.8, make, p2, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "default:desert_sand", "desert_stone")
end
end
end)
@ -497,6 +286,9 @@ if minetest.get_modpath("pyramids") == nil then
minetest.register_alias("pyramids:deco_stone2", "tsm_pyramids:deco_stone2")
minetest.register_alias("pyramids:deco_stone3", "tsm_pyramids:deco_stone3")
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
minetest.register_chatcommand("spawnpyramid", {
@ -517,7 +309,7 @@ minetest.register_chatcommand("spawnpyramid", {
room_id = r
end
local ok, msg
pos = vector.add(pos, {x=-PYRA_Wh, y=-1, z=0})
pos = vector.add(pos, {x=-11, y=-1, z=0})
if s == 1 then
-- Sandstone
ok, msg = make(pos, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone", room_id)

View File

@ -6,11 +6,10 @@ Desert Sandstone with Cactus Engraving=
Desert Sandstone with Scarab Engraving=
Falling Cracked Sandstone Brick=
Falling Cracked Desert Sandstone Brick=
Mummy=
Mummy Spawn Egg=
Mummy Spawner=
Sandstone with Eye Engraving=
Sandstone with Human Engraving=
Sandstone with Man Engraving=
Sandstone with Sun Engraving=
A mummy spawner causes hostile mummies to appear in its vicinity as long it exists.=
Can be used to create a hostile mummy.=
@ -20,6 +19,6 @@ 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=
[<room_type>]
Pyramid generated at @1.
Incorrect room type ID: @1

View File

@ -6,11 +6,10 @@ 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 Human Engraving=Sandstein mit Menschengravur
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).

View File

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

385
mummy.lua
View File

@ -1,6 +1,4 @@
local S = tsm_pyramids.S
local mod_cmi = minetest.get_modpath("cmi") ~= nil
local S = minetest.get_translator("tsm_pyramids")
local mummy_walk_limit = 1
local mummy_chillaxin_speed = 1
@ -14,13 +12,11 @@ local mummy_texture = {"tsm_pyramids_mummy.png"}
local mummy_hp = 20
local mummy_drop = "default:papyrus"
local spawner_entity_offset = -0.28
local sound_normal = "mummy"
local sound_hit = "mummy_hurt"
local sound_dead = "mummy_death"
local spawner_check_range = 17
local spawner_range = 17
local spawner_max_mobs = 6
local function get_animations()
@ -51,11 +47,15 @@ local ANIM_WALK_MINE = 5
local ANIM_MINE = 6
local function hit(self)
self.object:set_texture_mod("^tsm_pyramids_hit.png")
local prop = {
mesh = mummy_mesh,
textures = {"tsm_pyramids_mummy.png^tsm_pyramids_hit.png"},
}
self.object:set_properties(prop)
minetest.after(0.4, function(self)
local prop = {textures = mummy_texture,}
if self ~= nil and self.object ~= nil then
self.object:set_texture_mod("")
if self.object ~= nil then
self.object:set_properties(prop)
end
end, self)
end
@ -63,22 +63,20 @@ end
local function mummy_update_visuals_def(self)
npc_anim = 0 -- Animation will be set further below immediately
local prop = {
mesh = mummy_mesh,
textures = mummy_texture,
}
self.object:set_properties(prop)
end
local MUMMY_DEF = {
initial_properties = {
hp_max = mummy_hp,
physical = true,
collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4},
visual = "mesh",
visual_size = {x=8,y=8},
mesh = mummy_mesh,
textures = mummy_texture,
makes_footstep_sound = true,
},
physical = true,
collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4},
visual = "mesh",
visual_size = {x=8,y=8},
mesh = mummy_mesh,
textures = mummy_texture,
makes_footstep_sound = true,
npc_anim = 0,
timer = 0,
turn_timer = 0,
@ -92,74 +90,24 @@ local MUMMY_DEF = {
envdmg_timer = 0,
attacker = "",
attacking_timer = 0,
-- CMI stuff
-- Track last cause of damage for cmi.notify_die
last_damage_cause = { type = "unknown" },
_cmi_is_mob = true,
description = S("Mummy"),
mob_name = "mummy"
}
-- Returns true if a mummy spawner entity was found at pos.
-- If self is provided, upstream pointed that is not count but must be checked if are the same
local function check_if_mummy_spawner_entity_exists(pos, self)
local ents = minetest.get_objects_inside_radius(pos, 0.5)
if not ents then return false end
for e=1, #ents do
local objent = ents[e]
local lua = objent:get_luaentity()
if self then
if objent ~= self.object then
local sobj = self.object:get_luaentity()
if sobj.name then
if sobj.name == "tsm_pyramids:mummy_spawner" then return true end
if sobj.name == "mummy_spawner" then return true end
else
return false -- BUG could be a mob spawner but cannot get the name?
end
else
return false -- same object, is duplicate cos "self" is provided!
end
else
if type(lua) ~= "userdata" then -- not a player could be a spawner or a node
if lua then
-- entity found
if lua.name then
if lua.name == "tsm_pyramids:mummy_spawner" then return true end
if lua.name == "mummy_spawner" then return true end
end
end
else
return false
end
end
end
return false
end
local spawner_DEF = {
initial_properties = {
hp_max = 1,
physical = false,
pointable = false,
visual = "mesh",
visual_size = {x=3.3,y=3.3},
mesh = mummy_mesh,
textures = mummy_texture,
makes_footstep_sound = false,
automatic_rotate = math.pi * 2.9,
},
hp_max = 1,
physical = true,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
visual_size = {x=3.3,y=3.3},
mesh = mummy_mesh,
textures = mummy_texture,
makes_footstep_sound = false,
timer = 0,
automatic_rotate = math.pi * 2.9,
m_name = "dummy"
}
spawner_DEF.on_activate = function(self)
local pos = self.object:get_pos()
local spos = vector.new(pos.x, pos.y + spawner_entity_offset, pos.z)
if check_if_mummy_spawner_entity_exists(spos, self) then
-- Remove possible duplicate entity
self.object:remove()
return
end
mummy_update_visuals_def(self)
self.object:set_velocity({x=0, y=0, z=0})
self.object:set_acceleration({x=0, y=0, z=0})
@ -167,18 +115,13 @@ spawner_DEF.on_activate = function(self)
end
-- Regularily check if entity is still inside spawner
spawner_DEF.on_step = function(self, dtime)
self.timer = self.timer + dtime
local pos = self.object:get_pos()
pos.y = pos.y - spawner_entity_offset
local n = minetest.get_node_or_nil(pos)
if self.timer > 50 then
self.timer = self.timer + 0.01
local n = minetest.get_node_or_nil(self.object:get_pos())
if self.timer > 1 then
if n and n.name and n.name ~= "tsm_pyramids:spawner_mummy" then
self.object:remove()
return
end
self.timer = 0
end
end
@ -186,33 +129,25 @@ spawner_DEF.on_punch = function(self, hitter)
end
MUMMY_DEF.on_activate = function(self, staticdata, dtime_s)
if mod_cmi then
cmi.notify_activate(self, dtime_s)
end
MUMMY_DEF.on_activate = function(self)
mummy_update_visuals_def(self)
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.npc_anim = ANIM_STAND
self.object:set_acceleration({x=0,y=-20,z=0})--20
self.state = 1
self.object:set_hp(mummy_hp)
self.object:set_armor_groups({fleshy=130})
end
MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
if mod_cmi then
cmi.notify_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
end
MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
self.attacker = puncher
if damage and damage > 0 then
self.last_damage = {
type = "punch",
puncher = puncher,
}
end
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
hit(self)
self.direction = {x=self.object:get_velocity().x, y=self.object:get_velocity().y, z=self.object:get_velocity().z}
@ -225,26 +160,16 @@ MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabili
end
end
end
if self.object:get_hp() == 0 then
local obj = minetest.add_item(self.object:get_pos(), mummy_drop.." "..math.random(0,3))
end
end
MUMMY_DEF.on_death = function(self, killer)
minetest.sound_play(sound_dead, {pos = self.object:get_pos(), max_hear_distance = 10 , gain = 0.3}, true)
-- 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
local cnt1 = 0
local cnt2 = 0
MUMMY_DEF.on_step = function(self, dtime)
if mod_cmi then
cmi.notify_step(self, dtime)
end
self.timer = self.timer + 0.01
self.turn_timer = self.turn_timer + 0.01
self.jump_timer = self.jump_timer + 0.01
@ -258,11 +183,13 @@ MUMMY_DEF.on_step = function(self, dtime)
self.time_passed = 0
end
-- Environment damage
if self.object:get_hp() == 0 then
minetest.sound_play(sound_dead, {pos = current_pos, max_hear_distance = 10 , gain = 0.3})
self.object:remove()
end
local def = minetest.registered_nodes[current_node.name]
local dps = def.damage_per_second
local dmg = 0
local dmg_node, dmg_pos
if dps ~= nil and dps > 0 then
dmg = dps
end
@ -282,25 +209,11 @@ MUMMY_DEF.on_step = function(self, dtime)
self.envdmg_timer = self.envdmg_timer + dtime
if dmg > 0 then
if self.envdmg_timer >= 1 then
local new_hp = self.object:get_hp() - dmg
if new_hp <= 0 then
if self.on_death then
self.on_death(self)
end
self.object:remove()
return
else
self.envdmg_timer = 0
self.object:set_hp(new_hp)
self.last_damage = {
type = "environment",
pos = current_pos,
node = current_node,
}
hit(self)
self.sound_timer = 0
minetest.sound_play(sound_hit, {pos = current_pos, max_hear_distance = 10, gain = 0.4}, true)
end
self.envdmg_timer = 0
self.object:set_hp(self.object:get_hp()-dmg)
hit(self)
self.sound_timer = 0
minetest.sound_play(sound_hit, {pos = current_pos, max_hear_distance = 10, gain = 0.3})
end
else
self.time_passed = 0
@ -318,7 +231,7 @@ MUMMY_DEF.on_step = function(self, dtime)
--play sound
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
end
@ -339,23 +252,20 @@ MUMMY_DEF.on_step = function(self, dtime)
if self.state == 1 then
self.yawwer = true
self.attacker = ""
local pos_obj = self.object:get_pos()
if pos_obj then
for _,object in ipairs(minetest.get_objects_inside_radius(pos_obj, 4)) do
if object:is_player() then
self.yawwer = false
local NPC = self.object:get_pos()
local PLAYER = object:get_pos()
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
if PLAYER.x > NPC.x then
self.yaw = self.yaw + math.pi
end
self.yaw = self.yaw - 2
self.object:set_yaw(self.yaw)
self.attacker = object
end
end
for _,object in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 4)) do
if object:is_player() then
self.yawwer = false
local NPC = self.object:get_pos()
local PLAYER = object:get_pos()
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
if PLAYER.x > NPC.x then
self.yaw = self.yaw + math.pi
end
self.yaw = self.yaw - 2
self.object:set_yaw(self.yaw)
self.attacker = object
end
end
if self.attacker == "" and self.turn_timer > math.random(1,4) then
@ -364,8 +274,7 @@ MUMMY_DEF.on_step = function(self, dtime)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end
local old_vel = self.object:get_velocity()
self.object:set_velocity({x=0,y=old_vel and old_vel.y or 0,z=0})
self.object:set_velocity({x=0,y=self.object:get_velocity().y,z=0})
if self.npc_anim ~= ANIM_STAND then
self.anim = get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, mummy_animation_speed, mummy_animation_blend)
@ -380,12 +289,7 @@ MUMMY_DEF.on_step = function(self, dtime)
if self.state == 2 then
if self.direction ~= nil then
local old_vel = self.object:get_velocity()
self.object:set_velocity({
x=self.direction.x*mummy_chillaxin_speed,
y=old_vel and old_vel.y or 0,
z=self.direction.z*mummy_chillaxin_speed,
})
self.object:set_velocity({x=self.direction.x*mummy_chillaxin_speed,y=self.object:get_velocity().y,z=self.direction.z*mummy_chillaxin_speed})
end
if self.turn_timer > math.random(1,4) and not self.attacker then
self.yaw = 360 * math.random()
@ -431,29 +335,16 @@ minetest.register_craftitem("tsm_pyramids:spawn_egg", {
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
if pointed_thing.type == "node" then
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
-- 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,
})
-- Spawn a mummy at position
function tsm_pyramids.spawn_mummy_at(pos, number)
function tsm_pyramids.spawn_mummy (pos, number)
local node = minetest.get_node(pos)
if node.name ~= "air" then
return
@ -470,20 +361,6 @@ else
spawnersounds = default.node_sound_stone_defaults()
end
local spawn_mummy_spawner_entity = function(pos)
local spos = vector.new(pos.x, pos.y+spawner_entity_offset, pos.z)
minetest.add_entity(spos, "tsm_pyramids:mummy_spawner")
end
-- Respawn mummy spawner entity at pos if none exists
local respawn_mummy_spawner_entity = function(pos)
local spos = vector.new(pos.x, pos.y + spawner_entity_offset, pos.z)
if check_if_mummy_spawner_entity_exists(spos) then
return
end
spawn_mummy_spawner_entity(pos)
end
minetest.register_node("tsm_pyramids:spawner_mummy", {
description = S("Mummy Spawner"),
_doc_items_longdesc = S("A mummy spawner causes hostile mummies to appear in its vicinity as long it exists."),
@ -494,15 +371,13 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
groups = {cracky=1,level=1},
drop = "",
on_construct = function(pos)
spawn_mummy_spawner_entity(pos)
end,
on_punch = function(pos)
respawn_mummy_spawner_entity(pos)
pos.y = pos.y - 0.28
minetest.add_entity(pos,"tsm_pyramids:mummy_spawner")
end,
on_destruct = function(pos)
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do
if obj ~= nil and not obj:is_player() then
if obj:get_luaentity().name == "tsm_pyramids:mummy_spawner" then
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
if not obj:is_player() then
if obj ~= nil and obj:get_luaentity().m_name == "dummy" then
obj:remove()
end
end
@ -510,91 +385,35 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
end,
sounds = spawnersounds,
})
-- Neccessary in case the spawner entity got lost due to /clearobjects
minetest.register_lbm({
label = "Respawn mummy spawner entity",
name = "tsm_pyramids:respawn_mummy_spawner_entity",
nodenames = { "tsm_pyramids:spawner_mummy" },
run_at_every_load = true,
action = function(pos, node)
respawn_mummy_spawner_entity(pos)
end,
})
-- 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({
nodenames = {"tsm_pyramids:spawner_mummy"},
interval = 2.0,
chance = 20,
action = function(pos, node, active_object_count, active_object_count_wider)
tsm_pyramids.attempt_mummy_spawn(pos, true)
end,
local player_near = false
local mobs = 0
for _,obj in ipairs(minetest.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"})
local p2 = {x=pos.x, y=pos.y+1, z=pos.z}
local n2 = minetest.get_node(p2)
if n2.name == "air" then
tsm_pyramids.spawn_mummy(p, 1)
end
end
end
end
})
end

158
nodes.lua
View File

@ -1,11 +1,11 @@
local S = tsm_pyramids.S
local S = minetest.get_translator("tsm_pyramids")
local img = {
"eye", "men", "sun",
"ankh", "scarab", "cactus"
}
local desc = {
S("Sandstone with Eye Engraving"), S("Sandstone with Human Engraving"), S("Sandstone with Sun Engraving"),
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")
}
@ -34,93 +34,93 @@ for i=1, #img do
end
local trap_on_timer = function(pos, elapsed)
local n = minetest.get_node(pos)
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)
local n = minetest.get_node(pos)
for i, obj in pairs(objs) do
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
-- 70% chance to ignore player to make the time of falling less predictable
if math.random(1, 10) >= 3 then
if n and n.name then
if minetest.registered_nodes[n.name]._tsm_pyramids_crack and minetest.registered_nodes[n.name]._tsm_pyramids_crack < 2 then
if n.name == "tsm_pyramids:trap" then
minetest.set_node(pos, {name="tsm_pyramids:trap_2"})
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
return true
end
if n.name == "tsm_pyramids:trap" then
minetest.set_node(pos, {name="tsm_pyramids:trap_2"})
if minetest.check_for_falling ~= nil then minetest.check_for_falling(pos) else nodeupdate(pos) end
elseif n.name == "tsm_pyramids:desert_trap" then
minetest.set_node(pos, {name="tsm_pyramids:desert_trap_2"})
if minetest.check_for_falling ~= nil then minetest.check_for_falling(pos) else nodeupdate(pos) end
end
return true
end
end
end
return true
end
local register_trap_stone = function(basename, desc_normal, desc_falling, base_tile, drop)
minetest.register_node("tsm_pyramids:"..basename, {
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."),
tiles = { base_tile .. "^tsm_pyramids_crack.png" },
is_ground_content = false,
groups = {crumbly=3,cracky=3},
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.1)
end,
_tsm_pyramids_crack = 1,
on_timer = trap_on_timer,
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_node("tsm_pyramids:trap", {
description = S("Cracked Sandstone Brick"),
_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"},
is_ground_content = false,
groups = {crumbly=3,cracky=3},
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.1)
end,
_tsm_pyramids_crack = 1,
on_timer = trap_on_timer,
drop = {
items = {
{ items = { "default:sand" }, rarity = 1 },
{ items = { "default:sand" }, rarity = 2 },
},
}
})
minetest.register_alias("tsm_pyramids:chest", "default:chest")
minetest.register_node("tsm_pyramids:trap_2", {
description = S("Falling Cracked Sandstone Brick"),
_doc_items_longdesc = S("This old porous brick falls under its own weight."),
tiles = {"default_sandstone_brick.png^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 = {
items = {
{ items = { "default:sand" }, rarity = 1 },
{ items = { "default:sand" }, rarity = 2 },
},
}
})
minetest.register_node("tsm_pyramids:desert_trap", {
description = S("Cracked Desert Sandstone Brick"),
_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_desert_sandstone_brick.png^tsm_pyramids_crack.png"},
is_ground_content = false,
groups = {crumbly=3,cracky=3},
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.1)
end,
_tsm_pyramids_crack = 1,
on_timer = trap_on_timer,
drop = {
items = {
{ items = { "default:desert_sand" }, rarity = 1 },
{ items = { "default:desert_sand" }, rarity = 2 },
},
}
})
minetest.register_node("tsm_pyramids:desert_trap_2", {
description = S("Falling Cracked Desert Sandstone Brick"),
_doc_items_longdesc = S("This old porous brick falls under its own weight."),
tiles = {"default_desert_sandstone_brick.png^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 = {
items = {
{ items = { "default:desert_sand" }, rarity = 1 },
{ items = { "default:desert_sand" }, rarity = 2 },
},
}
})

772
room.lua

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.