Compare commits

..

93 Commits

Author SHA1 Message Date
55028bc300 try to sinc by consider mapgen version
* This will allow pyramids to find some desert sand, but
  the astute will notice those are the v7 Heat Noise Parameters,
  the (5349, 3, 0.7, 500), and the Humidity for those inclined
  to tinker are (842, 3, 0.55, 500), cos mods that rely on
  the perlin noise must be in sync.
* try to detect the older simplev7 mod and sync with guessed values
* also detect the multicraft v7 plus mapgen
2024-04-29 15:06:51 -04:00
9f69de44c0 improved the information of the mod and provides the info about this fork 2024-04-29 14:49:27 -04:00
4297ae029d Fixed a crash due to vague or illogical comparisons for mummies
* seems the mummy is a mob, and `get_objects_inside_radius` also
  gets players, dropped items, etc... cos this function checks
  for all loaded entities on the server, so you'll need to check
  for that mummy around if those objects are only mobs, or not mobs
  or players or nodes.. this check is not made by upstream stupid developer,
  he just said "works for me"! and close the issue
* that function may returns nil/null if the name of the object is
  not EXACT the same, as made `if lua.name == "tsm_pyramids:mummy_spawmer"`
  then that the name could fails in rare cases becouse is used as index
  also the comparison is made with same olbject that seems
  do not have much effect
* The error of a nul vector is related only to the engine!
* Closes https://codeberg.org/minetest-stuffs/minetest-mod-tsm_pyramids/issues/4
* Closes https://github.com/EdenLostMinetest/tsm_pyramids/issues/1
* Closes https://codeberg.org/Wuzzy/minetest_tsm_pyramids/issues/4
2024-04-29 10:35:00 -04:00
2c9ea6faca workaround for bulk_set_node newer implementations on onder engines
* the `bulk_set_node` seems the function is since minetest 5.0 but
  it seems does not show in the git-shit-hub search, so found it
  manually at 584d00a01c
  that is only an optimized bulk way of `set_node` using a list of positions
  now with this pyramids will work in older versions of minetest too
* Closes https://codeberg.org/minetest-stuffs/minetest-mod-tsm_pyramids/issues/5
* incorporate a detection of 5.4+ versions of engine
2024-04-29 10:29:47 -04:00
762b2d7838 fix perlin noise returns null on some rarte cases as reported in minetest
* i was first checked at https://forum.minetest.net/viewtopic.php?t=8157
  as "minetest.get_perlin() and minetest.get_perlin_map() Return nil" by prestidigitator
  The `minetest.get_perlin()` function returns nil since 0.4.8+ until 5.1.0
  The `PerlinNoise()` constructor does return a valid object, on the other hand,
  barely documented as alternatrive cos is internally used only and not api public
  cos can only call it after the environment is created, so the code
  must bne inside `minetest.after(0, ...)` it only works the first time,
  or must be used an alternative
* was reported also https://github.com/minetest/minetest/issues/10385 that
  does not properly handle large world seeds
* Close https://codeberg.org/Wuzzy/minetest_tsm_pyramids/issues/2
* Close https://codeberg.org/minetest-stuffs/minetest-mod-tsm_pyramids/issues/2
* Also uses older get2d vs get_2d for newer engines older pre 5.0.0
  as seen on https://github.com/minetest-LOTR/Lord-of-the-Test/issues/139
  detect newer engine and uses proper method to get agains perlin object
  Closes https://codeberg.org/minetest-stuffs/minetest-mod-tsm_pyramids/issues/2
2024-04-29 10:17:25 -04:00
6b53a21c96 backguard compatibility for 4.X on translator and noisebuffer loading
* the wrokaround is done waithing until mod loads using minetest.after,
 at older engines we only can callit one time at load, but now the error
 generates in other place..  check for more elaborate solution
 at https://codeberg.org/minetest-stuffs/minetest-mod-tsm_pyramids/issues/2#issuecomment-1712924
* reported at https://codeberg.org/Wuzzy/minetest_tsm_pyramids/issues/2
* related to https://github.com/minetest/minetest/issues/10385#issuecomment-1674162787
2024-03-24 18:48:20 -04:00
fd60628a52 backguard compatibility add for older mod idetification 2024-03-24 18:48:05 -04:00
f46a9ae4f7 return back original chest fill but leave the refill on 30 minutes
* this was due the change from commit 1eb0bc363e1e7e4e4a754d0b0ca7df73ac3a1f11
  of sys4 <sys4@sys4.fr> at Fri Dec 27 01:22:46 2019 +0100
  that said: Ajoute remplissage des coffres 30 minutes après ouverture
  et modifie les items générés par ceux de nalc_trm
  merged at commit dfd03b56c686e821a11a5a53efbee49376f0ce9e
2024-03-21 06:14:09 -04:00
ffdc7cd035 Consider mapgen v7. Add max height.
* set a maximun height and use the parameters on mapgen v7 from poikilos,
  seems oldcoder already does that! this was taken from old fork
  from commit e970ff7955
* the commit only takes the max height part.. the node detection
  suggestion was omited (few 3 lines around sand_cnt_max_id check)
  cos is already added on the previous function `select_pyramid_type(min, max)`
2024-03-21 06:04:04 -04:00
4fc72e39ad get back a proper git attibutes to use only linux format files 2024-03-21 05:46:12 -04:00
e947488c24 use check_for_falling if 5.0.0-dev
* takend from poikilos fork of oldcoder fix on older engines using 0.4.15
  commit 955a6e3dc4
2024-03-21 05:43:04 -04:00
dfd03b56c6 Merge master from https://github.com/ronoaldo/tsm_pyramids into main: fix crashes
* Fix crash caused by lack of luaentity nil check and minetest 5.6
  from commit d4d89c5cc4
* Add refill to chests 30 minutes after opening; and modify the items
  generated by those of nalc_trm (we must change this later)
  from commit 1eb0bc363e
2024-03-21 05:31:37 -04:00
Wuzzy
34359b250f Merge pull request 'Fix deprecation warnings' (#3) from frostsnow/minetest_tsm_pyramids:5.8.0-fixes into master
Reviewed-on: https://codeberg.org/Wuzzy/minetest_tsm_pyramids/pulls/3
2024-01-07 17:31:13 +00:00
Wade T. Cline
699012db80 Fix deprecation warnings
Move defined object properties into the initial_properties table.
2024-01-06 20:01:14 -08:00
Wuzzy
408e33b76f Add missing 'than' in comment 2023-08-12 09:53:23 +02:00
Wuzzy
57b07b18e5 Fix missing = signs in template.txt 2023-03-14 03:23:02 +01:00
Wuzzy
84bea1052e Version 1.0.4 2022-10-16 17:06:50 +02:00
Wuzzy
303d3cf45c Respawn spawner entity on punch/load 2022-10-16 17:06:03 +02:00
Wuzzy
ac9a442a07 Add min_minetest_version 2022-10-16 16:26:55 +02:00
Wuzzy
a17725133e Rename one of the engraving stones (Man→Human) 2022-10-16 16:24:16 +02:00
Wuzzy
041a4c5dcc Add .mailmap for Wuzzy 2022-10-16 16:20:37 +02:00
Wuzzy
36fc4d2639 Remove giant useless .gitignore 2022-10-16 16:18:45 +02:00
Wuzzy
111639b778 Remove useless .gitattributes 2022-10-16 16:18:23 +02:00
Wuzzy
3fc59c9010 Fix crash if mummy dies in fire 2022-10-16 16:17:14 +02:00
sys4
d4d89c5cc4 Fix crash caused by lack of luaentity nil check and minetest 5.6 2022-09-04 19:00:44 +02:00
sys4
c8ecf77255 Merge remote-tracking branch 'upstream/master' 2022-03-05 11:28:23 +01:00
Wuzzy
61ebaab55e Version 1.0.3 2022-02-19 23:27:55 +01:00
Wuzzy
8a449ea8a8 Fix crash if on_punch was called w/ nil damage 2022-02-19 23:27:23 +01:00
sys4
d8ece75bee Merge remote-tracking branch 'upstream/master' into nalc-1.2-dev 2020-06-12 21:51:55 +02:00
Wuzzy
0abcd7960a Version 1.0.2 2020-04-06 14:59:36 +02:00
Wuzzy
f5fef5118d Fix broken mummy hit texture 2020-04-06 14:59:11 +02:00
Wuzzy
0974de93e4 Fix occassional crash when mummy dies 2020-04-06 14:41:48 +02:00
Wuzzy
0629d3b6ed Version 1.0.1 2020-04-06 00:47:39 +02:00
Wuzzy
5e9cd77fdc Use TRUE ephemeral sounds 2020-04-06 00:47:00 +02:00
Wuzzy
1b3f948daa Use ephemeral sounds 2020-04-06 00:19:56 +02:00
sys4
1eb0bc363e Ajoute remplissage des coffres 30 minutes après ouverture
et modifie les items générés par ceux de nalc_trm
2019-12-27 01:22:46 +01:00
Wuzzy
63572c5c23 Fix crash 2019-10-01 13:06:20 +02:00
Wuzzy
2538680eea Fix undeclared global warnings 2019-09-26 14:31:24 +02:00
Wuzzy
85da5073b9 Version 1.0.0 2019-09-02 20:45:11 +02:00
Wuzzy
d995fd381a Spawn egg: Make node on_rightclick take precedence 2019-08-25 18:47:10 +02:00
Wuzzy
355aa1d40d Add mummy description field (CMI) 2019-08-25 18:21:12 +02:00
Wuzzy
44482f6268 Add basic CMI support (experimental) 2019-08-25 18:04:16 +02:00
Wuzzy
ae4fc9135c Add _cmi_is_mob 2019-08-25 17:35:56 +02:00
Wuzzy
22b0823de4 Version 0.8 2019-08-25 17:30:10 +02:00
Wuzzy
e0f929d8dd Refactor pyramid type selection 2019-08-25 16:41:22 +02:00
Wuzzy
5abc9c1e47 Fix some bugs with traps generating 2019-08-25 16:33:14 +02:00
Wuzzy
47b32ecae1 Simplify trap stone definition 2019-08-25 16:02:25 +02:00
Wuzzy
c2167e305a Add new trap type: Deep drop 2019-08-25 15:17:04 +02:00
Wuzzy
f71ca591c9 More treasure variety 2019-08-25 14:00:03 +02:00
Wuzzy
9d5dace4fb Guarantee 1 chest with treasures 2019-08-25 12:37:36 +02:00
Wuzzy
0efa3dd75e Remove unneccessary set_hp 2019-08-25 12:30:32 +02:00
Wuzzy
34750f407a Call on_death when mummy dies in node 2019-08-25 12:29:39 +02:00
Wuzzy
049e575da1 Don't spawn mummies above liquids 2019-08-25 12:09:13 +02:00
Wuzzy
5104b2a117 Fix bad hp_max of mummy 2019-08-25 05:22:04 +02:00
Wuzzy
d9c4b78998 Remove papyrus from treasures 2019-08-25 05:18:35 +02:00
Wuzzy
fe4ff2025c Mummies drop papyrus again 2019-08-25 05:18:08 +02:00
Wuzzy
19c81a9b4f Improve initial mummy spawn 2019-08-25 01:52:12 +02:00
Wuzzy
4fde7b9091 Improve mummy spawner behaviour 2019-08-25 01:37:59 +02:00
Wuzzy
56277166d3 More reliable method to delete dummy 2019-08-25 01:02:49 +02:00
Wuzzy
e6a76549f6 Enable traps for more rooms 2019-08-25 00:50:22 +02:00
Wuzzy
b278da5bcf Remove useless node sets in make_entrance 2019-08-25 00:19:45 +02:00
Wuzzy
4bce10ff7d Implement custom room walls 2019-08-25 00:19:35 +02:00
Wuzzy
a7b45cbba7 Implement stype restriction 2019-08-24 23:19:41 +02:00
Wuzzy
7f5e97357e Remove useless call 2019-08-24 22:53:11 +02:00
Wuzzy
694d279ff0 Add reverse sandstone room style 2019-08-24 22:30:38 +02:00
Wuzzy
a6e3a50266 Keep pyramids away from cactus and trees 2019-08-24 22:00:08 +02:00
Wuzzy
269987771d Remove sand spam 2019-08-24 21:45:41 +02:00
Wuzzy
4aa41e096f Fix some logging errors 2019-08-24 21:28:35 +02:00
Wuzzy
4d25bdadf2 Reduce spawning of floating pyramids 2019-08-24 21:19:25 +02:00
Wuzzy
1d9fee5ab1 Improve node restriction handling 2019-08-24 20:12:03 +02:00
Wuzzy
4ec1b6b5bc Present desert stone pyramids in sandy areas 2019-08-24 20:05:51 +02:00
Wuzzy
4300f641dc Keep pyramids away from the beach 2019-08-24 19:37:11 +02:00
Wuzzy
01acc67011 Desert stone pyramids: Disable sand 2019-08-24 19:26:37 +02:00
Wuzzy
9af486611c Reacivate desert stone pyramids ... for now 2019-08-24 19:25:40 +02:00
Wuzzy
76bd636df2 Drop a minetest.after 2019-08-24 18:58:20 +02:00
Wuzzy
e3a6dac028 Distiction between column and sandstone 2019-08-24 17:43:18 +02:00
Wuzzy
71393b0368 Improve hieroglpyhs room 2019-08-24 17:14:08 +02:00
Wuzzy
479d625484 Fix crash when spawning traps 2019-08-24 16:24:23 +02:00
Wuzzy
6f24883fa3 Add 4 new rooms 2019-08-24 16:08:11 +02:00
Wuzzy
39e5289b74 Reduce the water distance restriction 2019-08-23 21:01:35 +02:00
Wuzzy
212636b66d Never spawn pyramids beyond maxp 2019-08-23 18:53:35 +02:00
Wuzzy
10cf7524b5 Add pyramid size variable 2019-08-23 17:26:01 +02:00
Wuzzy
fe41da8bd0 More tiles to place traps on 2019-08-23 14:37:38 +02:00
Wuzzy
1e6f18253e Prevent traps generating below pillars 2019-08-23 14:34:42 +02:00
Wuzzy
1fdb855347 Build walls around trap section 2019-08-23 13:53:43 +02:00
Wuzzy
f1a7d039e7 Generate 2 solid layers at bottom of pit
To prevent lava escaping
2019-08-23 13:30:33 +02:00
Wuzzy
20f0c8a845 Update mummy doll properties for MT 5.0.0 2019-08-23 13:04:45 +02:00
Wuzzy
2f82b3665c Remove outdated TODOs/FIXMEs 2019-08-23 13:02:18 +02:00
Wuzzy
92d36f9e79 Disable desert stone pyramids for now 2019-08-23 13:00:35 +02:00
Wuzzy
e40a41e473 Merge branch 'desert_stone' 2019-08-23 12:58:27 +02:00
Wuzzy
bd3f84ed4c Make falling of trap stones more unpredictable 2019-08-22 16:18:08 +02:00
Wuzzy
e824fa467e Randomly rotate pyramids 2019-08-22 14:50:26 +02:00
Wuzzy
c87a2afafa Make sounds mono 2019-08-20 21:01:42 +02:00
17 changed files with 1425 additions and 759 deletions

23
.gitattributes vendored
View File

@ -1,22 +1,5 @@
# Improve language detection of repo by ignoring x files.
*.x -linguist-detectable
# Auto detect text files and perform LF normalization # Auto detect text files and perform LF normalization
* text=auto * 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
View File

@ -1,215 +0,0 @@
#################
## 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

2
.mailmap Normal file
View File

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

View File

@ -1,41 +1,56 @@
# Pyramids (with Treasurer support) [`tsm_pyramids`] # minetest-mod-tsm_pyramids
* Version: 0.7 BUILDINGS of pyramids with treasures!
## Information
Constructions of pyramids with treasures! You can find them in deserts and sandstone deserts.
## Description
This is a mod for Minetest Game which adds randomly spawned pyramids in deserts and 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. 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. Also there are mummies inside, which attack the player if found in their radius.
## Historic notes ![screenshot.png](screenshot.png)
This mod is a fork of the old `pyramids` mod by BlockMen and intended to be a direct
## 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
(but unofficial) successor of it. (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 ## Licensing
This program is free software. It comes without any warranty, to This program is free software. It comes without any warranty, to
the extent permitted by applicable law. the extent permitted by applicable law.
### Source code and textures * Source code and textures
* [MIT License](https://mit-license.org/)
* [MIT License](https://mit-license.org/) * (c) Copyright BlockMen (2013)
* (c) Copyright BlockMen (2013) * Mummy model
* MIT License
### Mummy model * (c) Copyright Pavel\_S (2013)
* Textures
* MIT License * `tsm_pyramids_eye.png` by bas080, [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
* (c) Copyright Pavel\_S (2013) * `tsm_pyramids_men.png` by bas080, CC-BY-SA 3.0
* `tsm_pyramids_sun.png` by bas080, CC-BY-SA 3.0
### Textures * Sounds from ([freesound.org](https://freesound.org)):
* `mummy.1.ogg` by Raventhornn, [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
* `tsm_pyramids_eye.png` by bas080, [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) * `mummy.2.ogg` by Raventhornn, CC0
* `tsm_pyramids_men.png` by bas080, CC-BY-SA 3.0 * `mummy_hurt.1.ogg` by Under7dude, CC0
* `tsm_pyramids_sun.png` by bas080, CC-BY-SA 3.0 * `mummy_death.1.ogg` by scorpion67890 (modified by Wuzzy), CC0
* All other: BlockMen (MIT License) * 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 Normal file
View File

@ -0,0 +1,17 @@
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

7
depends.txt Normal file
View File

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

1
description.txt Normal file
View File

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

518
init.lua
View File

@ -1,77 +1,160 @@
local S = minetest.get_translator("tsm_pyramids") 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
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("tsm_pyramids").."/mummy.lua") dofile(minetest.get_modpath(modpath).."/mummy.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/nodes.lua") dofile(minetest.get_modpath(modpath).."/nodes.lua")
dofile(minetest.get_modpath("tsm_pyramids").."/room.lua") dofile(minetest.get_modpath(modpath).."/room.lua")
local mg_name = minetest.get_mapgen_setting("mg_name") local mg_name = minetest.get_mapgen_setting("mg_name")
local chest_stuff = { local chest_stuff = {
{name="default:apple", max = 3}, normal = {
{name="default:steel_ingot", max = 3}, {name="default:steel_ingot", max = 3},
{name="default:copper_ingot", max = 3}, {name="default:copper_ingot", max = 3},
{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}, },
{name="default:papyrus", max = 9}, 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 if minetest.get_modpath("farming") then
table.insert(chest_stuff, {name="farming:bread", max = 3}) table.insert(chest_stuff.desert_sandstone, {name="farming:bread", max = 3})
table.insert(chest_stuff, {name="farming:cotton", max = 8}) 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 else
table.insert(chest_stuff, {name="farming:apple", max = 8}) table.insert(chest_stuff.normal, {name="farming:apple", max = 8})
table.insert(chest_stuff, {name="farming:apple", max = 3}) table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
end end
if minetest.get_modpath("tnt") then if minetest.get_modpath("tnt") then
table.insert(chest_stuff, {name="tnt:gunpowder", max = 6}) table.insert(chest_stuff.normal, {name="tnt:gunpowder", max = 6})
table.insert(chest_stuff.desert_stone, {name="tnt:gunpowder", max = 6})
else else
table.insert(chest_stuff, {name="farming:apple", max = 3}) table.insert(chest_stuff.normal, {name="farming:apple", max = 3})
end end
function tsm_pyramids.fill_chest(pos, stype, flood_sand) function tsm_pyramids.fill_chest(pos, stype, flood_sand, treasure_chance)
minetest.after(2, function() local sand = "default:sand"
local sand = "default:sand" local n = minetest.get_node(pos)
if stype == "desert_sandstone" or stype == "desert_stone" then local meta = minetest.get_meta(pos)
sand = "default:desert_sand" 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)})
end end
local n = minetest.get_node(pos) -- Add treasures
if n and n.name and n.name == "default:chest" then if math.random(1,100) <= treasure_chance then
local meta = minetest.get_meta(pos) if minetest.get_modpath("treasurer") ~= nil then
local inv = meta:get_inventory() stacks = treasurer.select_random_treasures(3,1,5,{"minetool", "food", "crafting_component"})
inv:set_size("main", 8*4) else
local stacks = {} for i=0,2,1 do
-- Fill with sand in sand-flooded pyramids local stuff = chest_stuff.normal[math.random(1,#chest_stuff.normal)]
if flood_sand then table.insert(stacks, {name=stuff.name, count = math.random(1,stuff.max)})
table.insert(stacks, {name=sand, count = math.random(1,32)})
end
-- 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
end if math.random(1,100) <= 75 then
for s=1,#stacks do local stuff = chest_stuff[stype][math.random(1,#chest_stuff[stype])]
if not inv:contains_item("main", stacks[s]) then table.insert(stacks, {name=stuff.name, count = math.random(1,stuff.max)})
inv:set_stack("main", math.random(1,32), stacks[s])
end end
treasure_added = true
end end
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
return treasure_added
end end
local function add_spawner(pos, mummy_offset) local function add_spawner(pos, mummy_offset)
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 tsm_pyramids.spawn_mummy(vector.add(pos, mummy_offset),2) end if not minetest.settings:get_bool("only_peaceful_mobs") then
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)
@ -99,82 +182,124 @@ local function make_foundation_part(pos, set_to_stone)
end end
end end
local function make_entrance(pos, brick, sand, flood_sand) local function make_entrance(pos, rot, brick, sand, flood_sand)
local gang = {x=pos.x+10,y=pos.y, z=pos.z} 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 max_sand_height = math.random(1,3) local max_sand_height = math.random(1,3)
for iz=0,6,1 do for ie=0,6,1 do
local sand_height = math.random(1,max_sand_height) local sand_height = math.random(1,max_sand_height)
for iy=2,3,1 do for iy=2,3,1 do
if flood_sand and sand ~= "ignore" and iy <= sand_height and iz >= 3 then -- dig hallway
minetest.set_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz}, {name=sand}) 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 else
minetest.remove_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz}) minetest.remove_node(way_dir)
end end
if iz >=3 and iy == 3 then -- build decoration above entrance
minetest.set_node({x=gang.x,y=gang.y+iy+1,z=gang.z+iz}, {name=brick}) if ie == 3 and iy == 3 then
minetest.set_node({x=gang.x+1,y=gang.y+iy+1,z=gang.z+iz}, {name=brick}) local deco = {x=way_dir.x, y=way_dir.y+1,z=way_dir.z}
minetest.set_node({x=gang.x+2,y=gang.y+iy+1,z=gang.z+iz}, {name=brick}) 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 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 function make_pyramid(pos, brick, sandstone, stone, sand)
local set_to_brick = {} local set_to_brick = {}
local set_to_sand = {}
local set_to_stone = {} local set_to_stone = {}
-- Build pyramid -- Build pyramid
for iy=0,math.random(10,11),1 do for iy=0,math.random(10,PYRA_Wh),1 do
for ix=iy,22-iy,1 do for ix=iy,PYRA_W-1-iy,1 do
for iz=iy,22-iy,1 do for iz=iy,PYRA_W-1-iy,1 do
if iy < 1 then if iy < 1 then
make_foundation_part({x=pos.x+ix,y=pos.y,z=pos.z+iz}, set_to_stone) make_foundation_part({x=pos.x+ix,y=pos.y,z=pos.z+iz}, set_to_stone)
end end
table.insert(set_to_brick, {x=pos.x+ix,y=pos.y+iy,z=pos.z+iz}) 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 end
end end
minetest.bulk_set_node(set_to_stone , {name=stone}) wa_bulk_set_node(set_to_stone, {name=stone})
minetest.bulk_set_node(set_to_brick, {name=brick}) wa_bulk_set_node(set_to_brick, {name=brick})
if sand ~= "ignore" then
minetest.bulk_set_node(set_to_sand, {name=sand})
end
end end
local function make(pos, brick, sandstone, stone, sand, ptype, room_id) local function make(pos, brick, sandstone, stone, sand, ptype, room_id)
local bpos = table.copy(pos)
-- Build pyramid -- Build pyramid
make_pyramid(pos, brick, sandstone, stone, sand) make_pyramid(bpos, brick, sandstone, stone, sand)
local rot = math.random(0, 3)
-- Build room -- Build room
local ok, msg, flood_sand = tsm_pyramids.make_room(pos, ptype, room_id) local ok, msg, flood_sand = tsm_pyramids.make_room(bpos, ptype, room_id, rot)
-- Place mummy spawner -- Place mummy spawner
local r = math.random(1,3) local r = math.random(1,3)
if r == 1 then -- 4 possible spawner positions
local spawner_posses = {
-- front -- front
add_spawner({x=pos.x+11,y=pos.y+2, z=pos.z+17}, {x=0, y=0, z=-2}) {{x=bpos.x+PYRA_Wh,y=bpos.y+2, z=bpos.z+5}, {x=0, y=0, z=2}},
elseif r == 2 then
-- right
add_spawner({x=pos.x+17,y=pos.y+2, z=pos.z+11}, {x=-2, y=0, z=0})
else
-- left -- left
add_spawner({x=pos.x+5,y=pos.y+2, z=pos.z+11}, {x=2, y=0, z=0}) {{x=bpos.x+PYRA_Wm-5,y=bpos.y+2, z=bpos.z+PYRA_Wh}, {x=-2, y=0, z=0}},
end -- 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 -- Build entrance
make_entrance({x=pos.x,y=pos.y, z=pos.z}, brick, sand, flood_sand) make_entrance(bpos, rot, brick, sand, flood_sand)
-- Done -- Done
minetest.log("action", "Created pyramid at ("..pos.x..","..pos.y..","..pos.z..")") minetest.log("action", "[tsm_pyramids] Created pyramid at "..minetest.pos_to_string(bpos)..".")
return ok, msg 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 -- perlin noise / it depends of the mapgen, upstream do not set property
local perlin1
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 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)
@ -184,95 +309,181 @@ local function hlp_fnct(pos, name)
return false return false
end end
end end
local function ground(pos, old) local function ground(pos, old)
local p2 = pos local p2 = table.copy(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 p2 return {x=old.x, y=p2.y, z=old.z}
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)}
minetest.register_on_generated(function(minp, maxp, seed) local sand
if maxp.y < 0 then return end local sands = {"default:sand", "default:desert_sand", "default:desert_stone"}
math.randomseed(seed) local p2
if not perlin1 then local psand = {}
perlin1 = minetest.get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1) local sand
end local cnt = 0
local noise1 = perlin1:get_2d({x=minp.x,y=minp.y})--,z=minp.z}) local sand_cnt_max = 0
local sand_cnt_max_id
if noise1 > 0.25 or noise1 < -0.26 then -- Look for sand or desert stone to place the pyramid on
local mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)} for s=1, #sands do
cnt = 0
local sands = {"default:sand", "default:desert_sand", "default:desert_stone"} local sand_cnt = 0
local p2 sand = sands[s]
local psand = {} psand[s] = minetest.find_node_near(mpos, 25, sand)
local sand while cnt < 5 do
local cnt = 0 cnt = cnt+1
local cnt_min = 100 mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
for s=1, #sands do local spos = minetest.find_node_near(mpos, 25, sand)
cnt = 0 if spos ~= nil then
sand = sands[s] sand_cnt = sand_cnt + 1
psand[s] = minetest.find_node_near(mpos, 25, sand) if psand[s] == nil then
while psand == nil and cnt < 5 do psand[s] = spos
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 end
if sand_cnt > sand_cnt_max then
sand_cnt_max = sand_cnt
sand_cnt_max_id = s
p2 = psand[s]
end
end end
if p2 == nil then return end end
if p2.y < 0 then return end
local off = 0 -- Select the material type by the most prominent node type
local opos1 = {x=p2.x+22,y=p2.y-1,z=p2.z+22} -- E.g. if desert sand is most prominent, we place a desert sandstone pyramid
local opos2 = {x=p2.x+22,y=p2.y-1,z=p2.z} if sand_cnt_max_id then
local opos3 = {x=p2.x,y=p2.y-1,z=p2.z+22} sand = sands[sand_cnt_max_id]
local opos1_n = minetest.get_node_or_nil(opos1) else
local opos2_n = minetest.get_node_or_nil(opos2) sand = nil
local opos3_n = minetest.get_node_or_nil(opos3) p2 = nil
if opos1_n and opos1_n.name and opos1_n.name == "air" then end
p2 = ground(opos1, p2) return sand, p2
end 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
-- 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
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
end
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 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 return
end 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 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)
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 if (mg_name == "v6" and sand == "default:desert_sand" and math.random(1, 2) == 1) then
sand = "default:sand" sand = "default:sand"
end 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 if sand == "default:desert_sand" then
-- Desert sandstone pyramid -- Desert sandstone pyramid
minetest.after(0.8, make, p2, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone") make(p2, "default:desert_sandstone_brick", "default:desert_sandstone", "default:desert_stone", "default:desert_sand", "desert_sandstone")
elseif sand == "default:sand" then elseif sand == "default:sand" then
-- Sandstone pyramid -- Sandstone pyramid
minetest.after(0.8, make, p2, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone") make(p2, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone")
else else
-- Desert stone pyramid -- Desert stone pyramid
minetest.after(0.8, make, p2, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "default:desert_sand", "desert_stone") make(p2, "default:desert_stonebrick", "default:desert_stone_block", "default:desert_stone", "ignore", "desert_stone")
end end
end end
end) end)
@ -286,9 +497,6 @@ 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.register_chatcommand("spawnpyramid", {
@ -309,7 +517,7 @@ minetest.register_chatcommand("spawnpyramid", {
room_id = r room_id = r
end end
local ok, msg local ok, msg
pos = vector.add(pos, {x=-11, y=-1, z=0}) pos = vector.add(pos, {x=-PYRA_Wh, y=-1, z=0})
if s == 1 then if s == 1 then
-- Sandstone -- Sandstone
ok, msg = make(pos, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone", room_id) ok, msg = make(pos, "default:sandstonebrick", "default:sandstone", "default:sandstone", "default:sand", "sandstone", room_id)

View File

@ -6,10 +6,11 @@ Desert Sandstone with Cactus Engraving=
Desert Sandstone with Scarab Engraving= Desert Sandstone with Scarab Engraving=
Falling Cracked Sandstone Brick= Falling Cracked Sandstone Brick=
Falling Cracked Desert Sandstone Brick= Falling Cracked Desert Sandstone Brick=
Mummy=
Mummy Spawn Egg= Mummy Spawn Egg=
Mummy Spawner= Mummy Spawner=
Sandstone with Eye Engraving= Sandstone with Eye Engraving=
Sandstone with Man Engraving= Sandstone with Human Engraving=
Sandstone with Sun Engraving= Sandstone with Sun Engraving=
A mummy spawner causes hostile mummies to appear in its vicinity as long it exists.= A mummy spawner causes hostile mummies to appear in its vicinity as long it exists.=
Can be used to create a hostile mummy.= Can be used to create a hostile mummy.=
@ -19,6 +20,6 @@ This old porous brick falls under its own weight.=
No more mummies!= No more mummies!=
Destroy a mummy spawner by digging.= Destroy a mummy spawner by digging.=
Generate a pyramid= Generate a pyramid=
[<room_type>] [<room_type>]=
Pyramid generated at @1. Pyramid generated at @1.=
Incorrect room type ID: @1 Incorrect room type ID: @1=

View File

@ -6,10 +6,11 @@ Desert Sandstone with Cactus Engraving=Wüstensandstein mit Kaktusgravur
Desert Sandstone with Scarab Engraving=Wüstensandstein mit Skarabäusgravur Desert Sandstone with Scarab Engraving=Wüstensandstein mit Skarabäusgravur
Falling Cracked Sandstone Brick=Fallender rissiger Sandsteinziegel Falling Cracked Sandstone Brick=Fallender rissiger Sandsteinziegel
Falling Cracked Desert Sandstone Brick=Fallender rissiger Wüstensandsteinziegel Falling Cracked Desert Sandstone Brick=Fallender rissiger Wüstensandsteinziegel
Mummy=Mumie
Mummy Spawn Egg=Mumien-Spawn-Ei Mummy Spawn Egg=Mumien-Spawn-Ei
Mummy Spawner=Mumien-Spawner Mummy Spawner=Mumien-Spawner
Sandstone with Eye Engraving=Sandstein mit Augengravur Sandstone with Eye Engraving=Sandstein mit Augengravur
Sandstone with Man Engraving=Sandstein mit Manngravur Sandstone with Human Engraving=Sandstein mit Menschengravur
Sandstone with Sun Engraving=Sandstein mit Sonnengravur 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. 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). Can be used to create a hostile mummy.=Kann benutzt werden, um eine feindliche Mumie zu erzeugen (auch »spawnen« genannt).

View File

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

383
mummy.lua
View File

@ -1,4 +1,6 @@
local S = minetest.get_translator("tsm_pyramids") local S = tsm_pyramids.S
local mod_cmi = minetest.get_modpath("cmi") ~= nil
local mummy_walk_limit = 1 local mummy_walk_limit = 1
local mummy_chillaxin_speed = 1 local mummy_chillaxin_speed = 1
@ -12,11 +14,13 @@ local mummy_texture = {"tsm_pyramids_mummy.png"}
local mummy_hp = 20 local mummy_hp = 20
local mummy_drop = "default:papyrus" local mummy_drop = "default:papyrus"
local spawner_entity_offset = -0.28
local sound_normal = "mummy" 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_range = 17 local spawner_check_range = 17
local spawner_max_mobs = 6 local spawner_max_mobs = 6
local function get_animations() local function get_animations()
@ -47,15 +51,11 @@ local ANIM_WALK_MINE = 5
local ANIM_MINE = 6 local ANIM_MINE = 6
local function hit(self) local function hit(self)
local prop = { self.object:set_texture_mod("^tsm_pyramids_hit.png")
mesh = mummy_mesh,
textures = {"tsm_pyramids_mummy.png^tsm_pyramids_hit.png"},
}
self.object:set_properties(prop)
minetest.after(0.4, function(self) minetest.after(0.4, function(self)
local prop = {textures = mummy_texture,} local prop = {textures = mummy_texture,}
if self.object ~= nil then if self ~= nil and self.object ~= nil then
self.object:set_properties(prop) self.object:set_texture_mod("")
end end
end, self) end, self)
end end
@ -63,20 +63,22 @@ 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 = {
physical = true, initial_properties = {
collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4}, hp_max = mummy_hp,
visual = "mesh", physical = true,
visual_size = {x=8,y=8}, collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.9, 0.4},
mesh = mummy_mesh, visual = "mesh",
textures = mummy_texture, visual_size = {x=8,y=8},
makes_footstep_sound = true, mesh = mummy_mesh,
textures = mummy_texture,
makes_footstep_sound = true,
},
npc_anim = 0, npc_anim = 0,
timer = 0, timer = 0,
turn_timer = 0, turn_timer = 0,
@ -90,24 +92,74 @@ local MUMMY_DEF = {
envdmg_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"),
} }
-- 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 = { local spawner_DEF = {
hp_max = 1, initial_properties = {
physical = true, hp_max = 1,
collisionbox = {0,0,0,0,0,0}, physical = false,
visual = "mesh", pointable = false,
visual_size = {x=3.3,y=3.3}, visual = "mesh",
mesh = mummy_mesh, visual_size = {x=3.3,y=3.3},
textures = mummy_texture, mesh = mummy_mesh,
makes_footstep_sound = false, textures = mummy_texture,
makes_footstep_sound = false,
automatic_rotate = math.pi * 2.9,
},
timer = 0, timer = 0,
automatic_rotate = math.pi * 2.9,
m_name = "dummy"
} }
spawner_DEF.on_activate = function(self) 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) mummy_update_visuals_def(self)
self.object:set_velocity({x=0, y=0, z=0}) self.object:set_velocity({x=0, y=0, z=0})
self.object:set_acceleration({x=0, y=0, z=0}) self.object:set_acceleration({x=0, y=0, z=0})
@ -115,13 +167,18 @@ spawner_DEF.on_activate = function(self)
end end
-- Regularily check if entity is still inside spawner
spawner_DEF.on_step = function(self, dtime) spawner_DEF.on_step = function(self, dtime)
self.timer = self.timer + 0.01 self.timer = self.timer + dtime
local n = minetest.get_node_or_nil(self.object:get_pos()) local pos = self.object:get_pos()
if self.timer > 1 then pos.y = pos.y - spawner_entity_offset
local n = minetest.get_node_or_nil(pos)
if self.timer > 50 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
self.timer = 0
end end
end end
@ -129,25 +186,33 @@ spawner_DEF.on_punch = function(self, hitter)
end end
MUMMY_DEF.on_activate = function(self) MUMMY_DEF.on_activate = function(self, staticdata, dtime_s)
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:set_acceleration({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) 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
self.attacker = puncher self.attacker = puncher
if damage and damage > 0 then
self.last_damage = {
type = "punch",
puncher = puncher,
}
end
if puncher ~= nil then if puncher ~= nil then
local sound = sound_hit minetest.sound_play(sound_hit, {pos = self.object:get_pos(), loop = false, max_hear_distance = 10, gain = 0.4}, true)
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:get_velocity().x, y=self.object:get_velocity().y, z=self.object:get_velocity().z}
@ -160,16 +225,26 @@ MUMMY_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabili
end end
end end
end end
end
if self.object:get_hp() == 0 then MUMMY_DEF.on_death = function(self, killer)
local obj = minetest.add_item(self.object:get_pos(), mummy_drop.." "..math.random(0,3)) 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
end end
local cnt1 = 0
local cnt2 = 0
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
@ -183,13 +258,11 @@ MUMMY_DEF.on_step = function(self, dtime)
self.time_passed = 0 self.time_passed = 0
end end
if self.object:get_hp() == 0 then -- Environment damage
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 def = minetest.registered_nodes[current_node.name]
local dps = def.damage_per_second local dps = def.damage_per_second
local dmg = 0 local dmg = 0
local dmg_node, dmg_pos
if dps ~= nil and dps > 0 then if dps ~= nil and dps > 0 then
dmg = dps dmg = dps
end end
@ -209,11 +282,25 @@ MUMMY_DEF.on_step = function(self, dtime)
self.envdmg_timer = self.envdmg_timer + dtime self.envdmg_timer = self.envdmg_timer + dtime
if dmg > 0 then if dmg > 0 then
if self.envdmg_timer >= 1 then if self.envdmg_timer >= 1 then
self.envdmg_timer = 0 local new_hp = self.object:get_hp() - dmg
self.object:set_hp(self.object:get_hp()-dmg) if new_hp <= 0 then
hit(self) if self.on_death then
self.sound_timer = 0 self.on_death(self)
minetest.sound_play(sound_hit, {pos = current_pos, max_hear_distance = 10, gain = 0.3}) 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
end end
else else
self.time_passed = 0 self.time_passed = 0
@ -231,7 +318,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}) minetest.sound_play(sound_normal, {pos = current_pos, max_hear_distance = 10, gain = 0.2}, true)
self.sound_timer = 0 self.sound_timer = 0
end end
@ -252,20 +339,23 @@ 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 local pos_obj = self.object:get_pos()
if object:is_player() then if pos_obj then
self.yawwer = false for _,object in ipairs(minetest.get_objects_inside_radius(pos_obj, 4)) do
local NPC = self.object:get_pos() if object:is_player() then
local PLAYER = object:get_pos() self.yawwer = false
self.vec = {x=PLAYER.x-NPC.x, y=PLAYER.y-NPC.y, z=PLAYER.z-NPC.z} local NPC = self.object:get_pos()
self.yaw = math.atan(self.vec.z/self.vec.x)+math.pi^2 local PLAYER = object:get_pos()
if PLAYER.x > NPC.x then self.vec = {x=PLAYER.x-NPC.x, y=PLAYER.y-NPC.y, z=PLAYER.z-NPC.z}
self.yaw = self.yaw + math.pi self.yaw = math.atan(self.vec.z/self.vec.x)+math.pi^2
end if PLAYER.x > NPC.x then
self.yaw = self.yaw - 2 self.yaw = self.yaw + math.pi
self.object:set_yaw(self.yaw) end
self.attacker = object self.yaw = self.yaw - 2
end self.object:set_yaw(self.yaw)
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
@ -274,7 +364,8 @@ MUMMY_DEF.on_step = function(self, dtime)
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}) local old_vel = self.object:get_velocity()
self.object:set_velocity({x=0,y=old_vel and old_vel.y or 0,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)
@ -289,7 +380,12 @@ 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}) 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,
})
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()
@ -335,16 +431,29 @@ minetest.register_craftitem("tsm_pyramids:spawn_egg", {
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.add_entity(pointed_thing.above,"tsm_pyramids:mummy")
if not minetest.settings:get_bool("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,
}) })
function tsm_pyramids.spawn_mummy (pos, number) -- Spawn a mummy at position
function tsm_pyramids.spawn_mummy_at(pos, number)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if node.name ~= "air" then if node.name ~= "air" then
return return
@ -361,6 +470,20 @@ else
spawnersounds = default.node_sound_stone_defaults() spawnersounds = default.node_sound_stone_defaults()
end 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", { 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."),
@ -371,13 +494,15 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
groups = {cracky=1,level=1}, groups = {cracky=1,level=1},
drop = "", drop = "",
on_construct = function(pos) on_construct = function(pos)
pos.y = pos.y - 0.28 spawn_mummy_spawner_entity(pos)
minetest.add_entity(pos,"tsm_pyramids:mummy_spawner") end,
on_punch = function(pos)
respawn_mummy_spawner_entity(pos)
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.get_objects_inside_radius(pos, 0.5)) do
if not obj:is_player() then if obj ~= nil and not obj:is_player() then
if obj ~= nil and obj:get_luaentity().m_name == "dummy" then if obj:get_luaentity().name == "tsm_pyramids:mummy_spawner" then
obj:remove() obj:remove()
end end
end end
@ -385,35 +510,91 @@ minetest.register_node("tsm_pyramids:spawner_mummy", {
end, end,
sounds = spawnersounds, 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 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)
local player_near = false tsm_pyramids.attempt_mummy_spawn(pos, true)
local mobs = 0 end,
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 end

158
nodes.lua
View File

@ -1,11 +1,11 @@
local S = minetest.get_translator("tsm_pyramids") local S = tsm_pyramids.S
local img = { local img = {
"eye", "men", "sun", "eye", "men", "sun",
"ankh", "scarab", "cactus" "ankh", "scarab", "cactus"
} }
local desc = { local desc = {
S("Sandstone with Eye Engraving"), S("Sandstone with Man Engraving"), S("Sandstone with Sun Engraving"), S("Sandstone with Eye Engraving"), S("Sandstone with Human Engraving"), S("Sandstone with Sun Engraving"),
S("Desert Sandstone with Ankh Engraving"), S("Desert Sandstone with Scarab Engraving"), S("Desert Sandstone with Cactus 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 end
local trap_on_timer = function(pos, elapsed) local trap_on_timer = function(pos, elapsed)
local objs = minetest.get_objects_inside_radius(pos, 2)
local n = minetest.get_node(pos) 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)
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 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 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 n.name == "tsm_pyramids:trap" then if math.random(1, 10) >= 3 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 return true
end 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 end
end end
return true return true
end end
minetest.register_node("tsm_pyramids:trap", { local register_trap_stone = function(basename, desc_normal, desc_falling, base_tile, drop)
description = S("Cracked Sandstone Brick"), minetest.register_node("tsm_pyramids:"..basename, {
_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."), description = desc_normal,
tiles = {"default_sandstone_brick.png^tsm_pyramids_crack.png"}, _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."),
is_ground_content = false, tiles = { base_tile .. "^tsm_pyramids_crack.png" },
groups = {crumbly=3,cracky=3}, is_ground_content = false,
sounds = default.node_sound_stone_defaults(), groups = {crumbly=3,cracky=3},
on_construct = function(pos) sounds = default.node_sound_stone_defaults(),
minetest.get_node_timer(pos):start(0.1) on_construct = function(pos)
end, minetest.get_node_timer(pos):start(0.1)
_tsm_pyramids_crack = 1, end,
on_timer = trap_on_timer, _tsm_pyramids_crack = 1,
drop = { on_timer = trap_on_timer,
items = { drop = drop,
{ items = { "default:sand" }, rarity = 1 }, })
{ items = { "default:sand" }, rarity = 2 },
}, 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_2", { minetest.register_alias("tsm_pyramids:chest", "default:chest")
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.