Compare commits
2 Commits
master
...
flyer_alti
Author | SHA1 | Date |
---|---|---|
cora | cbd3e3264f | |
cora | d1a37f38b4 |
2
API.md
|
@ -42,7 +42,7 @@ A lot of things are possible by using one of the APIs in the mods. Note that not
|
||||||
* Buckets: `ITEMS/mcl_buckets`
|
* Buckets: `ITEMS/mcl_buckets`
|
||||||
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
|
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
|
||||||
|
|
||||||
### Mobs
|
## Mobs
|
||||||
* Mobs: `ENTITIES/mcl_mobs`
|
* Mobs: `ENTITIES/mcl_mobs`
|
||||||
|
|
||||||
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.
|
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.
|
||||||
|
|
123
CONTRIBUTING.md
|
@ -2,7 +2,7 @@
|
||||||
So you want to contribute to MineClone2?
|
So you want to contribute to MineClone2?
|
||||||
Wow, thank you! :-)
|
Wow, thank you! :-)
|
||||||
|
|
||||||
MineClone2 is maintained by Nicu and Cora. If you have any
|
MineClone2 is maintained by Nicu and Fleckenstein. If you have any
|
||||||
problems or questions, contact us (See Links section below).
|
problems or questions, contact us (See Links section below).
|
||||||
|
|
||||||
You can help with MineClone2's development in many different ways,
|
You can help with MineClone2's development in many different ways,
|
||||||
|
@ -11,9 +11,18 @@ whether you're a programmer or not.
|
||||||
## MineClone2's development target is to...
|
## MineClone2's development target is to...
|
||||||
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
||||||
based on the Minetest engine with polished features, usable in both
|
based on the Minetest engine with polished features, usable in both
|
||||||
singleplayer and multiplayer. Currently, a lot of Minecraft features
|
singleplayer and multiplayer. Currently, most of **Minecraft Java
|
||||||
are already implemented.
|
Edition 1.12.2** features are already implemented and polishing existing
|
||||||
Polishing existing features is always welcome.
|
features are prioritized over new feature requests.
|
||||||
|
- With lessened priority yet strictly, implement features targetting
|
||||||
|
**Minecraft version 1.17 + OptiFine** (OptiFine only as far as supported
|
||||||
|
by the Minetest Engine). This means features in parity with the listed
|
||||||
|
Minecraft experiences are prioritized over those that don't fulfill this
|
||||||
|
scope.
|
||||||
|
- Optionally, create a performant experience that will run relatively
|
||||||
|
well on really low spec computers. Unfortunately, due to Minecraft's
|
||||||
|
mechanisms and Minetest engine's limitations along with a very small
|
||||||
|
playerbase on low spec computers, optimizations are hard to investigate.
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
* [Mesehub](https://git.minetest.land/MineClone2/MineClone2)
|
* [Mesehub](https://git.minetest.land/MineClone2/MineClone2)
|
||||||
|
@ -36,10 +45,8 @@ referenced frequently because of its usefulness. As such, it is valuable
|
||||||
in learning how git works and its terminology. It can also help you
|
in learning how git works and its terminology. It can also help you
|
||||||
keeping your game updated, and easily test pull requests.
|
keeping your game updated, and easily test pull requests.
|
||||||
|
|
||||||
Look at our wiki for some concrete guides:
|
|
||||||
https://git.minetest.land/MineClone2/MineClone2/wiki/
|
|
||||||
|
|
||||||
## How you can help as a non-programmer
|
## How you can help as a non-programmer
|
||||||
|
|
||||||
As someone who does not know how to write programs in Lua or does not
|
As someone who does not know how to write programs in Lua or does not
|
||||||
know how to use the Minetest API, you can still help us out a lot. For
|
know how to use the Minetest API, you can still help us out a lot. For
|
||||||
example, by opening an issue in the
|
example, by opening an issue in the
|
||||||
|
@ -51,10 +58,12 @@ you can report a bug or request a feature.
|
||||||
discussion.
|
discussion.
|
||||||
* Choose a descriptive title (e.g. not just "crash", "bug" or "question"
|
* Choose a descriptive title (e.g. not just "crash", "bug" or "question"
|
||||||
).
|
).
|
||||||
|
* Please write in plain, understandable English. It will be easier to
|
||||||
|
communicate.
|
||||||
|
* Please start the issue title with a capital letter.
|
||||||
* Always check the currently opened issues before creating a new one.
|
* Always check the currently opened issues before creating a new one.
|
||||||
Try not to report bugs that have already been reported or request features
|
Don't report bugs that have already been reported or request features
|
||||||
that already have been requested. This can often be ambiguous though.
|
that already have been requested.
|
||||||
If in doubt open an issue!
|
|
||||||
* If you know about Minetest's inner workings, please think about
|
* If you know about Minetest's inner workings, please think about
|
||||||
whether the bug / the feature that you are reporting / requesting is
|
whether the bug / the feature that you are reporting / requesting is
|
||||||
actually an issue with Minetest itself, and if it is, head to the
|
actually an issue with Minetest itself, and if it is, head to the
|
||||||
|
@ -64,9 +73,6 @@ instead.
|
||||||
an issue, feel free to ask on the Discord / Matrix server or the IRC
|
an issue, feel free to ask on the Discord / Matrix server or the IRC
|
||||||
channel.
|
channel.
|
||||||
|
|
||||||
The link to the mesehub registration page is: https://git.minetest.land/user/sign_up
|
|
||||||
(It appears to sometimes get lost on the page itsself)
|
|
||||||
|
|
||||||
### Reporting bugs
|
### Reporting bugs
|
||||||
* A bug is an unintended behavior or, in the worst case, a crash.
|
* A bug is an unintended behavior or, in the worst case, a crash.
|
||||||
However, it is not a bug if you believe something is missing in the
|
However, it is not a bug if you believe something is missing in the
|
||||||
|
@ -105,28 +111,23 @@ would report issues will pull requests similar to when you were
|
||||||
reporting bugs that are the mainline (See Reporting bugs section). You
|
reporting bugs that are the mainline (See Reporting bugs section). You
|
||||||
can find currently open pull requests here:
|
can find currently open pull requests here:
|
||||||
<https://git.minetest.land/MineClone2/MineClone2/pulls>. Note that pull
|
<https://git.minetest.land/MineClone2/MineClone2/pulls>. Note that pull
|
||||||
requests that start with a `WIP:` are not done yet and therefore could
|
requests that start with a `WIP:` are not done yet, and therefore might
|
||||||
still undergo substantial change. Testing these is still helpful however
|
not work, so it's not very useful to try them out yet.
|
||||||
because that is the reason developers put them up as WIP so other people
|
|
||||||
can have a look at the PR.
|
|
||||||
|
|
||||||
### Contributing assets
|
### Contributing assets
|
||||||
Due to license problems, MineClone2 cannot use Minecraft's assets,
|
Due to license problems, MineClone2 unfortunately cannot use
|
||||||
therefore we are always looking for asset contributions.
|
Minecraft's assets, therefore we are always looking for asset
|
||||||
|
contributions. To contribute assets, it can be useful to learn git
|
||||||
To contribute assets, it can be useful to learn git basics and read
|
basics and read the section for Programmers of this document, however
|
||||||
the section for Programmers of this document, however this is not required.
|
this is not required. It's also a good idea to join the Discord server
|
||||||
It's also a good idea to join the Discord server
|
|
||||||
(or alternatively IRC or Matrix).
|
(or alternatively IRC or Matrix).
|
||||||
|
|
||||||
#### Textures
|
#### Textures
|
||||||
For textures we use the Pixel Perfection texture pack. For older Minecraft
|
For textures we use the Pixel Perfection texture pack. This is mostly
|
||||||
features that is mostly enough but a lot of the newer textures in it are
|
enough; however in some cases - e.g. for newer Minecraft features, it's
|
||||||
copies or slight modifications of the original MC textures so great caution
|
useful to have texture artists around. If you want to make such
|
||||||
needs to be taken when using any textures coming from Minecraft texture
|
contributions, join our Discord server. Demands for textures will be
|
||||||
packs.
|
communicated there.
|
||||||
If you want to make such contributions, join our Discord server. Demands
|
|
||||||
for textures will be communicated there.
|
|
||||||
|
|
||||||
#### Sounds
|
#### Sounds
|
||||||
MineClone2 currently does not have a consistent way to handle sounds.
|
MineClone2 currently does not have a consistent way to handle sounds.
|
||||||
|
@ -250,25 +251,16 @@ of the results)
|
||||||
* [Official Minecraft Wiki](https://minecraft.fandom.com/wiki/Minecraft_Wiki)
|
* [Official Minecraft Wiki](https://minecraft.fandom.com/wiki/Minecraft_Wiki)
|
||||||
(Include a link to the specific page you used)
|
(Include a link to the specific page you used)
|
||||||
|
|
||||||
### Guidelines
|
### Stick to our guidelines
|
||||||
|
|
||||||
#### Git Guidelines
|
#### Git Guidelines
|
||||||
* Pushing to master is disabled - don't even try it.
|
* We use merge rather than rebase or squash merge
|
||||||
* Every change is tracked as a PR.
|
* We don't use git submodules.
|
||||||
* All but the tiniest changes require at least one approval from a Developer
|
* Your commit names should be relatively descriptive, e.g. when saying
|
||||||
* To update branches we use rebase not merge (so we don't end up with
|
"Fix #issueid", the commit message should also contain the title of the
|
||||||
excessive git bureaucracy commits in master)
|
issue.
|
||||||
* We use merge to add the commits from a PR/branch to master
|
* Try to keep your commits as atomic as possible (advise, but completely
|
||||||
* Submodules should only be used if a) upstream is highly reliable and
|
optional)
|
||||||
b) it is 100% certain that no mcl2 specific changes to the code will be
|
|
||||||
needed (this has never been the case before, hence mcl2 is submodule free so far)
|
|
||||||
* Commit messages should be descriptive and never contain mcl2 specific
|
|
||||||
issueids - there are other projects who might use commits from mcl2 and
|
|
||||||
it will confuse their issue trackers.
|
|
||||||
* Try to group your submissions best as you can:
|
|
||||||
* Try to keep your PRs small: In some cases things reasonably be can't
|
|
||||||
split up but in general multiple small PRs are better than a big one.
|
|
||||||
* Similarly multiple small commits are better than a giant one. (use git commit -p)
|
|
||||||
|
|
||||||
#### Code Guidelines
|
#### Code Guidelines
|
||||||
* Each mod must provide `mod.conf`.
|
* Each mod must provide `mod.conf`.
|
||||||
|
@ -351,23 +343,36 @@ Active and trusted contributors are often granted write access to the
|
||||||
MineClone2 repository.
|
MineClone2 repository.
|
||||||
|
|
||||||
#### Developer responsibilities
|
#### Developer responsibilities
|
||||||
- If you have developer privileges you can just open a new branch in the
|
- You should not push things directly to
|
||||||
mcl2 repository (which is preferred). From that you create a pull request.
|
MineClone2 master - rather, do your work on a branch on your private
|
||||||
This way other people can review your changes and make sure they work
|
repository, then create a pull request. This way other people can review
|
||||||
before they get merged.
|
your changes and make sure they work before they get merged.
|
||||||
- If you do not (yet) have developer privs you do your work on a branch
|
- Merge PRs only when they have recieved the necessary feedback and have
|
||||||
on your private repository e.g. using the "fork" function on mesehub.
|
been tested by at least two different people (including the author of
|
||||||
- Any developer is welcome to review, test and merge PRs. A PR needs
|
the pull request), to avoid crashes or the introduction of new bugs.
|
||||||
at least one approval (by someone else than the author) but the maintainers
|
- You may also be assigned to issues or pull
|
||||||
are usually relatively quick to react to new submissions.
|
requests as a developer. In this case it is your responsibility to fix
|
||||||
|
the issue / review and merge the pull request when it is ready. You can
|
||||||
|
also unassign yourself from the issue / PR if you have no time or don't
|
||||||
|
want to take care of it for some other reason. After all, everyone is a
|
||||||
|
volunteer and we can't expect you to do work that you are not interested
|
||||||
|
in. **The important thing is that you make sure to inform us if you
|
||||||
|
won't take care of something that has been assigned to you.**
|
||||||
|
- Please assign yourself to something that you want to work on to avoid
|
||||||
|
duplicate work.
|
||||||
|
- As a developer, it should be easy to reach you about your work. You
|
||||||
|
should be in at least one of the public MineClone2 discussion rooms -
|
||||||
|
preferrably Discord, but if you really don't like Discord, Matrix
|
||||||
|
or IRC are fine too.
|
||||||
|
|
||||||
### Maintainer status
|
### Maintainer status
|
||||||
Maintainers carry the main responsibility for the project.
|
Maintainers carry the main responsibility for the project.
|
||||||
|
|
||||||
#### Maintainer responsibilities
|
#### Maintainer responsibilities
|
||||||
- Making sure issues are addressed and pull requests are reviewed and
|
- Making sure issues are addressed and pull requests are reviewed and
|
||||||
merged.
|
merged, by assigning either themselves or Developers to issues / PRs
|
||||||
- Making releases
|
- Making releases
|
||||||
|
- Making sure guidelines are kept
|
||||||
- Making project decisions based on community feedback
|
- Making project decisions based on community feedback
|
||||||
- Granting/revoking developer access
|
- Granting/revoking developer access
|
||||||
- Enforcing the code of conduct (See CODE_OF_CONDUCT.md)
|
- Enforcing the code of conduct (See CODE_OF_CONDUCT.md)
|
||||||
|
@ -375,8 +380,8 @@ merged.
|
||||||
- Resolving conflicts and problems within the community
|
- Resolving conflicts and problems within the community
|
||||||
|
|
||||||
#### Current maintainers
|
#### Current maintainers
|
||||||
* Cora - responsible for gameplay review, publishing releases,
|
* Fleckenstein - responsible for gameplay review, publishing releases,
|
||||||
technical guidelines
|
technical guidelines and issue/PR delegation
|
||||||
* Nicu - responsible for community related issues
|
* Nicu - responsible for community related issues
|
||||||
|
|
||||||
#### Release process
|
#### Release process
|
||||||
|
|
27
CREDITS.md
|
@ -27,12 +27,6 @@
|
||||||
* Code-Sploit
|
* Code-Sploit
|
||||||
* NO11
|
* NO11
|
||||||
* kabou
|
* kabou
|
||||||
* rudzik8
|
|
||||||
* chmodsayshello
|
|
||||||
* PrairieWind
|
|
||||||
* RandomLegoBrick
|
|
||||||
* SumianVoice
|
|
||||||
* MrRar
|
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
* Laurent Rocher
|
* Laurent Rocher
|
||||||
|
@ -77,14 +71,6 @@
|
||||||
* Sven792
|
* Sven792
|
||||||
* aldum
|
* aldum
|
||||||
* Dieter44
|
* Dieter44
|
||||||
* Pepebotella
|
|
||||||
* MrRar
|
|
||||||
* Lazerbeak12345
|
|
||||||
* mrminer
|
|
||||||
* Thunder1035
|
|
||||||
* opfromthestart
|
|
||||||
* snowyu
|
|
||||||
* FaceDeer
|
|
||||||
|
|
||||||
## MineClone5
|
## MineClone5
|
||||||
* kay27
|
* kay27
|
||||||
|
@ -92,12 +78,10 @@
|
||||||
* epCode
|
* epCode
|
||||||
* NO11
|
* NO11
|
||||||
* j45
|
* j45
|
||||||
* chmodsayshello
|
|
||||||
* 3raven
|
* 3raven
|
||||||
* PrairieWind
|
* PrarieWind
|
||||||
* Gustavo1
|
* Gustavo1
|
||||||
* CableGuy67
|
* CableGuy67
|
||||||
* MrRar
|
|
||||||
|
|
||||||
## Mineclonia
|
## Mineclonia
|
||||||
* erlehmann
|
* erlehmann
|
||||||
|
@ -135,7 +119,6 @@
|
||||||
* 4Evergreen4
|
* 4Evergreen4
|
||||||
* jordan4ibanez
|
* jordan4ibanez
|
||||||
* paramat
|
* paramat
|
||||||
* cora
|
|
||||||
|
|
||||||
## 3D Models
|
## 3D Models
|
||||||
* 22i
|
* 22i
|
||||||
|
@ -151,9 +134,6 @@
|
||||||
* yutyo
|
* yutyo
|
||||||
* NO11
|
* NO11
|
||||||
* kay27
|
* kay27
|
||||||
* MysticTempest
|
|
||||||
* RandomLegoBrick
|
|
||||||
* cora
|
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
* Wuzzy
|
* Wuzzy
|
||||||
|
@ -163,10 +143,6 @@
|
||||||
* pitchum
|
* pitchum
|
||||||
* todoporlalibertad
|
* todoporlalibertad
|
||||||
* Marcin Serwin
|
* Marcin Serwin
|
||||||
* Pepebotella
|
|
||||||
* Emojigit
|
|
||||||
* snowyu
|
|
||||||
* 3raven
|
|
||||||
|
|
||||||
## Funders
|
## Funders
|
||||||
* 40W
|
* 40W
|
||||||
|
@ -174,6 +150,5 @@
|
||||||
## Special thanks
|
## Special thanks
|
||||||
* celeron55 for creating Minetest
|
* celeron55 for creating Minetest
|
||||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||||
* wsor for working tirelessly in the shadows for the good of all of us, particularly helping with solving contentDB and copyright issues.
|
|
||||||
* The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game
|
* The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game
|
||||||
* Notch and Jeb for being the major forces behind Minecraft
|
* Notch and Jeb for being the major forces behind Minecraft
|
||||||
|
|
18
README.md
|
@ -2,7 +2,7 @@
|
||||||
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
|
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
|
||||||
Developed by many people. Not developed or endorsed by Mojang AB.
|
Developed by many people. Not developed or endorsed by Mojang AB.
|
||||||
|
|
||||||
Version: 0.80 (in development)
|
Version: 0.75 (in development)
|
||||||
|
|
||||||
### Gameplay
|
### Gameplay
|
||||||
You start in a randomly-generated world made entirely of cubes. You can explore
|
You start in a randomly-generated world made entirely of cubes. You can explore
|
||||||
|
@ -91,11 +91,11 @@ The MineClone2 repository is hosted at Mesehub. To contribute or report issues,
|
||||||
## Target
|
## Target
|
||||||
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
||||||
based on the Minetest engine with polished features, usable in both
|
based on the Minetest engine with polished features, usable in both
|
||||||
singleplayer and multiplayer. Currently, a lot of **Minecraft Java
|
singleplayer and multiplayer. Currently, most of **Minecraft Java
|
||||||
Edition** features are already implemented and polishing existing
|
Edition 1.12.2** features are already implemented and polishing existing
|
||||||
features are prioritized over new feature requests.
|
features are prioritized over new feature requests.
|
||||||
- With lessened priority yet strictly, implement features targetting
|
- With lessened priority yet strictly, implement features targetting
|
||||||
**Current Minecraft versions + OptiFine** (OptiFine only as far as supported
|
**Minecraft version 1.17 + OptiFine** (OptiFine only as far as supported
|
||||||
by the Minetest Engine). This means features in parity with the listed
|
by the Minetest Engine). This means features in parity with the listed
|
||||||
Minecraft experiences are prioritized over those that don't fulfill this
|
Minecraft experiences are prioritized over those that don't fulfill this
|
||||||
scope.
|
scope.
|
||||||
|
@ -108,7 +108,8 @@ playerbase on low spec computers, optimizations are hard to investigate.
|
||||||
This game is currently in **beta** stage.
|
This game is currently in **beta** stage.
|
||||||
It is playable, but not yet feature-complete.
|
It is playable, but not yet feature-complete.
|
||||||
Backwards-compability is not entirely guaranteed, updating your world might cause small bugs.
|
Backwards-compability is not entirely guaranteed, updating your world might cause small bugs.
|
||||||
If you want to use the development version of MineClone2 in production, the master branch is usually relatively stable. The testing branch often features some experimental PRs and should be considered less stable.
|
If you want to use the git version of MineClone2 in production, consider using the production branch.
|
||||||
|
It is updated weekly and contains relatively stable code for servers.
|
||||||
|
|
||||||
The following main features are available:
|
The following main features are available:
|
||||||
|
|
||||||
|
@ -123,7 +124,7 @@ The following main features are available:
|
||||||
* Most blocks in the overworld
|
* Most blocks in the overworld
|
||||||
* Water and lava
|
* Water and lava
|
||||||
* Weather
|
* Weather
|
||||||
* 28 biomes + 5 Nether Biomes
|
* 28 biomes
|
||||||
* The Nether, a fiery underworld in another dimension
|
* The Nether, a fiery underworld in another dimension
|
||||||
* Redstone circuits (partially)
|
* Redstone circuits (partially)
|
||||||
* Minecarts (partial)
|
* Minecarts (partial)
|
||||||
|
@ -161,7 +162,7 @@ The following features are incomplete:
|
||||||
* Special minecarts
|
* Special minecarts
|
||||||
* A couple of non-trivial blocks and items
|
* A couple of non-trivial blocks and items
|
||||||
|
|
||||||
Bonus features (not found in Minecraft):
|
Bonus features (not found in Minecraft 1.12):
|
||||||
|
|
||||||
* Built-in crafting guide which shows you crafting and smelting recipes
|
* Built-in crafting guide which shows you crafting and smelting recipes
|
||||||
* In-game help system containing extensive help about gameplay basics, blocks, items and more
|
* In-game help system containing extensive help about gameplay basics, blocks, items and more
|
||||||
|
@ -174,9 +175,6 @@ Bonus features (not found in Minecraft):
|
||||||
* Nether Brick Fence Gate
|
* Nether Brick Fence Gate
|
||||||
* Red Nether Brick Fence
|
* Red Nether Brick Fence
|
||||||
* Red Nether Brick Fence Gate
|
* Red Nether Brick Fence Gate
|
||||||
* Structure replacements - these small variants of Minecraft structures serve as replacements until we can get large structures working:
|
|
||||||
* Woodland Cabin (Mansions)
|
|
||||||
* Nether Outpost (Fortress)
|
|
||||||
|
|
||||||
Technical differences from Minecraft:
|
Technical differences from Minecraft:
|
||||||
|
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
# MineClone2
|
|
||||||
Un jeu non-officiel similaire à Minecraft pour Minetest. Forké depuis Mineclone par davedevils. Développé par de nombreuses personnes. Ni développé ou supporté par Mojang AB.
|
|
||||||
|
|
||||||
Version: 0.79 (en dévelopment)
|
|
||||||
|
|
||||||
### Gameplay
|
|
||||||
|
|
||||||
Vous atterissez dans un monde fait entièrement de cubes et généré aléatoirement. Vous pouvez explorer le monde, miner et construire presque n'importe quel bloc pour créer de nouvelles structures. Vous pouvez choisir de jouer en "mode survie" dans lequel vous devez combattre des monstres et la faim et progresser lentement dans différents aspects du jeu, comme l'extraction de minerai, l'agriculture, la construction de machines et ainsi de suite. Ou alors vous pouvez jouer en "mode créatif" où vous pouvez construire à peu près n'importe quoi instantanément.
|
|
||||||
|
|
||||||
### Résumé du Gameplay
|
|
||||||
|
|
||||||
* Jeu de type bac-à-sable, sans objetifs
|
|
||||||
* Survie : combattre des monstres hostiles et la faim
|
|
||||||
* Creuser pour du minerai et d'autres trésors
|
|
||||||
* Magie : gagner de l'expérience et enchanter les outils
|
|
||||||
* Utiliser les blocs ramassés pour construire de magnifiques bâtiments, votre imagination est la limite
|
|
||||||
* Ramasser des fleurs (et d'autres sources de teinture) et colorez votre monde
|
|
||||||
* Trouvez des graines et commencez à cultiver
|
|
||||||
* Trouvez ou fabriquez des centaines d'objets
|
|
||||||
* Construisez un réseau ferroviaire complexe et amusez vous avec les wagonnets
|
|
||||||
* En mode créatif vous pouvez construire presque n'importe quoi gratuitement et sans limite
|
|
||||||
|
|
||||||
## Comment jouer (démarrer rapidement)
|
|
||||||
### Commencer
|
|
||||||
* **Frappez un arbre** jusqu'à ce qu'il casse et donne du bois
|
|
||||||
* Placez le **bois dans la grille 2x2** (la "grille de fabrication" de votre menu d'inventaire) et fabriquez 4 planches de bois
|
|
||||||
* Placer les 4 planches de bois dans la grille 2x2 et **fabriquez une table d'artisanat**
|
|
||||||
* **Cliquez droit la table d'artisanat** (icone livre) pour apprendre toutes les recettes possibles
|
|
||||||
* **Fabriquez une pioche de bois** pour miner la pierre
|
|
||||||
* Différents outils minent différentes sortes de blocs. Essayez les !
|
|
||||||
* Continuez à jouer comme vous voulez. Amusez vous !
|
|
||||||
|
|
||||||
### Agriculture
|
|
||||||
* Trouvez des graines
|
|
||||||
* Fabriquez une houe
|
|
||||||
* Cliquez droit la terre ou des blocs similaires avec la houe pour créer des terres agricoles
|
|
||||||
* Placer des graines sur des terres agricoles et regardez les pousser
|
|
||||||
* Récoltez les plantes une fois matûres
|
|
||||||
* Les terres agricoles proche de l'eau deviennent humides et accélèrent la croissance
|
|
||||||
|
|
||||||
### Four
|
|
||||||
* Fabriquer un Four
|
|
||||||
* Le four permet d'obtenir plus d'objets
|
|
||||||
* L'emplacement du haut doit contienir un objet fondable (par ex : minerai de fer)
|
|
||||||
* L'emplacement du bas doit contienir un objet combustible (par ex : charbon)
|
|
||||||
* Voir le guide d'artisanat pour en apprendre plus sur les objets fondables et combustibles
|
|
||||||
|
|
||||||
### Aide supplémentaire
|
|
||||||
Plus d'aide à propos du jeu, des blocs, objets et plus encore peuvent être trouvés dans le jeu. Vous pouvez accéder à l'aide depuis le menu inventaire.
|
|
||||||
|
|
||||||
### Objets spéciaux
|
|
||||||
Les objets suivants sont intéressants pour le mode Créatif et pour les constructeurs de cartes d'aventure. Ils ne peuvent être obtenus dans le jeu ou dans l'inventaire créatif.
|
|
||||||
|
|
||||||
* Barrière : `mcl_core:barrier`
|
|
||||||
|
|
||||||
Utilisez la commande de chat `/giveme` pour les obtenir. Voir l'aide interne au jeu pour une explication.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
Ce jeu nécessite [Minetest](http://minetest.net) pour fonctionner (version 5.4.1 ou plus). Vous devez donc installer Minetest d'abord. Seules les versions stables de Minetest sont officielement supportées.
|
|
||||||
Il n'y a pas de support de MineClone2 dans les versions développement de Minetest.
|
|
||||||
|
|
||||||
Pour installer MineClone2 (si ce n'est pas déjà fait), déplacez ce dossier dans le dossier “games” de Minetest. Consultez l'aide de Minetest pour en apprendre plus.
|
|
||||||
|
|
||||||
## Liens utiles
|
|
||||||
Le dépôt de MineClone2 est hébergé sur Mesehub. Pour contribuer ou rapporter des problèmes, aller là-bas.
|
|
||||||
|
|
||||||
* Mesehub: <https://git.minetest.land/MineClone2/MineClone2>
|
|
||||||
* Discord: <https://discord.gg/xE4z8EEpDC>
|
|
||||||
* YouTube <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
|
||||||
* IRC: <https://web.libera.chat/#mineclone2>
|
|
||||||
* Matrix: <https://app.element.io/#/room/#mc2:matrix.org>
|
|
||||||
* Reddit: <https://www.reddit.com/r/MineClone2/>
|
|
||||||
* Minetest forums: <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
|
||||||
* ContentDB: <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
|
||||||
* OpenCollective: <https://opencollective.com/mineclone2>
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
* Créer un clone stable, moddable, libre et gratuit basé sur le moteur de jeu Minetest avec des fonctionalités abouties, utilisable à la fois en mode solo et multijoueur. Actuellement, beaucoup des fonctionalités de **Minecraft Java Edition** sont déjà implémentées et leur amélioration est prioritaire sur les nouvelles demandes.
|
|
||||||
* Avec une priorité moindre, implémenter les fonctionalités des versions **Minecraft + OptiFine** (OtiFine autant que supporté par le moteur Minetest). Cela signifie que les fonctionalités présentes dans les versions listées sont priorisées.
|
|
||||||
* Dans l'idéal, créer une expérience performante qui tourne bien sur des ordinateurs à basse performance. Malheureusement, en raison des mécanismes de Minecraft et des limitations du moteur Minetest ainsi que de la petite taille de la communauté de joueurs sur des ordinateurs à basse performances, les optimisations sont difficiles à explorer.
|
|
||||||
|
|
||||||
## Statut de complétion
|
|
||||||
Ce jeu est actuellement au stade **beta**.
|
|
||||||
Il est jouable mais incomplet en fonctionalités.
|
|
||||||
La rétro-compatibilité n'est pas entièrement garantie, mettre votre monde à jour peut causer de petits bugs.
|
|
||||||
Si vous voulez utiliser la version de développement de MineClone2 en production, la branche master est habituellement relativement stable. Les branches de test fusionnent souvent des pull requests expérimentales et doivent être considérées comme moins stable.
|
|
||||||
|
|
||||||
Les principales fonctionalités suivantes sont disponibles :
|
|
||||||
|
|
||||||
* Outils, armes
|
|
||||||
* Armure
|
|
||||||
* Système de fabrication : grille 2x2, table d'artisanat (grille 3x3), four, incluant un guide de fabrication
|
|
||||||
* Coffres, grands coffres, coffre ender, boite de shulker
|
|
||||||
* Fours, entonnoirs
|
|
||||||
* Faim
|
|
||||||
* La plupart des monstres et animaux
|
|
||||||
* Tout les minerais de Minecraft
|
|
||||||
* La plupart des blocs de l'overworld
|
|
||||||
* Eau et lave
|
|
||||||
* Météo
|
|
||||||
* 28 biomes + 5 biomes du nether
|
|
||||||
* Le Nether, monde souterrain brûlant dans une autre dimension
|
|
||||||
* Circuits Redstone (partiel)
|
|
||||||
* Effets de Statut (partiel)
|
|
||||||
* Expérience
|
|
||||||
* Enchantement
|
|
||||||
* Brassage, potions, flèches trempées (partiel)
|
|
||||||
* Bâteaux
|
|
||||||
* Feu
|
|
||||||
* Blocs de construction : escaliers, dalles, portes, trappes, barrière, portillon, muret
|
|
||||||
* Horloge
|
|
||||||
* Boussole
|
|
||||||
* Eponge
|
|
||||||
* Bloc de slime
|
|
||||||
* Petites plantes et pousses
|
|
||||||
* Teintures
|
|
||||||
* Bannières
|
|
||||||
* Blocs de décoration : verre, verre teinté, vitres, barres de fer, terre cuites (et couleurs), têtes et plus
|
|
||||||
* Cadres d'objets
|
|
||||||
* Juke-boxes
|
|
||||||
* Livres pour écrire
|
|
||||||
* Commandes
|
|
||||||
* Villages
|
|
||||||
* L'End
|
|
||||||
* et plus !
|
|
||||||
|
|
||||||
Les fonctionalités suivantes sont incomplètes :
|
|
||||||
|
|
||||||
* certains monstres et animaux
|
|
||||||
* certains composants de Redstone
|
|
||||||
* Wagonnets spéciaux
|
|
||||||
* quelques blocs et objets non-triviaux
|
|
||||||
|
|
||||||
Fonctionalités bonus (absentes de Minecraft) :
|
|
||||||
|
|
||||||
* Guide d'artisanat intégré au jeu qui montre les recettes d'artisanat et de cuisson
|
|
||||||
* Système d'aide intégré au jeu contenant des informations à propos des techniques de base, blocs, objets et plus
|
|
||||||
* Recettes d'artisanat temporaires. Elles existent uniquement pour rendre des objets accessibles qui ne le seraient pas autrement sauf en mode créatif. Elles seront retirées au cours de l'avancement du développement et de l'ajout de nouvelles fonctionalités.
|
|
||||||
* Pousses dans les coffres en mapgen v6
|
|
||||||
* Entièrement moddable (grâce la puissante API lua de Minetest)
|
|
||||||
* Nouveaux blocs et objets :
|
|
||||||
* Outil de recherche, montre l'aide de ce qu'il touche
|
|
||||||
* Plus de dalles et d'escaliers
|
|
||||||
* Portillon en briques du Nether
|
|
||||||
* Barrière en briques du Nether rouges
|
|
||||||
* Portillon en briques du Nether rouges
|
|
||||||
* Structures de remplacement - ces petites variantes de structures de Minecraft servent de remplacement en attendant qu'on arrive à en faire fonctionner de plus grandes :
|
|
||||||
* Cabine dans les bois (Manoir des bois)
|
|
||||||
* Avant-poste du Nether (Forteresse)
|
|
||||||
|
|
||||||
Différences techniques avec Minecraft :
|
|
||||||
* Limite en hauteur de 31000 blocs (bien plus grand que Minecraft)
|
|
||||||
* Taille horizontale du monde 62000×62000 blocs (bien plus petit que Minecraft mais toujours très grand)
|
|
||||||
* Toujours assez incomplet et buggé
|
|
||||||
* Des blocs, objets, ennemis et fonctionalités manquent
|
|
||||||
* Quelques objets ont des noms légèrement différents pour être plus faciles à distinguer
|
|
||||||
* Des musiques différentes pour le juke-boxe
|
|
||||||
* Des textures différentes (Pixel Perfection)
|
|
||||||
* Des sons différents (sources diverses)
|
|
||||||
* Un moteur de jeu différent (Minetest)
|
|
||||||
* Des bonus cachés différents
|
|
||||||
...et enfin MineClone2 est un logiciel libre !
|
|
||||||
|
|
||||||
## Autres fichiers readme
|
|
||||||
|
|
||||||
* `LICENSE.txt`: Le texte de la license GPLv3
|
|
||||||
* `CONTRIBUTING.md`: Information pour ceux qui veulent contribuer
|
|
||||||
* `API.md`: Pour les modders Minetest qui veulent modder ce jeu
|
|
||||||
* `LEGAL.md`: Information légale
|
|
||||||
* `CREDITS.md`: Liste des contributeurs
|
|
|
@ -1,2 +1,2 @@
|
||||||
title = MineClone 2
|
name = MineClone 2
|
||||||
description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more.
|
description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more.
|
||||||
|
|
|
@ -33,8 +33,6 @@ mcl_damage = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local damage_enabled = minetest.settings:get_bool("enabled_damage",true)
|
|
||||||
|
|
||||||
function mcl_damage.register_modifier(func, priority)
|
function mcl_damage.register_modifier(func, priority)
|
||||||
table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0})
|
table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0})
|
||||||
end
|
end
|
||||||
|
@ -141,7 +139,6 @@ function mcl_damage.register_type(name, def)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
||||||
if not damage_enabled then return 0 end
|
|
||||||
if hp_change < 0 then
|
if hp_change < 0 then
|
||||||
if player:get_hp() <= 0 then
|
if player:get_hp() <= 0 then
|
||||||
return 0
|
return 0
|
||||||
|
@ -152,7 +149,6 @@ minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
||||||
end, true)
|
end, true)
|
||||||
|
|
||||||
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
||||||
if not damage_enabled then return 0 end
|
|
||||||
if player:get_hp() > 0 then
|
if player:get_hp() > 0 then
|
||||||
mt_reason.approved = true
|
mt_reason.approved = true
|
||||||
if hp_change < 0 then
|
if hp_change < 0 then
|
||||||
|
@ -165,9 +161,9 @@ minetest.register_on_dieplayer(function(player, mt_reason)
|
||||||
if mt_reason.approved then
|
if mt_reason.approved then
|
||||||
mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason))
|
mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason))
|
||||||
end
|
end
|
||||||
minetest.log("action","Player "..player:get_player_name().." died at "..minetest.pos_to_string(vector.round(player:get_pos())))
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
minetest.register_on_mods_loaded(function()
|
minetest.register_on_mods_loaded(function()
|
||||||
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
|
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
@ -337,6 +337,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc
|
||||||
if not obj:is_player() then
|
if not obj:is_player() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
|
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
|
||||||
|
|
||||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||||
|
|
|
@ -162,8 +162,7 @@ end
|
||||||
mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border
|
mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border
|
||||||
mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit
|
mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit
|
||||||
mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000
|
mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000
|
||||||
mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 64, z = 0 }
|
mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 74, z = 0 }
|
||||||
mcl_vars.mg_end_exit_portal_pos = vector.new(0, mcl_vars.mg_end_min + 71, 0)
|
|
||||||
|
|
||||||
-- Realm barrier used to safely separate the End from the void below the Overworld
|
-- Realm barrier used to safely separate the End from the void below the Overworld
|
||||||
mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max
|
mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max
|
||||||
|
|
Before Width: | Height: | Size: 144 B |
|
@ -610,95 +610,3 @@ function mcl_util.get_pointed_thing(player, liquid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This following part is 2 wrapper functions + helpers for
|
|
||||||
-- object:set_bones
|
|
||||||
-- and player:set_properties preventing them from being resent on
|
|
||||||
-- every globalstep when they have not changed.
|
|
||||||
|
|
||||||
local function roundN(n, d)
|
|
||||||
if type(n) ~= "number" then return n end
|
|
||||||
local m = 10^d
|
|
||||||
return math.floor(n * m + 0.5) / m
|
|
||||||
end
|
|
||||||
|
|
||||||
local function close_enough(a,b)
|
|
||||||
local rt=true
|
|
||||||
if type(a) == "table" and type(b) == "table" then
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
if roundN(v,2) ~= roundN(b[k],2) then
|
|
||||||
rt=false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
rt = roundN(a,2) == roundN(b,2)
|
|
||||||
end
|
|
||||||
return rt
|
|
||||||
end
|
|
||||||
|
|
||||||
local function props_changed(props,oldprops)
|
|
||||||
local changed=false
|
|
||||||
local p={}
|
|
||||||
for k,v in pairs(props) do
|
|
||||||
if not close_enough(v,oldprops[k]) then
|
|
||||||
p[k]=v
|
|
||||||
changed=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return changed,p
|
|
||||||
end
|
|
||||||
|
|
||||||
--tests for roundN
|
|
||||||
local test_round1=15
|
|
||||||
local test_round2=15.00199999999
|
|
||||||
local test_round3=15.00111111
|
|
||||||
local test_round4=15.00999999
|
|
||||||
|
|
||||||
assert(roundN(test_round1,2)==roundN(test_round1,2))
|
|
||||||
assert(roundN(test_round1,2)==roundN(test_round2,2))
|
|
||||||
assert(roundN(test_round1,2)==roundN(test_round3,2))
|
|
||||||
assert(roundN(test_round1,2)~=roundN(test_round4,2))
|
|
||||||
|
|
||||||
-- tests for close_enough
|
|
||||||
local test_cb = {-0.35,0,-0.35,0.35,0.8,0.35} --collisionboxes
|
|
||||||
local test_cb_close = {-0.351213,0,-0.35,0.35,0.8,0.351212}
|
|
||||||
local test_cb_diff = {-0.35,0,-1.35,0.35,0.8,0.35}
|
|
||||||
|
|
||||||
local test_eh = 1.65 --eye height
|
|
||||||
local test_eh_close = 1.65123123
|
|
||||||
local test_eh_diff = 1.35
|
|
||||||
|
|
||||||
local test_nt = { r = 225, b = 225, a = 225, g = 225 } --nametag
|
|
||||||
local test_nt_diff = { r = 225, b = 225, a = 0, g = 225 }
|
|
||||||
|
|
||||||
assert(close_enough(test_cb,test_cb_close))
|
|
||||||
assert(not close_enough(test_cb,test_cb_diff))
|
|
||||||
assert(close_enough(test_eh,test_eh_close))
|
|
||||||
assert(not close_enough(test_eh,test_eh_diff))
|
|
||||||
assert(not close_enough(test_nt,test_nt_diff)) --no floats involved here
|
|
||||||
|
|
||||||
--tests for properties_changed
|
|
||||||
local test_properties_set1={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
|
|
||||||
local test_properties_set2={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
|
|
||||||
|
|
||||||
local test_p1,_=props_changed(test_properties_set1,test_properties_set1)
|
|
||||||
local test_p2,_=props_changed(test_properties_set1,test_properties_set2)
|
|
||||||
|
|
||||||
assert(not test_p1)
|
|
||||||
assert(test_p2)
|
|
||||||
|
|
||||||
function mcl_util.set_properties(obj,props)
|
|
||||||
local changed,p=props_changed(props,obj:get_properties())
|
|
||||||
if changed then
|
|
||||||
obj:set_properties(p)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_util.set_bone_position(obj,b,p,r) --bone,position,rotation
|
|
||||||
local oldp,oldr=obj:get_bone_position(b)
|
|
||||||
if vector.equals(vector.round(oldp),vector.round(p)) and vector.equals(vector.round(oldr),vector.round(r)) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
obj:set_bone_position(b,p,r)
|
|
||||||
end
|
|
||||||
|
|
|
@ -28,10 +28,11 @@ end)
|
||||||
local timer = 0
|
local timer = 0
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
timer = timer + dtime
|
timer = timer + dtime
|
||||||
if timer >= 0.6 then
|
if timer >= 0.3 then
|
||||||
for _, player in pairs(get_connected_players()) do
|
for _, player in pairs(get_connected_players()) do
|
||||||
local ppos = player:get_pos()
|
local ppos = player:get_pos()
|
||||||
local npos = vector.add(ppos, vector.new(0, -0.1, 0))
|
ppos.y = ceil(ppos.y)
|
||||||
|
local npos = vector.add(ppos, vector.new(0, -1, 0))
|
||||||
if npos then
|
if npos then
|
||||||
local node = get_node(npos)
|
local node = get_node(npos)
|
||||||
if node then
|
if node then
|
||||||
|
|
|
@ -13,21 +13,11 @@ local function is_group(pos, group)
|
||||||
end
|
end
|
||||||
|
|
||||||
local is_water = flowlib.is_water
|
local is_water = flowlib.is_water
|
||||||
local function is_river_water(p)
|
|
||||||
local n = minetest.get_node(p).name
|
|
||||||
if n == "mclx_core:river_water_source" or n == "mclx_core:river_water_flowing" then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function is_ice(pos)
|
local function is_ice(pos)
|
||||||
return is_group(pos, "ice")
|
return is_group(pos, "ice")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function is_fire(pos)
|
|
||||||
return is_group(pos, "set_on_fire")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_sign(i)
|
local function get_sign(i)
|
||||||
if i == 0 then
|
if i == 0 then
|
||||||
return 0
|
return 0
|
||||||
|
@ -120,11 +110,9 @@ end
|
||||||
|
|
||||||
local boat = {
|
local boat = {
|
||||||
physical = true,
|
physical = true,
|
||||||
pointable = true,
|
|
||||||
-- Warning: Do not change the position of the collisionbox top surface,
|
-- Warning: Do not change the position of the collisionbox top surface,
|
||||||
-- lowering it causes the boat to fall through the world if underwater
|
-- lowering it causes the boat to fall through the world if underwater
|
||||||
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
|
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
|
||||||
selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.3, 0.7},
|
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mcl_boats_boat.b3d",
|
mesh = "mcl_boats_boat.b3d",
|
||||||
textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"},
|
textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"},
|
||||||
|
@ -206,8 +194,6 @@ end
|
||||||
|
|
||||||
function boat.on_step(self, dtime, moveresult)
|
function boat.on_step(self, dtime, moveresult)
|
||||||
mcl_burning.tick(self.object, dtime, self)
|
mcl_burning.tick(self.object, dtime, self)
|
||||||
-- mcl_burning.tick may remove object immediately
|
|
||||||
if not self.object:get_pos() then return end
|
|
||||||
|
|
||||||
self._v = get_v(self.object:get_velocity()) * get_sign(self._v)
|
self._v = get_v(self.object:get_velocity()) * get_sign(self._v)
|
||||||
local v_factor = 1
|
local v_factor = 1
|
||||||
|
@ -216,21 +202,16 @@ function boat.on_step(self, dtime, moveresult)
|
||||||
local on_water = true
|
local on_water = true
|
||||||
local on_ice = false
|
local on_ice = false
|
||||||
local in_water = is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})
|
local in_water = is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})
|
||||||
local in_river_water = is_river_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})
|
|
||||||
local waterp = {x=p.x, y=p.y-boat_y_offset - 0.1, z=p.z}
|
local waterp = {x=p.x, y=p.y-boat_y_offset - 0.1, z=p.z}
|
||||||
if not is_water(waterp) then
|
if not is_water(waterp) then
|
||||||
on_water = false
|
on_water = false
|
||||||
if not in_water and is_ice(waterp) then
|
if not in_water and is_ice(waterp) then
|
||||||
on_ice = true
|
on_ice = true
|
||||||
elseif is_fire({x=p.x, y=p.y-boat_y_offset, z=p.z}) then
|
|
||||||
boat.on_death(self, nil)
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
else
|
else
|
||||||
v_slowdown = 0.04
|
v_slowdown = 0.04
|
||||||
v_factor = 0.5
|
v_factor = 0.5
|
||||||
end
|
end
|
||||||
elseif in_water and not in_river_water then
|
elseif in_water then
|
||||||
on_water = false
|
on_water = false
|
||||||
in_water = true
|
in_water = true
|
||||||
v_factor = 0.75
|
v_factor = 0.75
|
||||||
|
@ -362,18 +343,7 @@ function boat.on_step(self, dtime, moveresult)
|
||||||
else
|
else
|
||||||
p.y = p.y + 1
|
p.y = p.y + 1
|
||||||
local is_obsidian_boat = self.object:get_luaentity()._itemstring == "mcl_boats:boat_obsidian"
|
local is_obsidian_boat = self.object:get_luaentity()._itemstring == "mcl_boats:boat_obsidian"
|
||||||
if is_river_water(p) then
|
if is_water(p) or is_obsidian_boat then
|
||||||
local y = self.object:get_velocity().y
|
|
||||||
if y >= 5 then
|
|
||||||
y = 5
|
|
||||||
elseif y < 0 then
|
|
||||||
new_acce = {x = 0, y = 10, z = 0}
|
|
||||||
else
|
|
||||||
new_acce = {x = 0, y = 2, z = 0}
|
|
||||||
end
|
|
||||||
new_velo = get_velocity(self._v, self.object:get_yaw(), y)
|
|
||||||
self.object:set_pos(self.object:get_pos())
|
|
||||||
elseif is_water(p) and not is_river_water(p) or is_obsidian_boat then
|
|
||||||
-- Inside water: Slowly sink
|
-- Inside water: Slowly sink
|
||||||
local y = self.object:get_velocity().y
|
local y = self.object:get_velocity().y
|
||||||
y = y - 0.01
|
y = y - 0.01
|
||||||
|
@ -413,21 +383,13 @@ end
|
||||||
-- Register one entity for all boat types
|
-- Register one entity for all boat types
|
||||||
minetest.register_entity("mcl_boats:boat", boat)
|
minetest.register_entity("mcl_boats:boat", boat)
|
||||||
|
|
||||||
local cboat = table.copy(boat)
|
local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian" }
|
||||||
cboat.mesh = "mcl_boats_boat_with_chest.b3d"
|
local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat") }
|
||||||
cboat.textures = {"mcl_boats_texture_oak_chest_boat.png", "mcl_boats_texture_oak_chest_boat.png", "mcl_boats_texture_oak_chest_boat.png", "mcl_boats_texture_oak_chest_boat.png", "mcl_boats_texture_oak_chest_boat.png"}
|
|
||||||
cboat._itemstring = "mcl_boats:chest_boat"
|
|
||||||
|
|
||||||
minetest.register_entity("mcl_boats:chest_boat", cboat)
|
|
||||||
mcl_entity_invs.register_inv("mcl_boats:chest_boat","Boat",27)
|
|
||||||
|
|
||||||
local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian", "boat_mangrove", "chest_boat", "chest_boat_spruce", "chest_boat_birch", "chest_boat_jungle", "chest_boat_acacia", "chest_boat_dark_oak", "chest_boat_mangrove" }
|
|
||||||
local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat"), S("Mangrove Boat"), S("Oak Chest Boat"), S("Spruce Chest Boat"), S("Birch Chest Boat"), S("Jungle Chest Boat"), S("Acacia Chest Boat"), S("Dark Oak Chest Boat"), S("Mangrove Chest Boat") }
|
|
||||||
local craftstuffs = {}
|
local craftstuffs = {}
|
||||||
if minetest.get_modpath("mcl_core") then
|
if minetest.get_modpath("mcl_core") then
|
||||||
craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian", "mcl_mangrove:mangrove_wood" }
|
craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian" }
|
||||||
end
|
end
|
||||||
local images = { "oak", "spruce", "birch", "jungle", "acacia", "dark_oak", "obsidian", "mangrove", "oak_chest", "spruce_chest", "birch_chest", "jungle_chest", "acacia_chest", "dark_oak_chest", "mangrove_chest" }
|
local images = { "oak", "spruce", "birch", "jungle", "acacia", "dark_oak", "obsidian" }
|
||||||
|
|
||||||
for b=1, #boat_ids do
|
for b=1, #boat_ids do
|
||||||
local itemstring = "mcl_boats:"..boat_ids[b]
|
local itemstring = "mcl_boats:"..boat_ids[b]
|
||||||
|
@ -477,11 +439,7 @@ for b=1, #boat_ids do
|
||||||
else
|
else
|
||||||
pos = vector.add(pos, vector.multiply(dir, boat_y_offset_ground))
|
pos = vector.add(pos, vector.multiply(dir, boat_y_offset_ground))
|
||||||
end
|
end
|
||||||
local boat_ent = "mcl_boats:boat"
|
local boat = minetest.add_entity(pos, "mcl_boats:boat")
|
||||||
if itemstring:find("chest") then
|
|
||||||
boat_ent = "mcl_boats:chest_boat"
|
|
||||||
end
|
|
||||||
local boat = minetest.add_entity(pos, boat_ent)
|
|
||||||
local texture = "mcl_boats_texture_"..images[b].."_boat.png"
|
local texture = "mcl_boats_texture_"..images[b].."_boat.png"
|
||||||
boat:get_luaentity()._itemstring = itemstring
|
boat:get_luaentity()._itemstring = itemstring
|
||||||
boat:set_properties({textures = { texture, texture, texture, texture, texture }})
|
boat:set_properties({textures = { texture, texture, texture, texture, texture }})
|
||||||
|
@ -504,14 +462,6 @@ for b=1, #boat_ids do
|
||||||
})
|
})
|
||||||
|
|
||||||
local c = craftstuffs[b]
|
local c = craftstuffs[b]
|
||||||
if not itemstring:find("chest") then
|
|
||||||
minetest.register_craft({
|
|
||||||
output = itemstring:gsub(":boat",":chest_boat"),
|
|
||||||
recipe = {
|
|
||||||
{"mcl_chests:chest"},
|
|
||||||
{itemstring},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = itemstring,
|
output = itemstring,
|
||||||
recipe = {
|
recipe = {
|
||||||
|
@ -519,7 +469,6 @@ for b=1, #boat_ids do
|
||||||
{c, c, c},
|
{c, c, c},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
|
|
@ -9,5 +9,4 @@ Oak Boat=Bateau en Chêne
|
||||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
|
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
|
||||||
Spruce Boat=Bateau en Sapin
|
Spruce Boat=Bateau en Sapin
|
||||||
Water vehicle=Véhicule aquatique
|
Water vehicle=Véhicule aquatique
|
||||||
Sneak to dismount=Se baisser pour descendre
|
Sneak to dismount=
|
||||||
Obsidian Boat=Bateau en Obsidienne
|
|
|
@ -10,4 +10,3 @@ Rightclick on a water source to place the boat. Rightclick the boat to enter it.
|
||||||
Spruce Boat=
|
Spruce Boat=
|
||||||
Water vehicle=
|
Water vehicle=
|
||||||
Sneak to dismount=
|
Sneak to dismount=
|
||||||
Obsidian Boat=
|
|
|
@ -1,5 +1,7 @@
|
||||||
name = mcl_boats
|
name = mcl_boats
|
||||||
author = PilzAdam
|
author = PilzAdam
|
||||||
description = Adds drivable boats.
|
description = Adds drivable boats.
|
||||||
depends = mcl_player, flowlib, mcl_title, mcl_entity_invs
|
depends = mcl_player, flowlib, mcl_title
|
||||||
optional_depends = mcl_core, doc_identifier
|
optional_depends = mcl_core, doc_identifier
|
||||||
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1,5 +1,3 @@
|
||||||
local enable_damage = minetest.settings:get_bool("enable_damage")
|
|
||||||
|
|
||||||
function mcl_burning.get_storage(obj)
|
function mcl_burning.get_storage(obj)
|
||||||
return obj:is_player() and mcl_burning.storage[obj] or obj:get_luaentity()
|
return obj:is_player() and mcl_burning.storage[obj] or obj:get_luaentity()
|
||||||
end
|
end
|
||||||
|
@ -79,7 +77,7 @@ end
|
||||||
-- The effective burn duration is modified by obj's armor protection.
|
-- The effective burn duration is modified by obj's armor protection.
|
||||||
-- If obj was already burning, its burn duration is updated if the current
|
-- If obj was already burning, its burn duration is updated if the current
|
||||||
-- duration is less than burn_time.
|
-- duration is less than burn_time.
|
||||||
-- If obj is dead, fireproof or enable_damage is disabled, this function does nothing.
|
-- If obj is dead, fireproof or a creative player, this function does nothing.
|
||||||
--
|
--
|
||||||
function mcl_burning.set_on_fire(obj, burn_time)
|
function mcl_burning.set_on_fire(obj, burn_time)
|
||||||
if obj:get_hp() < 0 then
|
if obj:get_hp() < 0 then
|
||||||
|
@ -91,9 +89,8 @@ function mcl_burning.set_on_fire(obj, burn_time)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if obj:is_player() and not enable_damage then
|
if obj:is_player() and minetest.is_creative_enabled(obj:get_player_name()) then
|
||||||
burn_time = 0
|
burn_time = 0
|
||||||
return
|
|
||||||
else
|
else
|
||||||
local max_fire_prot_lvl = 0
|
local max_fire_prot_lvl = 0
|
||||||
local inv = mcl_util.get_inventory(obj)
|
local inv = mcl_util.get_inventory(obj)
|
||||||
|
@ -137,7 +134,6 @@ function mcl_burning.set_on_fire(obj, burn_time)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_burning.extinguish(obj)
|
function mcl_burning.extinguish(obj)
|
||||||
if not obj:get_pos() then return end
|
|
||||||
if mcl_burning.is_burning(obj) then
|
if mcl_burning.is_burning(obj) then
|
||||||
local storage = mcl_burning.get_storage(obj)
|
local storage = mcl_burning.get_storage(obj)
|
||||||
if obj:is_player() then
|
if obj:is_player() then
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
name = mcl_burning
|
name = mcl_burning
|
||||||
description = Burning Objects for MineClone2
|
description = Burning Objects for MineClone2
|
||||||
author = Fleckenstein
|
author = Fleckenstein
|
||||||
depends = mcl_weather
|
|
|
@ -1,55 +1,66 @@
|
||||||
-- Dripping Water Mod
|
-- Dripping Water Mod
|
||||||
-- by kddekadenz
|
-- by kddekadenz
|
||||||
-- License of code, textures & sounds: CC0
|
|
||||||
|
|
||||||
local math = math
|
local math = math
|
||||||
local function make_drop(pos,liquid,sound,interval)
|
|
||||||
local pt = {
|
|
||||||
velocity = vector.new(0,0,0),
|
|
||||||
collision_removal = false,
|
|
||||||
}
|
|
||||||
local t = math.random() + math.random(1, interval)
|
|
||||||
minetest.after(t,function()
|
|
||||||
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
|
|
||||||
pt.pos = vector.offset(pos,x,-0.52,z)
|
|
||||||
pt.acceleration = vector.new(0,0,0)
|
|
||||||
pt.collisiondetection = false
|
|
||||||
pt.expirationtime = t
|
|
||||||
|
|
||||||
pt.texture="[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"
|
-- License of code, textures & sounds: CC0
|
||||||
minetest.add_particle(pt)
|
|
||||||
minetest.after(t,function()
|
|
||||||
pt.acceleration = vector.new(0,-5,0)
|
|
||||||
pt.collisiondetection = true
|
|
||||||
pt.expirationtime = math.random() + math.random(1, interval/2)
|
|
||||||
minetest.add_particle(pt)
|
|
||||||
minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = pos, gain = 0.5, max_hear_distance = 8}, true)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function register_drop(liquid, glow, sound, nodes, interval, chance)
|
local function register_drop(liquid, glow, sound, nodes)
|
||||||
|
minetest.register_entity("mcl_dripping:drop_" .. liquid, {
|
||||||
|
hp_max = 1,
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false,
|
||||||
|
collisionbox = {-0.01, 0.01, -0.01, 0.01, 0.01, 0.01},
|
||||||
|
glow = glow,
|
||||||
|
pointable = false,
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x = 0.1, y = 0.1},
|
||||||
|
textures = {""},
|
||||||
|
spritediv = {x = 1, y = 1},
|
||||||
|
initial_sprite_basepos = {x = 0, y = 0},
|
||||||
|
static_save = false,
|
||||||
|
_dropped = false,
|
||||||
|
on_activate = function(self)
|
||||||
|
self.object:set_properties({
|
||||||
|
textures = {"[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"}
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
local k = math.random(1, 222)
|
||||||
|
local ownpos = self.object:get_pos()
|
||||||
|
if k == 1 then
|
||||||
|
self.object:set_acceleration(vector.new(0, -5, 0))
|
||||||
|
end
|
||||||
|
if minetest.get_node(vector.offset(ownpos, 0, 0.5, 0)).name == "air" then
|
||||||
|
self.object:set_acceleration(vector.new(0, -5, 0))
|
||||||
|
end
|
||||||
|
if minetest.get_node(vector.offset(ownpos, 0, -0.1, 0)).name ~= "air" then
|
||||||
|
local ent = self.object:get_luaentity()
|
||||||
|
if not ent._dropped then
|
||||||
|
ent._dropped = true
|
||||||
|
minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = ownpos, gain = 0.5, max_hear_distance = 8}, true)
|
||||||
|
end
|
||||||
|
if k < 3 then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
label = "Create drops",
|
label = "Create drops",
|
||||||
nodenames = nodes,
|
nodenames = nodes,
|
||||||
neighbors = {"group:" .. liquid},
|
neighbors = {"group:" .. liquid},
|
||||||
interval = interval,
|
interval = 2,
|
||||||
chance = chance,
|
chance = 22,
|
||||||
action = function(pos)
|
action = function(pos)
|
||||||
local r = math.ceil(interval / 20)
|
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1, 0)).name, liquid) ~= 0
|
||||||
local nn=minetest.find_nodes_in_area(vector.offset(pos,-r,0,-r),vector.offset(pos,r,0,r),nodes)
|
and minetest.get_node(vector.offset(pos, 0, -1, 0)).name == "air" then
|
||||||
--start a bunch of particle cycles to be able to get away
|
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
|
||||||
--with longer abm cycles
|
minetest.add_entity(vector.offset(pos, x, -0.520, z), "mcl_dripping:drop_" .. liquid)
|
||||||
table.shuffle(nn)
|
|
||||||
for i=1,math.random(#nn) do
|
|
||||||
if minetest.get_item_group(minetest.get_node(vector.offset(nn[i], 0, 1, 0)).name, liquid) ~= 0
|
|
||||||
and minetest.get_node(vector.offset(nn[i], 0, -1, 0)).name == "air" then
|
|
||||||
make_drop(nn[i],liquid,sound,interval)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
register_drop("water", 1, "", {"group:opaque", "group:leaves"},60,10)
|
register_drop("water", 1, "", {"group:opaque", "group:leaves"})
|
||||||
register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"},60,10)
|
register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"})
|
|
@ -1,13 +0,0 @@
|
||||||
mcl_entity_invs
|
|
||||||
===============
|
|
||||||
|
|
||||||
Inventories for your entities. It's simple. Depend on mcl_entity_invs and register your entity like so:
|
|
||||||
|
|
||||||
* mcl_entity_invs.register_inv("entity:name","Title shown in formspec",inventory_size,disable_on_righclick)
|
|
||||||
*If disable_on_righclick is true other mods can handle when to show the inventory themselves
|
|
||||||
* The inventory size can be set dynamically by initializing it with an explicit nil
|
|
||||||
|
|
||||||
* mcl_entity_invs.show_inv_form(entity,clicker,[formspec text])
|
|
||||||
* formspec_text is an additional text that is put after the title
|
|
||||||
|
|
||||||
It works by setting up a detached inventory per entity which is accessed by an id/hash generated from the entities position at creation, the progressed gametime at creation and a random salt.
|
|
|
@ -1,170 +0,0 @@
|
||||||
mcl_entity_invs = {}
|
|
||||||
|
|
||||||
local open_invs = {}
|
|
||||||
|
|
||||||
local function check_distance(inv,player,count)
|
|
||||||
for _,o in pairs(minetest.get_objects_inside_radius(player:get_pos(),5)) do
|
|
||||||
local l = o:get_luaentity()
|
|
||||||
if l and l._inv_id and inv:get_location().name == l._inv_id then return count end
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local inv_callbacks = {
|
|
||||||
allow_take = function(inv, listname, index, stack, player)
|
|
||||||
return check_distance(inv,player,stack:get_count())
|
|
||||||
end,
|
|
||||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
|
||||||
return check_distance(inv,player,count)
|
|
||||||
end,
|
|
||||||
allow_put = function(inv, listname, index, stack, player)
|
|
||||||
return check_distance(inv,player,stack:get_count())
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function load_inv(ent,size)
|
|
||||||
if not ent._inv_id then return end
|
|
||||||
local inv = minetest.get_inventory({type="detached", name=ent._inv_id})
|
|
||||||
if not inv then
|
|
||||||
inv = minetest.create_detached_inventory(ent._inv_id, inv_callbacks)
|
|
||||||
inv:set_size("main", size)
|
|
||||||
if ent._items then
|
|
||||||
inv:set_list("main",ent._items)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return inv
|
|
||||||
end
|
|
||||||
|
|
||||||
local function save_inv(ent)
|
|
||||||
if ent._inv then
|
|
||||||
ent._items = {}
|
|
||||||
for i,it in ipairs(ent._inv:get_list("main")) do
|
|
||||||
ent._items[i] = it:to_string()
|
|
||||||
end
|
|
||||||
minetest.remove_detached_inventory(ent._inv_id)
|
|
||||||
ent._inv = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_entity_invs.show_inv_form(ent,player,text)
|
|
||||||
if not ent._inv_id then return end
|
|
||||||
if not open_invs[ent] then
|
|
||||||
open_invs[ent] = 0
|
|
||||||
end
|
|
||||||
text = text or ""
|
|
||||||
ent._inv = load_inv(ent,ent._inv_size)
|
|
||||||
open_invs[ent] = open_invs[ent] + 1
|
|
||||||
local playername = player:get_player_name()
|
|
||||||
local rows = 3
|
|
||||||
local cols = (math.ceil(ent._inv_size/rows))
|
|
||||||
local spacing = (9 - cols) / 2
|
|
||||||
local formspec = "size[9,8.75]"
|
|
||||||
.. "label[0,0;" .. minetest.formspec_escape(
|
|
||||||
minetest.colorize("#313131", ent._inv_title .. " ".. text)) .. "]"
|
|
||||||
.. "list[detached:"..ent._inv_id..";main;"..spacing..",0.5;"..cols..","..rows..";]"
|
|
||||||
.. mcl_formspec.get_itemslot_bg(spacing,0.5,cols,rows)
|
|
||||||
.. "label[0,4.0;" .. minetest.formspec_escape(
|
|
||||||
minetest.colorize("#313131", "Inventory")) .. "]"
|
|
||||||
.. "list[current_player;main;0,4.5;9,3;9]"
|
|
||||||
.. mcl_formspec.get_itemslot_bg(0,4.5,9,3)
|
|
||||||
.. "list[current_player;main;0,7.74;9,1;]"
|
|
||||||
.. mcl_formspec.get_itemslot_bg(0,7.74,9,1)
|
|
||||||
.. "listring[detached:"..ent._inv_id..";main]"
|
|
||||||
.. "listring[current_player;main]"
|
|
||||||
minetest.show_formspec(playername,ent._inv_id,formspec)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drop_inv(ent)
|
|
||||||
if not ent._items then return end
|
|
||||||
local pos = ent.object:get_pos()
|
|
||||||
for i,it in pairs(ent._items) do
|
|
||||||
local p = vector.add(pos,vector.new(math.random() - 0.5, math.random()-0.5, math.random()-0.5))
|
|
||||||
minetest.add_item(p,it)
|
|
||||||
end
|
|
||||||
ent._items = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_remove(self,killer,oldf)
|
|
||||||
save_inv(self)
|
|
||||||
drop_inv(self)
|
|
||||||
if oldf then return oldf(self,killer) end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
||||||
for k,v in pairs(open_invs) do
|
|
||||||
if formname == k._inv_id then
|
|
||||||
open_invs[k] = open_invs[k] - 1
|
|
||||||
if open_invs[k] < 1 then
|
|
||||||
save_inv(k)
|
|
||||||
open_invs[k] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
function mcl_entity_invs.register_inv(entity_name,show_name,size,no_on_righclick)
|
|
||||||
assert(minetest.registered_entities[entity_name],"mcl_entity_invs.register_inv called with invalid entity: "..tostring(entity_name))
|
|
||||||
minetest.registered_entities[entity_name]._inv_size = size
|
|
||||||
minetest.registered_entities[entity_name]._inv_title = show_name
|
|
||||||
|
|
||||||
local old_oa = minetest.registered_entities[entity_name].on_activate
|
|
||||||
minetest.registered_entities[entity_name].on_activate = function(self,staticdata,dtime_s)
|
|
||||||
local r
|
|
||||||
if old_oa then r=old_oa(self,staticdata,dtime_s) end
|
|
||||||
local d = minetest.deserialize(staticdata)
|
|
||||||
if type(d) == "table" and d._inv_id then
|
|
||||||
self._inv_id = d._inv_id
|
|
||||||
self._items = d._items
|
|
||||||
self._inv_size = d._inv_size
|
|
||||||
else
|
|
||||||
self._inv_id="entity_inv_"..minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random()))
|
|
||||||
--gametime and position for collision safety and math.random salt to protect against position brute-force
|
|
||||||
end
|
|
||||||
return r
|
|
||||||
end
|
|
||||||
if not no_on_righclick then
|
|
||||||
local old_rc = minetest.registered_entities[entity_name].on_rightclick
|
|
||||||
minetest.registered_entities[entity_name].on_rightclick = function(self,clicker)
|
|
||||||
mcl_entity_invs.show_inv_form(self,clicker,show_name)
|
|
||||||
if old_rc then return old_rc(self,clicker) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local old_gsd = minetest.registered_entities[entity_name].get_staticdata
|
|
||||||
minetest.registered_entities[entity_name].get_staticdata = function(self)
|
|
||||||
local old_sd = old_gsd(self)
|
|
||||||
local d = minetest.deserialize(old_sd)
|
|
||||||
assert(type(d) == "table","mcl_entity_invs currently only works with entities that return a (serialized) table in get_staticdata. "..tostring(self.name).." returned: "..tostring(old_sd))
|
|
||||||
d._inv_id = self._inv_id
|
|
||||||
d._inv_size = self._inv_size
|
|
||||||
d._items = {}
|
|
||||||
if self._items then
|
|
||||||
for i,it in ipairs(self._items) do
|
|
||||||
d._items[i] = it
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return minetest.serialize(d)
|
|
||||||
end
|
|
||||||
|
|
||||||
local old_ode = minetest.registered_entities[entity_name].on_deactivate
|
|
||||||
minetest.registered_entities[entity_name].on_deactivate = function(self,removal)
|
|
||||||
save_inv(self)
|
|
||||||
if removal then
|
|
||||||
on_remove(self)
|
|
||||||
end
|
|
||||||
if old_ode then return old_ode(self,removal) end
|
|
||||||
end
|
|
||||||
|
|
||||||
local old_od = minetest.registered_entities[entity_name].on_death
|
|
||||||
minetest.registered_entities[entity_name].on_death = function(self,killer)
|
|
||||||
if not self.is_mob then
|
|
||||||
on_remove(self,killer,old_od)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local old_odi = minetest.registered_entities[entity_name].on_die
|
|
||||||
minetest.registered_entities[entity_name].on_die = function(self,killer)
|
|
||||||
if self.is_mob then
|
|
||||||
on_remove(self,killer,old_od)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
name = mcl_entity_invs
|
|
||||||
author = cora
|
|
||||||
depends = mcl_formspec
|
|
|
@ -59,10 +59,6 @@ mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
|
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
|
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
|
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_core:crying_obsidian", "mcl:whosCuttingOnions")
|
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_nether:ancient_debris", "mcl:hiddenInTheDepths")
|
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_end:dragon_egg", "mcl:PickUpDragonEgg")
|
|
||||||
mcl_item_entity.register_pickup_achievement("mcl_armor:elytra", "mcl:skysTheLimit")
|
|
||||||
|
|
||||||
local function check_pickup_achievements(object, player)
|
local function check_pickup_achievements(object, player)
|
||||||
if has_awards then
|
if has_awards then
|
||||||
|
@ -82,6 +78,7 @@ local function enable_physics(object, luaentity, ignore_check)
|
||||||
object:set_properties({
|
object:set_properties({
|
||||||
physical = true
|
physical = true
|
||||||
})
|
})
|
||||||
|
object:set_velocity({x=0,y=0,z=0})
|
||||||
object:set_acceleration({x=0,y=-get_gravity(),z=0})
|
object:set_acceleration({x=0,y=-get_gravity(),z=0})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -320,14 +317,18 @@ function minetest.handle_node_drops(pos, drops, digger)
|
||||||
-- Spawn item and apply random speed
|
-- Spawn item and apply random speed
|
||||||
local obj = minetest.add_item(dpos, drop_item)
|
local obj = minetest.add_item(dpos, drop_item)
|
||||||
if obj then
|
if obj then
|
||||||
-- set the velocity multiplier to the stored amount or if the game dug this node, apply a bigger velocity
|
local x = math.random(1, 5)
|
||||||
local v = 1
|
if math.random(1,2) == 1 then
|
||||||
if digger and digger:is_player() then
|
x = -x
|
||||||
obj:get_luaentity().random_velocity = 1
|
|
||||||
else
|
|
||||||
obj:get_luaentity().random_velocity = 1.6
|
|
||||||
end
|
end
|
||||||
|
local z = math.random(1, 5)
|
||||||
|
if math.random(1,2) == 1 then
|
||||||
|
z = -z
|
||||||
|
end
|
||||||
|
obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z})
|
||||||
|
|
||||||
obj:get_luaentity().age = item_drop_settings.dug_buffer
|
obj:get_luaentity().age = item_drop_settings.dug_buffer
|
||||||
|
|
||||||
obj:get_luaentity()._insta_collect = false
|
obj:get_luaentity()._insta_collect = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -406,33 +407,9 @@ minetest.register_entity(":__builtin:item", {
|
||||||
-- Number of seconds this item entity has existed so far
|
-- Number of seconds this item entity has existed so far
|
||||||
age = 0,
|
age = 0,
|
||||||
|
|
||||||
-- Multiplier for initial random velocity when the item is spawned
|
|
||||||
random_velocity = 1,
|
|
||||||
|
|
||||||
-- How old it has become in the collection animation
|
-- How old it has become in the collection animation
|
||||||
collection_age = 0,
|
collection_age = 0,
|
||||||
|
|
||||||
-- Function to apply a random velocity
|
|
||||||
apply_random_vel = function(self, speed)
|
|
||||||
if not self or not self.object or not self.object:get_luaentity() then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- if you passed a value then use that for the velocity multiplier
|
|
||||||
if speed ~= nil then self.random_velocity = speed end
|
|
||||||
|
|
||||||
local vel = self.object:get_velocity()
|
|
||||||
if vel and vel.x == 0 and vel.z == 0 and self.random_velocity > 0 then
|
|
||||||
local v = self.random_velocity
|
|
||||||
local x = math.random(5, 10) / 10 * v
|
|
||||||
if math.random(0,10) < 5 then x = -x end
|
|
||||||
local z = math.random(5, 10) / 10 * v
|
|
||||||
if math.random(0,10) < 5 then z = -z end
|
|
||||||
local y = math.random(2,4)
|
|
||||||
self.object:set_velocity({x=x, y=y, z=z})
|
|
||||||
end
|
|
||||||
self.random_velocity = 0
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_item = function(self, itemstring)
|
set_item = function(self, itemstring)
|
||||||
self.itemstring = itemstring
|
self.itemstring = itemstring
|
||||||
if self.itemstring == "" then
|
if self.itemstring == "" then
|
||||||
|
@ -485,9 +462,27 @@ minetest.register_entity(":__builtin:item", {
|
||||||
glow = glow,
|
glow = glow,
|
||||||
}
|
}
|
||||||
self.object:set_properties(prop)
|
self.object:set_properties(prop)
|
||||||
if item_drop_settings.random_item_velocity == true and self.age < 1 then
|
if item_drop_settings.random_item_velocity == true then
|
||||||
minetest.after(0, self.apply_random_vel, self)
|
minetest.after(0, function(self)
|
||||||
|
if not self or not self.object or not self.object:get_luaentity() then
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
local vel = self.object:get_velocity()
|
||||||
|
if vel and vel.x == 0 and vel.z == 0 then
|
||||||
|
local x = math.random(1, 5)
|
||||||
|
if math.random(1,2) == 1 then
|
||||||
|
x = -x
|
||||||
|
end
|
||||||
|
local z = math.random(1, 5)
|
||||||
|
if math.random(1,2) == 1 then
|
||||||
|
z = -z
|
||||||
|
end
|
||||||
|
local y = math.random(2,4)
|
||||||
|
self.object:set_velocity({x=1/x, y=y, z=1/z})
|
||||||
|
end
|
||||||
|
end, self)
|
||||||
|
end
|
||||||
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
@ -541,9 +536,9 @@ minetest.register_entity(":__builtin:item", {
|
||||||
self.itemstring = data.itemstring
|
self.itemstring = data.itemstring
|
||||||
self.always_collect = data.always_collect
|
self.always_collect = data.always_collect
|
||||||
if data.age then
|
if data.age then
|
||||||
self.age = data.age
|
self.age = data.age + dtime_s
|
||||||
else
|
else
|
||||||
self.age = self.age
|
self.age = dtime_s
|
||||||
end
|
end
|
||||||
--remember collection data
|
--remember collection data
|
||||||
-- If true, can collect item without delay
|
-- If true, can collect item without delay
|
||||||
|
@ -576,7 +571,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
self._forcetimer = 0
|
self._forcetimer = 0
|
||||||
|
|
||||||
self.object:set_armor_groups({immortal = 1})
|
self.object:set_armor_groups({immortal = 1})
|
||||||
-- self.object:set_velocity({x = 0, y = 2, z = 0})
|
self.object:set_velocity({x = 0, y = 2, z = 0})
|
||||||
self.object:set_acceleration({x = 0, y = -get_gravity(), z = 0})
|
self.object:set_acceleration({x = 0, y = -get_gravity(), z = 0})
|
||||||
self:set_item(self.itemstring)
|
self:set_item(self.itemstring)
|
||||||
end,
|
end,
|
||||||
|
@ -606,13 +601,12 @@ minetest.register_entity(":__builtin:item", {
|
||||||
end
|
end
|
||||||
-- Merge the remote stack into this one
|
-- Merge the remote stack into this one
|
||||||
|
|
||||||
-- local pos = object:get_pos()
|
local pos = object:get_pos()
|
||||||
-- pos.y = pos.y + ((total_count - count) / max_count) * 0.15
|
pos.y = pos.y + ((total_count - count) / max_count) * 0.15
|
||||||
-- self.object:move_to(pos)
|
self.object:move_to(pos)
|
||||||
|
|
||||||
self.age = 0 -- Handle as new entity
|
self.age = 0 -- Handle as new entity
|
||||||
own_stack:set_count(total_count)
|
own_stack:set_count(total_count)
|
||||||
self.random_velocity = 0
|
|
||||||
self:set_item(own_stack:to_string())
|
self:set_item(own_stack:to_string())
|
||||||
|
|
||||||
entity._removed = true
|
entity._removed = true
|
||||||
|
@ -651,53 +645,33 @@ minetest.register_entity(":__builtin:item", {
|
||||||
local node = minetest.get_node_or_nil(p)
|
local node = minetest.get_node_or_nil(p)
|
||||||
local in_unloaded = (node == nil)
|
local in_unloaded = (node == nil)
|
||||||
|
|
||||||
if in_unloaded then
|
|
||||||
-- Don't infinetly fall into unloaded map
|
|
||||||
disable_physics(self.object, self)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.is_clock then
|
if self.is_clock then
|
||||||
self.object:set_properties({
|
self.object:set_properties({
|
||||||
textures = {"mcl_clock:clock_" .. (mcl_worlds.clock_works(p) and mcl_clock.old_time or mcl_clock.random_frame)}
|
textures = {"mcl_clock:clock_" .. (mcl_worlds.clock_works(p) and mcl_clock.old_time or mcl_clock.random_frame)}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
local nn = node.name
|
|
||||||
local is_in_water = (minetest.get_item_group(nn, "liquid") ~= 0)
|
|
||||||
local nn_above = minetest.get_node({x=p.x, y=p.y+0.1, z=p.z}).name
|
|
||||||
-- make sure it's more or less stationary and is at water level
|
|
||||||
local sleep_threshold = 0.3
|
|
||||||
local is_floating = false
|
|
||||||
local is_stationary = math.abs(self.object:get_velocity().x) < sleep_threshold
|
|
||||||
and math.abs(self.object:get_velocity().y) < sleep_threshold
|
|
||||||
and math.abs(self.object:get_velocity().z) < sleep_threshold
|
|
||||||
if is_in_water and is_stationary then
|
|
||||||
is_floating = (is_in_water
|
|
||||||
and (minetest.get_item_group(nn_above, "liquid") == 0))
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_floating and self.physical_state == true then
|
|
||||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
|
||||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
|
||||||
disable_physics(self.object, self)
|
|
||||||
end
|
|
||||||
-- If no collector was found for a long enough time, declare the magnet as disabled
|
-- If no collector was found for a long enough time, declare the magnet as disabled
|
||||||
if self._magnet_active and (self._collector_timer == nil or (self._collector_timer > item_drop_settings.magnet_time)) then
|
if self._magnet_active and (self._collector_timer == nil or (self._collector_timer > item_drop_settings.magnet_time)) then
|
||||||
self._magnet_active = false
|
self._magnet_active = false
|
||||||
enable_physics(self.object, self)
|
enable_physics(self.object, self)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if in_unloaded then
|
||||||
|
-- Don't infinetly fall into unloaded map
|
||||||
|
disable_physics(self.object, self)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Destroy item in lava, fire or special nodes
|
-- Destroy item in lava, fire or special nodes
|
||||||
|
local nn = node.name
|
||||||
local def = minetest.registered_nodes[nn]
|
local def = minetest.registered_nodes[nn]
|
||||||
local lg = minetest.get_item_group(nn, "lava")
|
local lg = minetest.get_item_group(nn, "lava")
|
||||||
local fg = minetest.get_item_group(nn, "fire")
|
local fg = minetest.get_item_group(nn, "fire")
|
||||||
local dg = minetest.get_item_group(nn, "destroys_items")
|
local dg = minetest.get_item_group(nn, "destroys_items")
|
||||||
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
|
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
|
||||||
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
|
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
|
||||||
if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then
|
if self.age > 2 then
|
||||||
if dg ~= 2 then
|
if dg ~= 2 then
|
||||||
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
|
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
|
||||||
end
|
end
|
||||||
|
@ -720,7 +694,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Push item out when stuck inside solid opaque node
|
-- Push item out when stuck inside solid opaque node
|
||||||
if not is_in_water and def and def.walkable and def.groups and def.groups.opaque == 1 then
|
if def and def.walkable and def.groups and def.groups.opaque == 1 then
|
||||||
local shootdir
|
local shootdir
|
||||||
local cx = (p.x % 1) - 0.5
|
local cx = (p.x % 1) - 0.5
|
||||||
local cz = (p.z % 1) - 0.5
|
local cz = (p.z % 1) - 0.5
|
||||||
|
@ -761,8 +735,8 @@ minetest.register_entity(":__builtin:item", {
|
||||||
local newv = vector.multiply(shootdir, 3)
|
local newv = vector.multiply(shootdir, 3)
|
||||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||||
self.object:set_velocity(newv)
|
self.object:set_velocity(newv)
|
||||||
disable_physics(self.object, self, false, false)
|
|
||||||
|
|
||||||
|
disable_physics(self.object, self, false, false)
|
||||||
|
|
||||||
if shootdir.y == 0 then
|
if shootdir.y == 0 then
|
||||||
self._force = newv
|
self._force = newv
|
||||||
|
@ -800,9 +774,8 @@ minetest.register_entity(":__builtin:item", {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water.
|
-- Move item around on flowing liquids
|
||||||
if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then
|
if def and def.liquidtype == "flowing" then
|
||||||
self._flowing = true
|
|
||||||
|
|
||||||
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
||||||
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
||||||
|
@ -811,11 +784,11 @@ minetest.register_entity(":__builtin:item", {
|
||||||
-- Just to make sure we don't manipulate the speed for no reason
|
-- Just to make sure we don't manipulate the speed for no reason
|
||||||
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
||||||
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
||||||
local f = 1.2
|
local f = 1.39
|
||||||
-- Set new item moving speed into the direciton of the liquid
|
-- Set new item moving speed into the direciton of the liquid
|
||||||
local newv = vector.multiply(vec, f)
|
local newv = vector.multiply(vec, f)
|
||||||
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
|
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||||
self.object:set_acceleration({x = newv.x, y = -0.22, z = newv.z})
|
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
|
||||||
|
|
||||||
self.physical_state = true
|
self.physical_state = true
|
||||||
self._flowing = true
|
self._flowing = true
|
||||||
|
@ -824,29 +797,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if is_in_water and def.liquidtype == "source" then
|
elseif self._flowing == true then
|
||||||
local cur_vec = self.object:get_velocity()
|
|
||||||
-- apply some acceleration in the opposite direction so it doesn't slide forever
|
|
||||||
local vec = {
|
|
||||||
x = 0 -cur_vec.x*0.9,
|
|
||||||
y = 3 -cur_vec.y*0.9,
|
|
||||||
z = 0 -cur_vec.z*0.9}
|
|
||||||
self.object:set_acceleration(vec)
|
|
||||||
-- slow down the item in water
|
|
||||||
local vel = self.object:get_velocity()
|
|
||||||
if vel.y < 0 then
|
|
||||||
vel.y = vel.y * 0.9
|
|
||||||
end
|
|
||||||
self.object:set_velocity(vel)
|
|
||||||
if self.physical_state ~= false or self._flowing ~= true then
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif self._flowing == true and not is_in_water and not is_floating then
|
|
||||||
-- Disable flowing physics if not on/in flowing liquid
|
-- Disable flowing physics if not on/in flowing liquid
|
||||||
self._flowing = false
|
self._flowing = false
|
||||||
enable_physics(self.object, self, true)
|
enable_physics(self.object, self, true)
|
||||||
|
@ -855,13 +806,10 @@ minetest.register_entity(":__builtin:item", {
|
||||||
|
|
||||||
-- If node is not registered or node is walkably solid and resting on nodebox
|
-- If node is not registered or node is walkably solid and resting on nodebox
|
||||||
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
|
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
|
||||||
local def = minetest.registered_nodes[nn]
|
|
||||||
local v = self.object:get_velocity()
|
local v = self.object:get_velocity()
|
||||||
local is_on_floor = def and (def.walkable
|
|
||||||
and not def.groups.slippery and v.y == 0)
|
|
||||||
|
|
||||||
if not minetest.registered_nodes[nn]
|
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and v.y == 0 then
|
||||||
or is_floating or is_on_floor then
|
if self.physical_state then
|
||||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||||
-- Merge with close entities of the same item
|
-- Merge with close entities of the same item
|
||||||
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
|
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
|
||||||
|
@ -872,17 +820,14 @@ minetest.register_entity(":__builtin:item", {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- don't disable if underwater
|
end
|
||||||
if not is_in_water then
|
|
||||||
disable_physics(self.object, self)
|
disable_physics(self.object, self)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
else
|
else
|
||||||
if self._magnet_active == false and not is_floating then
|
if self._magnet_active == false then
|
||||||
enable_physics(self.object, self)
|
enable_physics(self.object, self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
|
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
|
||||||
|
|
|
@ -677,8 +677,7 @@ register_minecart(
|
||||||
{ "mcl_chests_normal.png", "mcl_minecarts_minecart.png" },
|
{ "mcl_chests_normal.png", "mcl_minecarts_minecart.png" },
|
||||||
"mcl_minecarts_minecart_chest.png",
|
"mcl_minecarts_minecart_chest.png",
|
||||||
{"mcl_minecarts:minecart", "mcl_chests:chest"},
|
{"mcl_minecarts:minecart", "mcl_chests:chest"},
|
||||||
nil, nil, true)
|
nil, nil, false)
|
||||||
mcl_entity_invs.register_inv("mcl_minecarts:chest_minecart","Minecart",27)
|
|
||||||
|
|
||||||
-- Minecart with Furnace
|
-- Minecart with Furnace
|
||||||
register_minecart(
|
register_minecart(
|
||||||
|
@ -731,7 +730,7 @@ register_minecart(
|
||||||
"mcl_minecarts_minecart.png",
|
"mcl_minecarts_minecart.png",
|
||||||
}})
|
}})
|
||||||
end
|
end
|
||||||
end, nil, true
|
end, nil, false
|
||||||
)
|
)
|
||||||
|
|
||||||
-- Minecart with Command Block
|
-- Minecart with Command Block
|
||||||
|
@ -831,7 +830,8 @@ minetest.register_craft({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
-- TODO: Re-enable crafting of special minecarts when they have been implemented
|
||||||
|
--[[minetest.register_craft({
|
||||||
output = "mcl_minecarts:furnace_minecart",
|
output = "mcl_minecarts:furnace_minecart",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mcl_furnaces:furnace"},
|
{"mcl_furnaces:furnace"},
|
||||||
|
@ -839,16 +839,13 @@ minetest.register_craft({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- TODO: Re-enable crafting of special minecarts when they have been implemented
|
minetest.register_craft({
|
||||||
|
|
||||||
--[[minetest.register_craft({
|
|
||||||
output = "mcl_minecarts:hopper_minecart",
|
output = "mcl_minecarts:hopper_minecart",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mcl_hoppers:hopper"},
|
{"mcl_hoppers:hopper"},
|
||||||
{"mcl_minecarts:minecart"},
|
{"mcl_minecarts:minecart"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
--]]
|
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mcl_minecarts:chest_minecart",
|
output = "mcl_minecarts:chest_minecart",
|
||||||
|
@ -856,7 +853,7 @@ minetest.register_craft({
|
||||||
{"mcl_chests:chest"},
|
{"mcl_chests:chest"},
|
||||||
{"mcl_minecarts:minecart"},
|
{"mcl_minecarts:minecart"},
|
||||||
},
|
},
|
||||||
})
|
})]]
|
||||||
|
|
||||||
|
|
||||||
if has_mcl_wip then
|
if has_mcl_wip then
|
||||||
|
|
|
@ -33,4 +33,4 @@ Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté
|
||||||
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
|
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
|
||||||
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
|
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
|
||||||
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
|
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
|
||||||
Sneak to dismount=Se baisser pour descendre
|
Sneak to dismount=
|
|
@ -1,5 +1,6 @@
|
||||||
name = mcl_minecarts
|
name = mcl_minecarts
|
||||||
author = Krock
|
author = Krock
|
||||||
description = Minecarts are vehicles to move players quickly on rails.
|
description = Minecarts are vehicles to move players quickly on rails.
|
||||||
depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_entity_invs
|
depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
|
||||||
optional_depends = doc_identifier, mcl_wip
|
optional_depends = doc_identifier, mcl_wip
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ local function register_rail(itemstring, tiles, def_extras, creative)
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = groups,
|
groups = groups,
|
||||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||||
_mcl_blast_resistance = 0.7,
|
_mcl_blast_resistance = 3.5,
|
||||||
_mcl_hardness = 0.7,
|
_mcl_hardness = 0.7,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
-- Scan for minecarts in this pos and force them to execute their "floating" check.
|
-- Scan for minecarts in this pos and force them to execute their "floating" check.
|
||||||
|
|
|
@ -259,7 +259,6 @@ functions needed for the mob to work properly which contains the following:
|
||||||
that are bred in a different way.
|
that are bred in a different way.
|
||||||
'pick_up' table of itemstrings the mob will pick up (e.g. for breeding)
|
'pick_up' table of itemstrings the mob will pick up (e.g. for breeding)
|
||||||
'on_pick_up' function that will be called on item pickup - return true to not pickup the item
|
'on_pick_up' function that will be called on item pickup - return true to not pickup the item
|
||||||
'custom_visual_size' will not reset visual_size from the base class on reload
|
|
||||||
|
|
||||||
mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival
|
mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival
|
||||||
|
|
||||||
|
@ -434,7 +433,7 @@ true the mob will not spawn.
|
||||||
MineClone 2 extensions
|
MineClone 2 extensions
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
mcl_mobs:spawn_child(pos, mob_type)
|
mobs:spawn_child(pos, mob_type)
|
||||||
|
|
||||||
This function spawns a mob as a child. The parameter mob_type is the
|
This function spawns a mob as a child. The parameter mob_type is the
|
||||||
entitystring of the new mob.
|
entitystring of the new mob.
|
||||||
|
@ -444,7 +443,6 @@ mobs:death_effect(pos, collisionbox)
|
||||||
|
|
||||||
Create death particles at pos with the given collisionbox.
|
Create death particles at pos with the given collisionbox.
|
||||||
|
|
||||||
mcl_mobs.spawn(pos,name/entity name)
|
|
||||||
|
|
||||||
Making Arrows
|
Making Arrows
|
||||||
-------------
|
-------------
|
||||||
|
@ -486,13 +484,13 @@ This function registers a arrow for mobs with the attack type shoot.
|
||||||
Spawn Eggs
|
Spawn Eggs
|
||||||
----------
|
----------
|
||||||
|
|
||||||
mobs:register_egg(name, description, background_color, overlay_color, addegg, no_creative)
|
mobs:register_egg(name, description, background, addegg, no_creative)
|
||||||
|
|
||||||
This function registers a spawn egg which can be used by admin to properly spawn in a mob.
|
This function registers a spawn egg which can be used by admin to properly spawn in a mob.
|
||||||
|
|
||||||
'name' this is the name of your new mob to spawn e.g. "mob:sheep"
|
'name' this is the name of your new mob to spawn e.g. "mob:sheep"
|
||||||
'description' the name of the new egg you are creating e.g. "Spawn Sheep"
|
'description' the name of the new egg you are creating e.g. "Spawn Sheep"
|
||||||
'background_color' and 'overlay_color' define the colors for the texture displayed for the egg in inventory
|
'background'the texture displayed for the egg in inventory
|
||||||
'addegg' would you like an egg image in front of your texture (1 = yes,
|
'addegg' would you like an egg image in front of your texture (1 = yes,
|
||||||
0 = no)
|
0 = no)
|
||||||
'no_creative' when set to true this stops spawn egg appearing in creative
|
'no_creative' when set to true this stops spawn egg appearing in creative
|
||||||
|
|
|
@ -15,7 +15,7 @@ local math_cos = math.cos
|
||||||
local math_sin = math.sin
|
local math_sin = math.sin
|
||||||
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
|
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
|
||||||
|
|
||||||
local vector_distance = vector.distance
|
--local vector_distance = vector.distance
|
||||||
local vector_new = vector.new
|
local vector_new = vector.new
|
||||||
local vector_floor = vector.floor
|
local vector_floor = vector.floor
|
||||||
|
|
||||||
|
@ -23,23 +23,13 @@ local table_copy = table.copy
|
||||||
local table_remove = table.remove
|
local table_remove = table.remove
|
||||||
|
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local dbg_spawn_attempts = 0
|
|
||||||
local dbg_spawn_succ = 0
|
|
||||||
-- range for mob count
|
|
||||||
local aoc_range = 136
|
|
||||||
|
|
||||||
local mob_cap = {
|
-- range for mob count
|
||||||
monster = minetest.settings:get_bool("mcl_mob_cap_monster") or 70,
|
local aoc_range = 32
|
||||||
animal = minetest.settings:get_bool("mcl_mob_cap_animal") or 10,
|
|
||||||
ambient = minetest.settings:get_bool("mcl_mob_cap_ambient") or 15,
|
|
||||||
water = minetest.settings:get_bool("mcl_mob_cap_water") or 5, --currently unused
|
|
||||||
water_ambient = minetest.settings:get_bool("mcl_mob_cap_water_ambient") or 20, --currently unused
|
|
||||||
}
|
|
||||||
|
|
||||||
--do mobs spawn?
|
--do mobs spawn?
|
||||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||||
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
|
|
||||||
local logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
|
|
||||||
|
|
||||||
local noise_params = {
|
local noise_params = {
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
@ -73,7 +63,6 @@ local list_of_all_biomes = {
|
||||||
"JungleM_underground",
|
"JungleM_underground",
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
"MangroveSwamp_underground",
|
|
||||||
|
|
||||||
-- ocean:
|
-- ocean:
|
||||||
|
|
||||||
|
@ -137,8 +126,6 @@ local list_of_all_biomes = {
|
||||||
"BirchForestM_deep_ocean",
|
"BirchForestM_deep_ocean",
|
||||||
"Taiga_deep_ocean",
|
"Taiga_deep_ocean",
|
||||||
"JungleM_ocean",
|
"JungleM_ocean",
|
||||||
"MangroveSwamp_ocean",
|
|
||||||
"MangroveSwamp_deep_ocean",
|
|
||||||
|
|
||||||
-- water or beach?
|
-- water or beach?
|
||||||
|
|
||||||
|
@ -162,15 +149,10 @@ local list_of_all_biomes = {
|
||||||
"MushroomIslandShore",
|
"MushroomIslandShore",
|
||||||
"JungleM_shore",
|
"JungleM_shore",
|
||||||
"Jungle_shore",
|
"Jungle_shore",
|
||||||
"MangroveSwamp_shore",
|
|
||||||
|
|
||||||
-- dimension biome:
|
-- dimension biome:
|
||||||
|
|
||||||
"Nether",
|
"Nether",
|
||||||
"BasaltDelta",
|
|
||||||
"CrimsonForest",
|
|
||||||
"WarpedForest",
|
|
||||||
"SoulsandValley",
|
|
||||||
"End",
|
"End",
|
||||||
|
|
||||||
-- Overworld regular:
|
-- Overworld regular:
|
||||||
|
@ -180,8 +162,6 @@ local list_of_all_biomes = {
|
||||||
"Swampland",
|
"Swampland",
|
||||||
"Taiga",
|
"Taiga",
|
||||||
"ExtremeHills",
|
"ExtremeHills",
|
||||||
"ExtremeHillsM",
|
|
||||||
"ExtremeHills+_snowtop",
|
|
||||||
"Jungle",
|
"Jungle",
|
||||||
"Savanna",
|
"Savanna",
|
||||||
"BirchForest",
|
"BirchForest",
|
||||||
|
@ -200,6 +180,7 @@ local list_of_all_biomes = {
|
||||||
"ExtremeHills+_snowtop",
|
"ExtremeHills+_snowtop",
|
||||||
"MesaPlateauFM_grasstop",
|
"MesaPlateauFM_grasstop",
|
||||||
"JungleEdgeM",
|
"JungleEdgeM",
|
||||||
|
"ExtremeHillsM",
|
||||||
"JungleM",
|
"JungleM",
|
||||||
"BirchForestM",
|
"BirchForestM",
|
||||||
"MesaPlateauF",
|
"MesaPlateauF",
|
||||||
|
@ -208,32 +189,16 @@ local list_of_all_biomes = {
|
||||||
"MesaBryce",
|
"MesaBryce",
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
"MangroveSwamp",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- count how many mobs are in an area
|
-- count how many mobs are in an area
|
||||||
local function count_mobs(pos,r,mob_type)
|
local function count_mobs(pos)
|
||||||
local num = 0
|
local num = 0
|
||||||
for _,l in pairs(minetest.luaentities) do
|
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do
|
||||||
if l and l.is_mob and (mob_type == nil or l.type == mob_type) then
|
if object and object:get_luaentity() and object:get_luaentity().is_mob then
|
||||||
local p = l.object:get_pos()
|
|
||||||
if p and vector_distance(p,pos) < r then
|
|
||||||
num = num + 1
|
num = num + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return num
|
|
||||||
end
|
|
||||||
|
|
||||||
local function count_mobs_total(mob_type)
|
|
||||||
local num = 0
|
|
||||||
for _,l in pairs(minetest.luaentities) do
|
|
||||||
if l.is_mob then
|
|
||||||
if mob_type == nil or l.type == mob_type then
|
|
||||||
num = num + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -411,119 +376,13 @@ local function is_farm_animal(n)
|
||||||
return n == "mobs_mc:pig" or n == "mobs_mc:cow" or n == "mobs_mc:sheep" or n == "mobs_mc:chicken" or n == "mobs_mc:horse" or n == "mobs_mc:donkey"
|
return n == "mobs_mc:pig" or n == "mobs_mc:cow" or n == "mobs_mc:sheep" or n == "mobs_mc:chicken" or n == "mobs_mc:horse" or n == "mobs_mc:donkey"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_water_spawn(p)
|
|
||||||
local nn = minetest.find_nodes_in_area(vector.offset(p,-2,-1,-2),vector.offset(p,2,-15,2),{"group:water"})
|
|
||||||
if nn and #nn > 0 then
|
|
||||||
return nn[math.random(#nn)]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function spawn_check(pos,spawn_def)
|
|
||||||
if not spawn_def then return end
|
|
||||||
dbg_spawn_attempts = dbg_spawn_attempts + 1
|
|
||||||
local dimension = mcl_worlds.pos_to_dimension(pos)
|
|
||||||
local mob_type = minetest.registered_entities[spawn_def.name].type
|
|
||||||
local gotten_node = get_node(pos).name
|
|
||||||
local gotten_biome = minetest.get_biome_data(pos)
|
|
||||||
if not gotten_node or not gotten_biome then return end
|
|
||||||
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
|
||||||
|
|
||||||
local is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
|
|
||||||
if not is_ground then
|
|
||||||
pos.y = pos.y - 1
|
|
||||||
gotten_node = get_node(pos).name
|
|
||||||
is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
|
|
||||||
end
|
|
||||||
pos.y = pos.y + 1
|
|
||||||
local has_room = #minetest.find_nodes_in_area(pos,vector.offset(pos,0,1,0),{"air"}) or 0 >= 2
|
|
||||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
|
||||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
|
||||||
local is_leaf = get_item_group(gotten_node, "leaves") ~= 0
|
|
||||||
local is_bedrock = gotten_node == "mcl_core:bedrock"
|
|
||||||
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
|
|
||||||
local mob_count_wide = count_mobs(pos,aoc_range,mob_type)
|
|
||||||
local mob_count = count_mobs(pos,32,mob_type)
|
|
||||||
|
|
||||||
if pos and spawn_def
|
|
||||||
and mob_count_wide < (mob_cap[mob_type] or 15)
|
|
||||||
and mob_count < 5
|
|
||||||
and pos.y >= spawn_def.min_height
|
|
||||||
and pos.y <= spawn_def.max_height
|
|
||||||
and spawn_def.dimension == dimension
|
|
||||||
and biome_check(spawn_def.biomes, gotten_biome)
|
|
||||||
and (is_ground or spawn_def.type_of_spawning ~= "ground")
|
|
||||||
and (spawn_def.type_of_spawning ~= "ground" or not is_leaf)
|
|
||||||
and (spawn_def.type_of_spawning ~= "ground" or has_room)
|
|
||||||
and (spawn_def.check_position and spawn_def.check_position(pos) or true)
|
|
||||||
and (not is_farm_animal(spawn_def.name) or is_grass)
|
|
||||||
and (spawn_def.type_of_spawning ~= "water" or is_water)
|
|
||||||
and ( not spawn_protected or not minetest.is_protected(pos, "") )
|
|
||||||
and not is_bedrock then
|
|
||||||
--only need to poll for node light if everything else worked
|
|
||||||
local gotten_light = get_node_light(pos)
|
|
||||||
if gotten_light >= spawn_def.min_light and gotten_light <= spawn_def.max_light then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_mobs.spawn(pos,id)
|
|
||||||
local def = minetest.registered_entities[id] or minetest.registered_entities["mobs_mc:"..id] or minetest.registered_entities["extra_mobs:"..id]
|
|
||||||
if not def or (def.can_spawn and not def.can_spawn(pos)) or not def.is_mob then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return minetest.add_entity(pos, def.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function spawn_group(p,mob,spawn_on,group_max,group_min)
|
|
||||||
if not group_min then group_min = 1 end
|
|
||||||
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
|
||||||
local o
|
|
||||||
table.shuffle(nn)
|
|
||||||
if not nn or #nn < 1 then
|
|
||||||
nn = {}
|
|
||||||
table.insert(nn,p)
|
|
||||||
end
|
|
||||||
for i = 1, math.random(group_min,group_max) do
|
|
||||||
local sp = vector.offset(nn[math.random(#nn)],0,1,0)
|
|
||||||
if spawn_check(nn[math.random(#nn)],mob) then
|
|
||||||
if mob.type_of_spawning == "water" then
|
|
||||||
sp = get_water_spawn(sp)
|
|
||||||
end
|
|
||||||
o = mcl_mobs.spawn(sp,mob.name)
|
|
||||||
if o then dbg_spawn_succ = dbg_spawn_succ + 1 end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return o
|
|
||||||
end
|
|
||||||
|
|
||||||
mcl_mobs.spawn_group = spawn_group
|
|
||||||
|
|
||||||
minetest.register_chatcommand("spawn_mob",{
|
|
||||||
privs = { debug = true },
|
|
||||||
func = function(n,param)
|
|
||||||
local pos = minetest.get_player_by_name(n):get_pos()
|
|
||||||
if mcl_mobs.spawn(pos,param) then
|
|
||||||
return true, param.." spawned at "..minetest.pos_to_string(pos),
|
|
||||||
minetest.log("action", n.." spawned "..param.." at "..minetest.pos_to_string(pos))
|
|
||||||
end
|
|
||||||
return false, "Couldn't spawn "..param
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
if mobs_spawn then
|
if mobs_spawn then
|
||||||
|
|
||||||
local perlin_noise
|
local perlin_noise
|
||||||
|
|
||||||
local function spawn_a_mob(pos, dimension, y_min, y_max)
|
local function spawn_a_mob(pos, dimension, y_min, y_max)
|
||||||
--create a disconnected clone of the spawn dictionary
|
local dimension = dimension or mcl_worlds.pos_to_dimension(pos)
|
||||||
--prevents memory leak
|
|
||||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
|
||||||
local goal_pos = get_next_mob_spawn_pos(pos)
|
local goal_pos = get_next_mob_spawn_pos(pos)
|
||||||
--grab mob that fits into the spawning location
|
|
||||||
--randomly grab a mob, don't exclude any possibilities
|
|
||||||
local spawning_position_list = find_nodes_in_area_under_air(
|
local spawning_position_list = find_nodes_in_area_under_air(
|
||||||
{x = goal_pos.x, y = y_min, z = goal_pos.z},
|
{x = goal_pos.x, y = y_min, z = goal_pos.z},
|
||||||
{x = goal_pos.x, y = y_max, z = goal_pos.z},
|
{x = goal_pos.x, y = y_max, z = goal_pos.z},
|
||||||
|
@ -532,10 +391,41 @@ if mobs_spawn then
|
||||||
if #spawning_position_list <= 0 then return end
|
if #spawning_position_list <= 0 then return end
|
||||||
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
||||||
|
|
||||||
|
--hard code mob limit in area to 5 for now
|
||||||
|
if count_mobs(spawning_position) >= 5 then return end
|
||||||
|
|
||||||
|
local gotten_node = get_node(spawning_position).name
|
||||||
|
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||||
|
if not gotten_node or not gotten_biome then return end
|
||||||
|
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
||||||
|
|
||||||
|
--add this so mobs don't spawn inside nodes
|
||||||
|
spawning_position.y = spawning_position.y + 1
|
||||||
|
|
||||||
|
--only need to poll for node light if everything else worked
|
||||||
|
local gotten_light = get_node_light(spawning_position)
|
||||||
|
|
||||||
|
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||||
|
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||||
|
local is_ground = not (is_water or is_lava)
|
||||||
|
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
|
||||||
|
local has_bed = minetest.find_node_near(pos,25,{"group:bed"})
|
||||||
|
|
||||||
|
if not is_ground then
|
||||||
|
spawning_position.y = spawning_position.y - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local mob_def
|
||||||
|
|
||||||
|
--create a disconnected clone of the spawn dictionary
|
||||||
|
--prevents memory leak
|
||||||
|
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||||
|
|
||||||
|
--grab mob that fits into the spawning location
|
||||||
|
--randomly grab a mob, don't exclude any possibilities
|
||||||
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||||
local noise = perlin_noise:get_3d(spawning_position)
|
local noise = perlin_noise:get_3d(spawning_position)
|
||||||
local current_summary_chance = summary_chance
|
local current_summary_chance = summary_chance
|
||||||
table.shuffle(mob_library_worker_table)
|
|
||||||
while #mob_library_worker_table > 0 do
|
while #mob_library_worker_table > 0 do
|
||||||
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||||
local mob_index = 1
|
local mob_index = 1
|
||||||
|
@ -547,37 +437,23 @@ if mobs_spawn then
|
||||||
step_chance = step_chance + mob_chance
|
step_chance = step_chance + mob_chance
|
||||||
end
|
end
|
||||||
local mob_def = mob_library_worker_table[mob_index]
|
local mob_def = mob_library_worker_table[mob_index]
|
||||||
local spawn_in_group = minetest.registered_entities[mob_def.name].spawn_in_group or 4
|
|
||||||
local spawn_in_group_min = minetest.registered_entities[mob_def.name].spawn_in_group_min or 1
|
|
||||||
local mob_type = minetest.registered_entities[mob_def.name].type
|
local mob_type = minetest.registered_entities[mob_def.name].type
|
||||||
if spawn_check(spawning_position,mob_def) then
|
if mob_def
|
||||||
if mob_def.type_of_spawning == "water" then
|
and spawning_position.y >= mob_def.min_height
|
||||||
spawning_position = get_water_spawn(spawning_position)
|
and spawning_position.y <= mob_def.max_height
|
||||||
if not spawning_position then
|
and mob_def.dimension == dimension
|
||||||
return
|
and biome_check(mob_def.biomes, gotten_biome)
|
||||||
end
|
and gotten_light >= mob_def.min_light
|
||||||
end
|
and gotten_light <= mob_def.max_light
|
||||||
if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(pos) then
|
and (is_ground or mob_def.type_of_spawning ~= "ground")
|
||||||
return
|
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
|
||||||
end
|
and (not is_farm_animal(mob_def.name) or is_grass)
|
||||||
|
and (mob_type ~= "npc" or has_bed)
|
||||||
|
then
|
||||||
--everything is correct, spawn mob
|
--everything is correct, spawn mob
|
||||||
local object
|
local object = minetest.add_entity(spawning_position, mob_def.name)
|
||||||
if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then
|
|
||||||
if logging then
|
|
||||||
minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1))
|
|
||||||
end
|
|
||||||
object = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name},spawn_in_group,spawn_in_group_min)
|
|
||||||
|
|
||||||
else
|
|
||||||
if logging then
|
|
||||||
minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1))
|
|
||||||
end
|
|
||||||
object = mcl_mobs.spawn(spawning_position, mob_def.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
if object then
|
if object then
|
||||||
return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position)
|
return mob_def.on_spawn and mob_def.on_spawn(object, pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
current_summary_chance = current_summary_chance - mob_chance
|
current_summary_chance = current_summary_chance - mob_chance
|
||||||
|
@ -606,14 +482,3 @@ if mobs_spawn then
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("mobstats",{
|
|
||||||
privs = { debug = true },
|
|
||||||
func = function(n,param)
|
|
||||||
local pos = minetest.get_player_by_name(n):get_pos()
|
|
||||||
minetest.chat_send_player(n,"mobs within 32 radius of player:"..count_mobs(pos,32))
|
|
||||||
minetest.chat_send_player(n,"total mobs:"..count_mobs_total())
|
|
||||||
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
|
|
||||||
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
|
@ -38,12 +38,6 @@ local function wither_spawn(pos)
|
||||||
if check_schem(p, schem) then
|
if check_schem(p, schem) then
|
||||||
remove_schem(p, schem)
|
remove_schem(p, schem)
|
||||||
minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither")
|
minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither")
|
||||||
local objects = minetest.get_objects_inside_radius(pos, 20)
|
|
||||||
for _, players in ipairs(objects) do
|
|
||||||
if players:is_player() then
|
|
||||||
awards.unlock(players:get_player_name(), "mcl:witheringHeights")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -52,9 +46,6 @@ end
|
||||||
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
|
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
|
||||||
local old_on_place = wither_head.on_place
|
local old_on_place = wither_head.on_place
|
||||||
function wither_head.on_place(itemstack, placer, pointed)
|
function wither_head.on_place(itemstack, placer, pointed)
|
||||||
local n = minetest.get_node(vector.offset(pointed.above,0,-1,0))
|
|
||||||
if n and n.name == "mcl_nether:soul_sand" then
|
|
||||||
minetest.after(0, wither_spawn, pointed.above)
|
minetest.after(0, wither_spawn, pointed.above)
|
||||||
end
|
old_on_place(itemstack, placer, pointed)
|
||||||
return old_on_place(itemstack, placer, pointed)
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ mcl_mobs:register_mob("mobs_mc:bat", {
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "ambient",
|
spawn_class = "ambient",
|
||||||
can_despawn = true,
|
can_despawn = true,
|
||||||
spawn_in_group = 8,
|
|
||||||
passive = true,
|
passive = true,
|
||||||
hp_min = 6,
|
hp_min = 6,
|
||||||
hp_max = 6,
|
hp_max = 6,
|
||||||
|
@ -144,4 +143,4 @@ mobs_mc.water_level-1)
|
||||||
|
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:bat", S("Bat"), "#4c3e30", "#0f0f0f", 0)
|
mcl_mobs:register_egg("mobs_mc:bat", S("Bat"), "mobs_mc_spawn_icon_bat.png", 0)
|
||||||
|
|
|
@ -16,8 +16,6 @@ mcl_mobs:register_mob("mobs_mc:blaze", {
|
||||||
description = S("Blaze"),
|
description = S("Blaze"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
spawn_in_group_min = 2,
|
|
||||||
spawn_in_group = 3,
|
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
hp_max = 20,
|
hp_max = 20,
|
||||||
xp_min = 10,
|
xp_min = 10,
|
||||||
|
@ -26,12 +24,6 @@ mcl_mobs:register_mob("mobs_mc:blaze", {
|
||||||
rotate = -180,
|
rotate = -180,
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_blaze.b3d",
|
mesh = "mobs_mc_blaze.b3d",
|
||||||
head_swivel = "head.control",
|
|
||||||
bone_eye_height = 4,
|
|
||||||
head_eye_height = 3.5,
|
|
||||||
curiosity = 10,
|
|
||||||
head_yaw_offset = 180,
|
|
||||||
head_pitch_multiplier=-1,
|
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_blaze.png"},
|
{"mobs_mc_blaze.png"},
|
||||||
},
|
},
|
||||||
|
@ -208,4 +200,4 @@ mcl_mobs:register_arrow("mobs_mc:blaze_fireball", {
|
||||||
})
|
})
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:blaze", S("Blaze"), "#f6b201", "#fff87e", 0)
|
mcl_mobs:register_egg("mobs_mc:blaze", S("Blaze"), "mobs_mc_spawn_icon_blaze.png", 0)
|
||||||
|
|
|
@ -20,18 +20,12 @@ mcl_mobs:register_mob("mobs_mc:chicken", {
|
||||||
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
|
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
|
||||||
runaway = true,
|
runaway = true,
|
||||||
floats = 1,
|
floats = 1,
|
||||||
head_swivel = "head.control",
|
|
||||||
bone_eye_height = 4,
|
|
||||||
head_eye_height = 1.5,
|
|
||||||
horrizonatal_head_height = -.3,
|
|
||||||
curiosity = 10,
|
|
||||||
head_yaw="z",
|
|
||||||
visual_size = {x=1,y=1},
|
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_chicken.b3d",
|
mesh = "mobs_mc_chicken.b3d",
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_chicken.png"},
|
{"mobs_mc_chicken.png"},
|
||||||
},
|
},
|
||||||
|
visual_size = {x=2.2, y=2.2},
|
||||||
|
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
walk_velocity = 1,
|
walk_velocity = 1,
|
||||||
|
@ -64,15 +58,12 @@ mcl_mobs:register_mob("mobs_mc:chicken", {
|
||||||
distance = 16,
|
distance = 16,
|
||||||
},
|
},
|
||||||
animation = {
|
animation = {
|
||||||
|
stand_speed = 25, walk_speed = 25, run_speed = 50,
|
||||||
stand_start = 0, stand_end = 0,
|
stand_start = 0, stand_end = 0,
|
||||||
walk_start = 0, walk_end = 20, walk_speed = 25,
|
walk_start = 0, walk_end = 40,
|
||||||
run_start = 0, run_end = 20, run_speed = 50,
|
run_start = 0, run_end = 40,
|
||||||
},
|
|
||||||
child_animations = {
|
|
||||||
stand_start = 31, stand_end = 31,
|
|
||||||
walk_start = 31, walk_end = 51, walk_speed = 37,
|
|
||||||
run_start = 31, run_end = 51, run_speed = 75,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
follow = {
|
follow = {
|
||||||
"mcl_farming:wheat_seeds",
|
"mcl_farming:wheat_seeds",
|
||||||
"mcl_farming:melon_seeds",
|
"mcl_farming:melon_seeds",
|
||||||
|
@ -83,7 +74,7 @@ mcl_mobs:register_mob("mobs_mc:chicken", {
|
||||||
fear_height = 4,
|
fear_height = 4,
|
||||||
|
|
||||||
on_rightclick = function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
|
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
|
||||||
if mcl_mobs:protect(self, clicker) then return end
|
if mcl_mobs:protect(self, clicker) then return end
|
||||||
if mcl_mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
|
if mcl_mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
|
||||||
end,
|
end,
|
||||||
|
@ -131,6 +122,8 @@ mcl_mobs:spawn_specific(
|
||||||
"ExtremeHills_beach",
|
"ExtremeHills_beach",
|
||||||
"ExtremeHillsM",
|
"ExtremeHillsM",
|
||||||
"ExtremeHills+",
|
"ExtremeHills+",
|
||||||
|
"ExtremeHills+_snowtop",
|
||||||
|
"StoneBeach",
|
||||||
"Plains",
|
"Plains",
|
||||||
"Plains_beach",
|
"Plains_beach",
|
||||||
"SunflowerPlains",
|
"SunflowerPlains",
|
||||||
|
@ -163,4 +156,4 @@ mobs_mc.water_level,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:chicken", S("Chicken"), "#a1a1a1", "#ff0000", 0)
|
mcl_mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0)
|
||||||
|
|
|
@ -1,274 +0,0 @@
|
||||||
--MCmobs v0.4
|
|
||||||
--maikerumine
|
|
||||||
--made for MC like Survival game
|
|
||||||
--License for code WTFPL and otherwise stated in readmes
|
|
||||||
|
|
||||||
local pi = math.pi
|
|
||||||
local atann = math.atan
|
|
||||||
local atan = function(x)
|
|
||||||
if not x or x ~= x then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return atann(x)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local dir_to_pitch = function(dir)
|
|
||||||
local dir2 = vector.normalize(dir)
|
|
||||||
local xz = math.abs(dir.x) + math.abs(dir.z)
|
|
||||||
return -math.atan2(-dir.y, xz)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function degrees(rad)
|
|
||||||
return rad * 180.0 / math.pi
|
|
||||||
end
|
|
||||||
|
|
||||||
local S = minetest.get_translator(minetest.get_current_modname())
|
|
||||||
|
|
||||||
--###################
|
|
||||||
--################### cod
|
|
||||||
--###################
|
|
||||||
|
|
||||||
local cod = {
|
|
||||||
type = "animal",
|
|
||||||
spawn_class = "water",
|
|
||||||
can_despawn = true,
|
|
||||||
passive = true,
|
|
||||||
hp_min = 3,
|
|
||||||
hp_max = 3,
|
|
||||||
xp_min = 1,
|
|
||||||
xp_max = 3,
|
|
||||||
armor = 100,
|
|
||||||
rotate = 180,
|
|
||||||
spawn_in_group_min = 3,
|
|
||||||
spawn_in_group = 8,
|
|
||||||
tilt_swim = true,
|
|
||||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
|
|
||||||
visual = "mesh",
|
|
||||||
mesh = "extra_mobs_cod.b3d",
|
|
||||||
textures = {
|
|
||||||
{"extra_mobs_cod.png"}
|
|
||||||
},
|
|
||||||
sounds = {
|
|
||||||
},
|
|
||||||
animation = {
|
|
||||||
stand_start = 1,
|
|
||||||
stand_end = 20,
|
|
||||||
walk_start = 1,
|
|
||||||
walk_end = 20,
|
|
||||||
run_start = 1,
|
|
||||||
run_end = 20,
|
|
||||||
},
|
|
||||||
drops = {
|
|
||||||
{name = "mcl_fishing:fish_raw",
|
|
||||||
chance = 1,
|
|
||||||
min = 1,
|
|
||||||
max = 1,},
|
|
||||||
{name = "mcl_dye:white",
|
|
||||||
chance = 20,
|
|
||||||
min = 1,
|
|
||||||
max = 1,},
|
|
||||||
},
|
|
||||||
visual_size = {x=3, y=3},
|
|
||||||
makes_footstep_sound = false,
|
|
||||||
fly = true,
|
|
||||||
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
|
|
||||||
breathes_in_water = true,
|
|
||||||
jump = false,
|
|
||||||
view_range = 16,
|
|
||||||
runaway = true,
|
|
||||||
fear_height = 4,
|
|
||||||
do_custom = function(self)
|
|
||||||
--[[ this is supposed to make them jump out the water but doesn't appear to work very well
|
|
||||||
self.object:set_bone_position("body", vector.new(0,1,0), vector.new(degrees(dir_to_pitch(self.object:get_velocity())) * -1 + 90,0,0))
|
|
||||||
if minetest.get_item_group(self.standing_in, "water") ~= 0 then
|
|
||||||
if self.object:get_velocity().y < 5 then
|
|
||||||
self.object:add_velocity({ x = 0 , y = math.random(-.007, .007), z = 0 })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--]]
|
|
||||||
for _,object in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 10)) do
|
|
||||||
local lp = object:get_pos()
|
|
||||||
local s = self.object:get_pos()
|
|
||||||
local vec = {
|
|
||||||
x = lp.x - s.x,
|
|
||||||
y = lp.y - s.y,
|
|
||||||
z = lp.z - s.z
|
|
||||||
}
|
|
||||||
if object and not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mobs_mc:cod" then
|
|
||||||
self.state = "runaway"
|
|
||||||
self.object:set_rotation({x=0,y=(atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate,z=0})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
on_rightclick = function(self, clicker)
|
|
||||||
if clicker:get_wielded_item():get_name() == "mcl_buckets:bucket_water" then
|
|
||||||
self.object:remove()
|
|
||||||
clicker:set_wielded_item("mcl_buckets:bucket_cod")
|
|
||||||
awards.unlock(clicker:get_player_name(), "mcl:tacticalFishing")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:cod", cod)
|
|
||||||
|
|
||||||
|
|
||||||
--spawning TODO: in schools
|
|
||||||
|
|
||||||
local water = 0
|
|
||||||
|
|
||||||
mcl_mobs:spawn_specific(
|
|
||||||
"mobs_mc:cod",
|
|
||||||
"overworld",
|
|
||||||
"water",
|
|
||||||
{
|
|
||||||
"Mesa",
|
|
||||||
"FlowerForest",
|
|
||||||
"Swampland",
|
|
||||||
"Taiga",
|
|
||||||
"ExtremeHills",
|
|
||||||
"Jungle",
|
|
||||||
"Savanna",
|
|
||||||
"BirchForest",
|
|
||||||
"MegaSpruceTaiga",
|
|
||||||
"MegaTaiga",
|
|
||||||
"ExtremeHills+",
|
|
||||||
"Forest",
|
|
||||||
"Plains",
|
|
||||||
"Desert",
|
|
||||||
"ColdTaiga",
|
|
||||||
"MushroomIsland",
|
|
||||||
"IcePlainsSpikes",
|
|
||||||
"SunflowerPlains",
|
|
||||||
"IcePlains",
|
|
||||||
"RoofedForest",
|
|
||||||
"ExtremeHills+_snowtop",
|
|
||||||
"MesaPlateauFM_grasstop",
|
|
||||||
"JungleEdgeM",
|
|
||||||
"ExtremeHillsM",
|
|
||||||
"JungleM",
|
|
||||||
"BirchForestM",
|
|
||||||
"MesaPlateauF",
|
|
||||||
"MesaPlateauFM",
|
|
||||||
"MesaPlateauF_grasstop",
|
|
||||||
"MesaBryce",
|
|
||||||
"JungleEdge",
|
|
||||||
"SavannaM",
|
|
||||||
"FlowerForest_beach",
|
|
||||||
"Forest_beach",
|
|
||||||
"StoneBeach",
|
|
||||||
"ColdTaiga_beach_water",
|
|
||||||
"Taiga_beach",
|
|
||||||
"Savanna_beach",
|
|
||||||
"Plains_beach",
|
|
||||||
"ExtremeHills_beach",
|
|
||||||
"ColdTaiga_beach",
|
|
||||||
"Swampland_shore",
|
|
||||||
"MushroomIslandShore",
|
|
||||||
"JungleM_shore",
|
|
||||||
"Jungle_shore",
|
|
||||||
"MesaPlateauFM_sandlevel",
|
|
||||||
"MesaPlateauF_sandlevel",
|
|
||||||
"MesaBryce_sandlevel",
|
|
||||||
"Mesa_sandlevel",
|
|
||||||
"RoofedForest_ocean",
|
|
||||||
"JungleEdgeM_ocean",
|
|
||||||
"BirchForestM_ocean",
|
|
||||||
"BirchForest_ocean",
|
|
||||||
"IcePlains_deep_ocean",
|
|
||||||
"Jungle_deep_ocean",
|
|
||||||
"Savanna_ocean",
|
|
||||||
"MesaPlateauF_ocean",
|
|
||||||
"ExtremeHillsM_deep_ocean",
|
|
||||||
"Savanna_deep_ocean",
|
|
||||||
"SunflowerPlains_ocean",
|
|
||||||
"Swampland_deep_ocean",
|
|
||||||
"Swampland_ocean",
|
|
||||||
"MegaSpruceTaiga_deep_ocean",
|
|
||||||
"ExtremeHillsM_ocean",
|
|
||||||
"JungleEdgeM_deep_ocean",
|
|
||||||
"SunflowerPlains_deep_ocean",
|
|
||||||
"BirchForest_deep_ocean",
|
|
||||||
"IcePlainsSpikes_ocean",
|
|
||||||
"Mesa_ocean",
|
|
||||||
"StoneBeach_ocean",
|
|
||||||
"Plains_deep_ocean",
|
|
||||||
"JungleEdge_deep_ocean",
|
|
||||||
"SavannaM_deep_ocean",
|
|
||||||
"Desert_deep_ocean",
|
|
||||||
"Mesa_deep_ocean",
|
|
||||||
"ColdTaiga_deep_ocean",
|
|
||||||
"Plains_ocean",
|
|
||||||
"MesaPlateauFM_ocean",
|
|
||||||
"Forest_deep_ocean",
|
|
||||||
"JungleM_deep_ocean",
|
|
||||||
"FlowerForest_deep_ocean",
|
|
||||||
"MushroomIsland_ocean",
|
|
||||||
"MegaTaiga_ocean",
|
|
||||||
"StoneBeach_deep_ocean",
|
|
||||||
"IcePlainsSpikes_deep_ocean",
|
|
||||||
"ColdTaiga_ocean",
|
|
||||||
"SavannaM_ocean",
|
|
||||||
"MesaPlateauF_deep_ocean",
|
|
||||||
"MesaBryce_deep_ocean",
|
|
||||||
"ExtremeHills+_deep_ocean",
|
|
||||||
"ExtremeHills_ocean",
|
|
||||||
"MushroomIsland_deep_ocean",
|
|
||||||
"Forest_ocean",
|
|
||||||
"MegaTaiga_deep_ocean",
|
|
||||||
"JungleEdge_ocean",
|
|
||||||
"MesaBryce_ocean",
|
|
||||||
"MegaSpruceTaiga_ocean",
|
|
||||||
"ExtremeHills+_ocean",
|
|
||||||
"Jungle_ocean",
|
|
||||||
"RoofedForest_deep_ocean",
|
|
||||||
"IcePlains_ocean",
|
|
||||||
"FlowerForest_ocean",
|
|
||||||
"ExtremeHills_deep_ocean",
|
|
||||||
"MesaPlateauFM_deep_ocean",
|
|
||||||
"Desert_ocean",
|
|
||||||
"Taiga_ocean",
|
|
||||||
"BirchForestM_deep_ocean",
|
|
||||||
"Taiga_deep_ocean",
|
|
||||||
"JungleM_ocean",
|
|
||||||
"FlowerForest_underground",
|
|
||||||
"JungleEdge_underground",
|
|
||||||
"StoneBeach_underground",
|
|
||||||
"MesaBryce_underground",
|
|
||||||
"Mesa_underground",
|
|
||||||
"RoofedForest_underground",
|
|
||||||
"Jungle_underground",
|
|
||||||
"Swampland_underground",
|
|
||||||
"MushroomIsland_underground",
|
|
||||||
"BirchForest_underground",
|
|
||||||
"Plains_underground",
|
|
||||||
"MesaPlateauF_underground",
|
|
||||||
"ExtremeHills_underground",
|
|
||||||
"MegaSpruceTaiga_underground",
|
|
||||||
"BirchForestM_underground",
|
|
||||||
"SavannaM_underground",
|
|
||||||
"MesaPlateauFM_underground",
|
|
||||||
"Desert_underground",
|
|
||||||
"Savanna_underground",
|
|
||||||
"Forest_underground",
|
|
||||||
"SunflowerPlains_underground",
|
|
||||||
"ColdTaiga_underground",
|
|
||||||
"IcePlains_underground",
|
|
||||||
"IcePlainsSpikes_underground",
|
|
||||||
"MegaTaiga_underground",
|
|
||||||
"Taiga_underground",
|
|
||||||
"ExtremeHills+_underground",
|
|
||||||
"JungleM_underground",
|
|
||||||
"ExtremeHillsM_underground",
|
|
||||||
"JungleEdgeM_underground",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
minetest.LIGHT_MAX+1,
|
|
||||||
30,
|
|
||||||
4000,
|
|
||||||
3,
|
|
||||||
water-16,
|
|
||||||
water+1)
|
|
||||||
|
|
||||||
--spawn egg
|
|
||||||
mcl_mobs:register_egg("mobs_mc:cod", S("Cod"), "#c1a76a", "#e5c48b", 0)
|
|
|
@ -17,12 +17,7 @@ local cow_def = {
|
||||||
"mobs_mc_cow.png",
|
"mobs_mc_cow.png",
|
||||||
"blank.png",
|
"blank.png",
|
||||||
}, },
|
}, },
|
||||||
head_swivel = "head.control",
|
visual_size = {x=2.8, y=2.8},
|
||||||
bone_eye_height = 10,
|
|
||||||
head_eye_height = 1.1,
|
|
||||||
horrizonatal_head_height=-1.8,
|
|
||||||
curiosity = 2,
|
|
||||||
head_yaw="z",
|
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
walk_velocity = 1,
|
walk_velocity = 1,
|
||||||
drops = {
|
drops = {
|
||||||
|
@ -46,17 +41,14 @@ local cow_def = {
|
||||||
distance = 16,
|
distance = 16,
|
||||||
},
|
},
|
||||||
animation = {
|
animation = {
|
||||||
stand_start = 0, stand_end = 0,
|
stand_speed = 25, walk_speed = 40,
|
||||||
walk_start = 0, walk_end = 40, walk_speed = 30,
|
run_speed = 60, stand_start = 0,
|
||||||
run_start = 0, run_end = 40, run_speed = 40,
|
stand_end = 0, walk_start = 0,
|
||||||
},
|
walk_end = 40, run_start = 0,
|
||||||
child_animations = {
|
run_end = 40,
|
||||||
stand_start = 41, stand_end = 41,
|
|
||||||
walk_start = 41, walk_end = 81, walk_speed = 45,
|
|
||||||
run_start = 41, run_end = 81, run_speed = 60,
|
|
||||||
},
|
},
|
||||||
on_rightclick = function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
|
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
|
||||||
if mcl_mobs:protect(self, clicker) then return end
|
if mcl_mobs:protect(self, clicker) then return end
|
||||||
|
|
||||||
if self.child then
|
if self.child then
|
||||||
|
@ -90,11 +82,10 @@ mcl_mobs:register_mob("mobs_mc:cow", cow_def)
|
||||||
-- Mooshroom
|
-- Mooshroom
|
||||||
local mooshroom_def = table.copy(cow_def)
|
local mooshroom_def = table.copy(cow_def)
|
||||||
mooshroom_def.description = S("Mooshroom")
|
mooshroom_def.description = S("Mooshroom")
|
||||||
mooshroom_def.spawn_in_group_min = 4
|
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
||||||
mooshroom_def.spawn_in_group = 8
|
|
||||||
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
||||||
mooshroom_def.on_rightclick = function(self, clicker)
|
mooshroom_def.on_rightclick = function(self, clicker)
|
||||||
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
|
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
|
||||||
if mcl_mobs:protect(self, clicker) then return end
|
if mcl_mobs:protect(self, clicker) then return end
|
||||||
|
|
||||||
if self.child then
|
if self.child then
|
||||||
|
@ -160,12 +151,17 @@ mcl_mobs:spawn_specific(
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"flat",
|
"flat",
|
||||||
|
"IcePlainsSpikes",
|
||||||
|
"ColdTaiga",
|
||||||
|
"ColdTaiga_beach",
|
||||||
|
"ColdTaiga_beach_water",
|
||||||
"MegaTaiga",
|
"MegaTaiga",
|
||||||
"MegaSpruceTaiga",
|
"MegaSpruceTaiga",
|
||||||
"ExtremeHills",
|
"ExtremeHills",
|
||||||
"ExtremeHills_beach",
|
"ExtremeHills_beach",
|
||||||
"ExtremeHillsM",
|
"ExtremeHillsM",
|
||||||
"ExtremeHills+",
|
"ExtremeHills+",
|
||||||
|
"ExtremeHills+_snowtop",
|
||||||
"StoneBeach",
|
"StoneBeach",
|
||||||
"Plains",
|
"Plains",
|
||||||
"Plains_beach",
|
"Plains_beach",
|
||||||
|
@ -218,5 +214,5 @@ mcl_vars.mg_overworld_min,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
-- spawn egg
|
-- spawn egg
|
||||||
mcl_mobs:register_egg("mobs_mc:cow", S("Cow"), "#443626", "#a1a1a1", 0)
|
mcl_mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0)
|
||||||
mcl_mobs:register_egg("mobs_mc:mooshroom", S("Mooshroom"), "#a00f10", "#b7b7b7", 0)
|
mcl_mobs:register_egg("mobs_mc:mooshroom", S("Mooshroom"), "mobs_mc_spawn_icon_mooshroom.png", 0)
|
||||||
|
|
|
@ -12,7 +12,6 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
mcl_mobs:register_mob("mobs_mc:creeper", {
|
mcl_mobs:register_mob("mobs_mc:creeper", {
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
spawn_in_group = 1,
|
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
hp_max = 20,
|
hp_max = 20,
|
||||||
xp_min = 5,
|
xp_min = 5,
|
||||||
|
@ -21,9 +20,6 @@ mcl_mobs:register_mob("mobs_mc:creeper", {
|
||||||
pathfinding = 1,
|
pathfinding = 1,
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_creeper.b3d",
|
mesh = "mobs_mc_creeper.b3d",
|
||||||
head_swivel = "Head_Control",
|
|
||||||
bone_eye_height = 2.35,
|
|
||||||
curiosity = 2,
|
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_creeper.png",
|
{"mobs_mc_creeper.png",
|
||||||
"mobs_mc_empty.png"},
|
"mobs_mc_empty.png"},
|
||||||
|
@ -278,6 +274,7 @@ mcl_mobs:spawn_specific(
|
||||||
"Plains",
|
"Plains",
|
||||||
"Desert",
|
"Desert",
|
||||||
"ColdTaiga",
|
"ColdTaiga",
|
||||||
|
"MushroomIsland",
|
||||||
"IcePlainsSpikes",
|
"IcePlainsSpikes",
|
||||||
"SunflowerPlains",
|
"SunflowerPlains",
|
||||||
"IcePlains",
|
"IcePlains",
|
||||||
|
@ -304,6 +301,7 @@ mcl_mobs:spawn_specific(
|
||||||
"ExtremeHills_beach",
|
"ExtremeHills_beach",
|
||||||
"ColdTaiga_beach",
|
"ColdTaiga_beach",
|
||||||
"Swampland_shore",
|
"Swampland_shore",
|
||||||
|
"MushroomIslandShore",
|
||||||
"JungleM_shore",
|
"JungleM_shore",
|
||||||
"Jungle_shore",
|
"Jungle_shore",
|
||||||
"MesaPlateauFM_sandlevel",
|
"MesaPlateauFM_sandlevel",
|
||||||
|
@ -342,6 +340,7 @@ mcl_mobs:spawn_specific(
|
||||||
"Forest_deep_ocean",
|
"Forest_deep_ocean",
|
||||||
"JungleM_deep_ocean",
|
"JungleM_deep_ocean",
|
||||||
"FlowerForest_deep_ocean",
|
"FlowerForest_deep_ocean",
|
||||||
|
"MushroomIsland_ocean",
|
||||||
"MegaTaiga_ocean",
|
"MegaTaiga_ocean",
|
||||||
"StoneBeach_deep_ocean",
|
"StoneBeach_deep_ocean",
|
||||||
"IcePlainsSpikes_deep_ocean",
|
"IcePlainsSpikes_deep_ocean",
|
||||||
|
@ -351,6 +350,7 @@ mcl_mobs:spawn_specific(
|
||||||
"MesaBryce_deep_ocean",
|
"MesaBryce_deep_ocean",
|
||||||
"ExtremeHills+_deep_ocean",
|
"ExtremeHills+_deep_ocean",
|
||||||
"ExtremeHills_ocean",
|
"ExtremeHills_ocean",
|
||||||
|
"MushroomIsland_deep_ocean",
|
||||||
"Forest_ocean",
|
"Forest_ocean",
|
||||||
"MegaTaiga_deep_ocean",
|
"MegaTaiga_deep_ocean",
|
||||||
"JungleEdge_ocean",
|
"JungleEdge_ocean",
|
||||||
|
@ -376,6 +376,7 @@ mcl_mobs:spawn_specific(
|
||||||
"RoofedForest_underground",
|
"RoofedForest_underground",
|
||||||
"Jungle_underground",
|
"Jungle_underground",
|
||||||
"Swampland_underground",
|
"Swampland_underground",
|
||||||
|
"MushroomIsland_underground",
|
||||||
"BirchForest_underground",
|
"BirchForest_underground",
|
||||||
"Plains_underground",
|
"Plains_underground",
|
||||||
"MesaPlateauF_underground",
|
"MesaPlateauF_underground",
|
||||||
|
@ -407,4 +408,4 @@ mcl_vars.mg_overworld_min,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:creeper", S("Creeper"), "#0da70a", "#000000", 0)
|
mcl_mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
mcl_mobs
|
|
@ -1,253 +0,0 @@
|
||||||
--MCmobs v0.4
|
|
||||||
--maikerumine
|
|
||||||
--made for MC like Survival game
|
|
||||||
--License for code WTFPL and otherwise stated in readmes
|
|
||||||
|
|
||||||
local pi = math.pi
|
|
||||||
local atann = math.atan
|
|
||||||
local atan = function(x)
|
|
||||||
if not x or x ~= x then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return atann(x)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local dir_to_pitch = function(dir)
|
|
||||||
local dir2 = vector.normalize(dir)
|
|
||||||
local xz = math.abs(dir.x) + math.abs(dir.z)
|
|
||||||
return -math.atan2(-dir.y, xz)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function degrees(rad)
|
|
||||||
return rad * 180.0 / math.pi
|
|
||||||
end
|
|
||||||
|
|
||||||
local S = minetest.get_translator(minetest.get_current_modname())
|
|
||||||
|
|
||||||
--###################
|
|
||||||
--################### dolphin
|
|
||||||
--###################
|
|
||||||
|
|
||||||
local dolphin = {
|
|
||||||
type = "animal",
|
|
||||||
spawn_class = "water",
|
|
||||||
can_despawn = true,
|
|
||||||
passive = true,
|
|
||||||
hp_min = 10,
|
|
||||||
hp_max = 10,
|
|
||||||
xp_min = 1,
|
|
||||||
xp_max = 3,
|
|
||||||
armor = 100,
|
|
||||||
walk_chance = 100,
|
|
||||||
breath_max = 120,
|
|
||||||
rotate = 180,
|
|
||||||
spawn_in_group_min = 3,
|
|
||||||
spawn_in_group = 5,
|
|
||||||
tilt_swim = true,
|
|
||||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
|
|
||||||
visual = "mesh",
|
|
||||||
mesh = "extra_mobs_dolphin.b3d",
|
|
||||||
textures = {
|
|
||||||
{"extra_mobs_dolphin.png"}
|
|
||||||
},
|
|
||||||
sounds = {
|
|
||||||
},
|
|
||||||
animation = {
|
|
||||||
stand_start = 20,
|
|
||||||
stand_end = 20,
|
|
||||||
walk_start = 0,
|
|
||||||
walk_end = 15,
|
|
||||||
run_start = 30,
|
|
||||||
run_end = 45,
|
|
||||||
},
|
|
||||||
drops = {
|
|
||||||
{name = "mcl_fishing:fish_raw",
|
|
||||||
chance = 1,
|
|
||||||
min = 0,
|
|
||||||
max = 1,},
|
|
||||||
},
|
|
||||||
visual_size = {x=3, y=3},
|
|
||||||
makes_footstep_sound = false,
|
|
||||||
fly = true,
|
|
||||||
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
|
|
||||||
breathes_in_water = true,
|
|
||||||
jump = false,
|
|
||||||
view_range = 16,
|
|
||||||
fear_height = 4,
|
|
||||||
walk_velocity = 3,
|
|
||||||
run_velocity = 6,
|
|
||||||
reach = 2,
|
|
||||||
damage = 2.5,
|
|
||||||
attack_type = "dogfight",
|
|
||||||
do_custom = function(self,dtime)
|
|
||||||
--[[ this is supposed to make them jump out the water but doesn't appear to work very well
|
|
||||||
self.object:set_bone_position("body", vector.new(0,1,0), vector.new(degrees(dir_to_pitch(self.object:get_velocity())) * -1 + 90,0,0))
|
|
||||||
if minetest.get_item_group(self.standing_in, "water") ~= 0 then
|
|
||||||
if self.object:get_velocity().y < 5 then
|
|
||||||
self.object:add_velocity({ x = 0 , y = math.random(-.007, .007), z = 0 })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--]]
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:dolphin", dolphin)
|
|
||||||
|
|
||||||
|
|
||||||
--spawning TO DO: in schools
|
|
||||||
local water = 0
|
|
||||||
mcl_mobs:spawn_specific(
|
|
||||||
"mobs_mc:dolphin",
|
|
||||||
"overworld",
|
|
||||||
"water",
|
|
||||||
{
|
|
||||||
"Mesa",
|
|
||||||
"FlowerForest",
|
|
||||||
"Swampland",
|
|
||||||
"Taiga",
|
|
||||||
"ExtremeHills",
|
|
||||||
"Jungle",
|
|
||||||
"Savanna",
|
|
||||||
"BirchForest",
|
|
||||||
"MegaSpruceTaiga",
|
|
||||||
"MegaTaiga",
|
|
||||||
"ExtremeHills+",
|
|
||||||
"Forest",
|
|
||||||
"Plains",
|
|
||||||
"Desert",
|
|
||||||
"ColdTaiga",
|
|
||||||
"MushroomIsland",
|
|
||||||
"IcePlainsSpikes",
|
|
||||||
"SunflowerPlains",
|
|
||||||
"IcePlains",
|
|
||||||
"RoofedForest",
|
|
||||||
"ExtremeHills+_snowtop",
|
|
||||||
"MesaPlateauFM_grasstop",
|
|
||||||
"JungleEdgeM",
|
|
||||||
"ExtremeHillsM",
|
|
||||||
"JungleM",
|
|
||||||
"BirchForestM",
|
|
||||||
"MesaPlateauF",
|
|
||||||
"MesaPlateauFM",
|
|
||||||
"MesaPlateauF_grasstop",
|
|
||||||
"MesaBryce",
|
|
||||||
"JungleEdge",
|
|
||||||
"SavannaM",
|
|
||||||
"FlowerForest_beach",
|
|
||||||
"Forest_beach",
|
|
||||||
"StoneBeach",
|
|
||||||
"Taiga_beach",
|
|
||||||
"Savanna_beach",
|
|
||||||
"Plains_beach",
|
|
||||||
"ExtremeHills_beach",
|
|
||||||
"ColdTaiga_beach",
|
|
||||||
"Swampland_shore",
|
|
||||||
"MushroomIslandShore",
|
|
||||||
"JungleM_shore",
|
|
||||||
"Jungle_shore",
|
|
||||||
"MesaPlateauFM_sandlevel",
|
|
||||||
"MesaPlateauF_sandlevel",
|
|
||||||
"MesaBryce_sandlevel",
|
|
||||||
"Mesa_sandlevel",
|
|
||||||
"RoofedForest_ocean",
|
|
||||||
"JungleEdgeM_ocean",
|
|
||||||
"BirchForestM_ocean",
|
|
||||||
"BirchForest_ocean",
|
|
||||||
"IcePlains_deep_ocean",
|
|
||||||
"Jungle_deep_ocean",
|
|
||||||
"Savanna_ocean",
|
|
||||||
"MesaPlateauF_ocean",
|
|
||||||
"ExtremeHillsM_deep_ocean",
|
|
||||||
"Savanna_deep_ocean",
|
|
||||||
"SunflowerPlains_ocean",
|
|
||||||
"Swampland_deep_ocean",
|
|
||||||
"Swampland_ocean",
|
|
||||||
"MegaSpruceTaiga_deep_ocean",
|
|
||||||
"ExtremeHillsM_ocean",
|
|
||||||
"JungleEdgeM_deep_ocean",
|
|
||||||
"SunflowerPlains_deep_ocean",
|
|
||||||
"BirchForest_deep_ocean",
|
|
||||||
"IcePlainsSpikes_ocean",
|
|
||||||
"Mesa_ocean",
|
|
||||||
"StoneBeach_ocean",
|
|
||||||
"Plains_deep_ocean",
|
|
||||||
"JungleEdge_deep_ocean",
|
|
||||||
"SavannaM_deep_ocean",
|
|
||||||
"Desert_deep_ocean",
|
|
||||||
"Mesa_deep_ocean",
|
|
||||||
"ColdTaiga_deep_ocean",
|
|
||||||
"Plains_ocean",
|
|
||||||
"MesaPlateauFM_ocean",
|
|
||||||
"Forest_deep_ocean",
|
|
||||||
"JungleM_deep_ocean",
|
|
||||||
"FlowerForest_deep_ocean",
|
|
||||||
"MushroomIsland_ocean",
|
|
||||||
"MegaTaiga_ocean",
|
|
||||||
"StoneBeach_deep_ocean",
|
|
||||||
"IcePlainsSpikes_deep_ocean",
|
|
||||||
"ColdTaiga_ocean",
|
|
||||||
"SavannaM_ocean",
|
|
||||||
"MesaPlateauF_deep_ocean",
|
|
||||||
"MesaBryce_deep_ocean",
|
|
||||||
"ExtremeHills+_deep_ocean",
|
|
||||||
"ExtremeHills_ocean",
|
|
||||||
"MushroomIsland_deep_ocean",
|
|
||||||
"Forest_ocean",
|
|
||||||
"MegaTaiga_deep_ocean",
|
|
||||||
"JungleEdge_ocean",
|
|
||||||
"MesaBryce_ocean",
|
|
||||||
"MegaSpruceTaiga_ocean",
|
|
||||||
"ExtremeHills+_ocean",
|
|
||||||
"Jungle_ocean",
|
|
||||||
"RoofedForest_deep_ocean",
|
|
||||||
"IcePlains_ocean",
|
|
||||||
"FlowerForest_ocean",
|
|
||||||
"ExtremeHills_deep_ocean",
|
|
||||||
"MesaPlateauFM_deep_ocean",
|
|
||||||
"Desert_ocean",
|
|
||||||
"Taiga_ocean",
|
|
||||||
"BirchForestM_deep_ocean",
|
|
||||||
"Taiga_deep_ocean",
|
|
||||||
"JungleM_ocean",
|
|
||||||
"FlowerForest_underground",
|
|
||||||
"JungleEdge_underground",
|
|
||||||
"StoneBeach_underground",
|
|
||||||
"MesaBryce_underground",
|
|
||||||
"Mesa_underground",
|
|
||||||
"RoofedForest_underground",
|
|
||||||
"Jungle_underground",
|
|
||||||
"Swampland_underground",
|
|
||||||
"MushroomIsland_underground",
|
|
||||||
"BirchForest_underground",
|
|
||||||
"Plains_underground",
|
|
||||||
"MesaPlateauF_underground",
|
|
||||||
"ExtremeHills_underground",
|
|
||||||
"MegaSpruceTaiga_underground",
|
|
||||||
"BirchForestM_underground",
|
|
||||||
"SavannaM_underground",
|
|
||||||
"MesaPlateauFM_underground",
|
|
||||||
"Desert_underground",
|
|
||||||
"Savanna_underground",
|
|
||||||
"Forest_underground",
|
|
||||||
"SunflowerPlains_underground",
|
|
||||||
"ColdTaiga_underground",
|
|
||||||
"IcePlains_underground",
|
|
||||||
"IcePlainsSpikes_underground",
|
|
||||||
"MegaTaiga_underground",
|
|
||||||
"Taiga_underground",
|
|
||||||
"ExtremeHills+_underground",
|
|
||||||
"JungleM_underground",
|
|
||||||
"ExtremeHillsM_underground",
|
|
||||||
"JungleEdgeM_underground",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
minetest.LIGHT_MAX+1,
|
|
||||||
30,
|
|
||||||
4000,
|
|
||||||
3,
|
|
||||||
water-16,
|
|
||||||
water+1)
|
|
||||||
|
|
||||||
--spawn egg
|
|
||||||
mcl_mobs:register_egg("mobs_mc:dolphin", S("Dolphin"), "#223b4d", "#f9f9f9", 0)
|
|
|
@ -4,50 +4,6 @@
|
||||||
|
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
local BEAM_CHECK_FREQUENCY = 2
|
|
||||||
local POS_CHECK_FREQUENCY = 15
|
|
||||||
local HEAL_AMMOUNT = 37
|
|
||||||
|
|
||||||
local function heal(self)
|
|
||||||
local o = self.object
|
|
||||||
self.health = math.min(self.hp_max,self.health + HEAL_AMMOUNT)
|
|
||||||
end
|
|
||||||
local function check_beam(self)
|
|
||||||
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
|
|
||||||
local luaentity = obj:get_luaentity()
|
|
||||||
if luaentity and luaentity.name == "mcl_end:crystal" then
|
|
||||||
if luaentity.beam then
|
|
||||||
if luaentity.beam == self.beam then
|
|
||||||
heal(self)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if self.beam then
|
|
||||||
self.beam:remove()
|
|
||||||
end
|
|
||||||
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function check_pos(self)
|
|
||||||
if self._portal_pos then
|
|
||||||
-- migrate old format
|
|
||||||
if type(self._portal_pos) == "string" then
|
|
||||||
self._portal_pos = minetest.string_to_pos(self._portal_pos)
|
|
||||||
end
|
|
||||||
local portal_center = vector.add(self._portal_pos, vector.new(0, 11, 0))
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if vector.distance(pos, portal_center) > 50 then
|
|
||||||
self.object:set_pos(self._last_good_pos or portal_center)
|
|
||||||
else
|
|
||||||
self._last_good_pos = pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
||||||
description = S("Ender Dragon"),
|
description = S("Ender Dragon"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
|
@ -67,7 +23,7 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
||||||
{"mobs_mc_dragon.png"},
|
{"mobs_mc_dragon.png"},
|
||||||
},
|
},
|
||||||
visual_size = {x=3, y=3},
|
visual_size = {x=3, y=3},
|
||||||
view_range = 64,
|
view_range = 35,
|
||||||
walk_velocity = 6,
|
walk_velocity = 6,
|
||||||
run_velocity = 6,
|
run_velocity = 6,
|
||||||
can_despawn = false,
|
can_despawn = false,
|
||||||
|
@ -79,7 +35,6 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
||||||
},
|
},
|
||||||
physical = true,
|
physical = true,
|
||||||
damage = 10,
|
damage = 10,
|
||||||
knock_back = false,
|
|
||||||
jump = true,
|
jump = true,
|
||||||
jump_height = 14,
|
jump_height = 14,
|
||||||
fly = true,
|
fly = true,
|
||||||
|
@ -105,33 +60,45 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
||||||
run_start = 0, run_end = 20,
|
run_start = 0, run_end = 20,
|
||||||
},
|
},
|
||||||
ignores_nametag = true,
|
ignores_nametag = true,
|
||||||
do_custom = function(self,dtime)
|
do_custom = function(self)
|
||||||
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
|
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
|
||||||
if self._pos_timer == nil or self._pos_timer > POS_CHECK_FREQUENCY then
|
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
|
||||||
self._pos_timer = 0
|
local luaentity = obj:get_luaentity()
|
||||||
check_pos(self)
|
if luaentity and luaentity.name == "mcl_end:crystal" then
|
||||||
|
if luaentity.beam then
|
||||||
|
if luaentity.beam == self.beam then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if self.beam then
|
||||||
|
self.beam:remove()
|
||||||
|
end
|
||||||
|
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self._portal_pos then
|
||||||
|
-- migrate old format
|
||||||
|
if type(self._portal_pos) == "string" then
|
||||||
|
self._portal_pos = minetest.string_to_pos(self._portal_pos)
|
||||||
|
end
|
||||||
|
local portal_center = vector.add(self._portal_pos, vector.new(3, 11, 3))
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
if vector.distance(pos, portal_center) > 50 then
|
||||||
|
self.object:set_pos(self._last_good_pos or portal_center)
|
||||||
|
else
|
||||||
|
self._last_good_pos = pos
|
||||||
end
|
end
|
||||||
if self._beam_timer == nil or self._beam_timer > BEAM_CHECK_FREQUENCY then
|
|
||||||
self._beam_timer = 0
|
|
||||||
check_beam(self)
|
|
||||||
end
|
end
|
||||||
self._beam_timer = self._beam_timer + dtime
|
|
||||||
self._pos_timer = self._pos_timer + dtime
|
|
||||||
end,
|
end,
|
||||||
on_die = function(self, pos, cmi_cause)
|
on_die = function(self, pos)
|
||||||
if self._portal_pos then
|
if self._portal_pos then
|
||||||
mcl_portals.spawn_gateway_portal()
|
mcl_portals.spawn_gateway_portal()
|
||||||
mcl_structures.place_structure(self._portal_pos,mcl_structures.registered_structures["end_exit_portal_open"],PseudoRandom(minetest.get_mapgen_setting("seed")),-1)
|
mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open")
|
||||||
if self._initial then
|
if self._initial then
|
||||||
mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000
|
mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000
|
||||||
minetest.set_node(vector.add(self._portal_pos, vector.new(0, 5, 0)), {name = "mcl_end:dragon_egg"})
|
minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = "mcl_end:dragon_egg"})
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Free The End Advancement
|
|
||||||
for _,players in pairs(minetest.get_objects_inside_radius(pos,64)) do
|
|
||||||
if players:is_player() then
|
|
||||||
awards.unlock(players:get_player_name(), "mcl:freeTheEnd")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -170,7 +137,6 @@ mcl_mobs:register_arrow("mobs_mc:dragon_fireball", {
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
mcl_mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "#252525", "#b313c9", 0, true)
|
mcl_mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "mobs_mc_spawn_icon_dragon.png", 0, true)
|
||||||
|
|
||||||
|
|
||||||
mcl_wip.register_wip_item("mobs_mc:enderdragon")
|
mcl_wip.register_wip_item("mobs_mc:enderdragon")
|
||||||
|
|
|
@ -24,25 +24,7 @@
|
||||||
-- added rain damage.
|
-- added rain damage.
|
||||||
-- fixed the grass_with_dirt issue.
|
-- fixed the grass_with_dirt issue.
|
||||||
|
|
||||||
minetest.register_entity("mobs_mc:ender_eyes", {
|
|
||||||
visual = "mesh",
|
|
||||||
mesh = "mobs_mc_spider.b3d",
|
|
||||||
visual_size = {x=1.01, y=1.01},
|
|
||||||
textures = {
|
|
||||||
"mobs_mc_enderman_eyes.png",
|
|
||||||
},
|
|
||||||
on_step = function(self)
|
|
||||||
if self and self.object then
|
|
||||||
if not self.object:get_attach() then
|
|
||||||
self.object:remove()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
glow = 50,
|
|
||||||
})
|
|
||||||
|
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
local enable_damage = minetest.settings:get_bool("enable_damage")
|
|
||||||
|
|
||||||
local telesound = function(pos, is_source)
|
local telesound = function(pos, is_source)
|
||||||
local snd
|
local snd
|
||||||
|
@ -237,7 +219,6 @@ local select_enderman_animation = function(animation_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||||
local spawners = {}
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:enderman", {
|
mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
description = S("Enderman"),
|
description = S("Enderman"),
|
||||||
|
@ -255,19 +236,6 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
textures = create_enderman_textures(),
|
textures = create_enderman_textures(),
|
||||||
visual_size = {x=3, y=3},
|
visual_size = {x=3, y=3},
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
on_spawn = function(self)
|
|
||||||
local spider_eyes=false
|
|
||||||
for n = 1, #self.object:get_children() do
|
|
||||||
local obj = self.object:get_children()[n]
|
|
||||||
if obj:get_luaentity() and self.object:get_luaentity().name == "mobs_mc:ender_eyes" then
|
|
||||||
spider_eyes = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not spider_eyes then
|
|
||||||
minetest.add_entity(self.object:get_pos(), "mobs_mc:ender_eyes"):set_attach(self.object, "head.top", vector.new(0,2.54,-1.99), vector.new(90,0,180))
|
|
||||||
minetest.add_entity(self.object:get_pos(), "mobs_mc:ender_eyes"):set_attach(self.object, "head.top", vector.new(1,2.54,-1.99), vector.new(90,0,180))
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
sounds = {
|
sounds = {
|
||||||
-- TODO: Custom war cry sound
|
-- TODO: Custom war cry sound
|
||||||
war_cry = "mobs_sandmonster",
|
war_cry = "mobs_sandmonster",
|
||||||
|
@ -289,48 +257,23 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
},
|
},
|
||||||
animation = select_enderman_animation("normal"),
|
animation = select_enderman_animation("normal"),
|
||||||
_taken_node = "",
|
_taken_node = "",
|
||||||
can_spawn = function(pos)
|
|
||||||
return #minetest.find_nodes_in_area(vector.offset(pos,0,1,0),vector.offset(pos,0,3,0),{"air"}) > 2
|
|
||||||
end,
|
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
-- PARTICLE BEHAVIOUR HERE.
|
-- PARTICLE BEHAVIOUR HERE.
|
||||||
local enderpos = self.object:get_pos()
|
local enderpos = self.object:get_pos()
|
||||||
if self._particle_timer and self._particle_timer >= 1 then
|
local chanceOfParticle = math.random(0, 1)
|
||||||
for _,player in pairs(minetest.get_connected_players()) do
|
if chanceOfParticle == 1 then
|
||||||
if not spawners[player] then spawners[player] = {} end
|
minetest.add_particle({
|
||||||
local dst = vector.distance(player:get_pos(),enderpos)
|
pos = {x=enderpos.x+math.random(-1,1)*math.random()/2,y=enderpos.y+math.random(0,3),z=enderpos.z+math.random(-1,1)*math.random()/2},
|
||||||
if dst < 128 and not spawners[player][self.object] then
|
velocity = {x=math.random(-.25,.25), y=math.random(-.25,.25), z=math.random(-.25,.25)},
|
||||||
self._particle_timer = 0
|
acceleration = {x=math.random(-.5,.5), y=math.random(-.5,.5), z=math.random(-.5,.5)},
|
||||||
spawners[player][self.object] = minetest.add_particlespawner({
|
expirationtime = math.random(),
|
||||||
amount = 5,
|
size = math.random(),
|
||||||
minpos = vector.new(-0.6,0,-0.6),
|
|
||||||
maxpos = vector.new(0.6,3,0.6),
|
|
||||||
minvel = vector.new(-0.25,-0.25,-0.25),
|
|
||||||
maxvel = vector.new(0.25,0.25,0.25),
|
|
||||||
minacc = vector.new(-0.5,-0.5,-0.5),
|
|
||||||
maxacc = vector.new(0.5,0.5,0.5),
|
|
||||||
minexptime = 0.2,
|
|
||||||
maxexptime = 3,
|
|
||||||
minsize = 0.2,
|
|
||||||
maxsize = 1.2,
|
|
||||||
collisiondetection = true,
|
collisiondetection = true,
|
||||||
vertical = false,
|
vertical = false,
|
||||||
time = 0,
|
|
||||||
texture = "mcl_portals_particle"..math.random(1, 5)..".png",
|
texture = "mcl_portals_particle"..math.random(1, 5)..".png",
|
||||||
attached = self.object,
|
|
||||||
playername = player:get_player_name(),
|
|
||||||
})
|
})
|
||||||
elseif dst > 128 and spawners[player][self.object] then
|
|
||||||
minetest.delete_particlespawner(spawners[player][self.object])
|
|
||||||
spawners[player][self.object] = nil
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
elseif not self._particle_timer then
|
|
||||||
self._particle_timer = 0
|
|
||||||
end
|
|
||||||
self._particle_timer = self._particle_timer + dtime
|
|
||||||
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
|
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
|
||||||
enderpos = self.object:get_pos()
|
|
||||||
local dim = mcl_worlds.pos_to_dimension(enderpos)
|
local dim = mcl_worlds.pos_to_dimension(enderpos)
|
||||||
if dim == "overworld" then
|
if dim == "overworld" then
|
||||||
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
|
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
|
||||||
|
@ -366,6 +309,10 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
else return end
|
else return end
|
||||||
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
|
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
|
||||||
if self.state == "attack" then
|
if self.state == "attack" then
|
||||||
|
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||||
|
--self:teleport(nil)
|
||||||
|
--self.state = ""
|
||||||
|
--else
|
||||||
if self.attack then
|
if self.attack then
|
||||||
local target = self.attack
|
local target = self.attack
|
||||||
local pos = target:get_pos()
|
local pos = target:get_pos()
|
||||||
|
@ -375,16 +322,11 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else --if not attacking try to tp to the dark
|
--end
|
||||||
local light = minetest.get_node_light(enderpos)
|
|
||||||
if light and light > minetest.LIGHT_MAX then
|
|
||||||
self:teleport(nil)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
||||||
-- Check for arrows and people nearby.
|
-- Check for arrows and people nearby.
|
||||||
|
local enderpos = self.object:get_pos()
|
||||||
enderpos = self.object:get_pos()
|
|
||||||
enderpos.y = enderpos.y + 1.5
|
enderpos.y = enderpos.y + 1.5
|
||||||
local objs = minetest.get_objects_inside_radius(enderpos, 2)
|
local objs = minetest.get_objects_inside_radius(enderpos, 2)
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
@ -413,7 +355,7 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
-- self:teleport(nil)
|
-- self:teleport(nil)
|
||||||
-- self.state = ""
|
-- self.state = ""
|
||||||
--else
|
--else
|
||||||
if self.attack ~= nil and enable_damage then
|
if self.attack ~= nil and not minetest.settings:get_bool("creative_mode") then
|
||||||
self.state = 'attack'
|
self.state = 'attack'
|
||||||
end
|
end
|
||||||
--end
|
--end
|
||||||
|
@ -648,14 +590,6 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||||
attack_type = "dogfight",
|
attack_type = "dogfight",
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
|
||||||
if not spawners[player] then return end
|
|
||||||
for _,s in pairs(spawners[player]) do
|
|
||||||
minetest.delete_particlespawner(s)
|
|
||||||
end
|
|
||||||
spawners[player] = nil
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
-- End spawn
|
-- End spawn
|
||||||
mcl_mobs:spawn_specific(
|
mcl_mobs:spawn_specific(
|
||||||
|
@ -663,12 +597,7 @@ mcl_mobs:spawn_specific(
|
||||||
"end",
|
"end",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"End",
|
"End"
|
||||||
"EndIsland",
|
|
||||||
"EndMidlands",
|
|
||||||
"EndBarrens",
|
|
||||||
"EndBorder",
|
|
||||||
"EndSmallIslands"
|
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
|
@ -698,6 +627,7 @@ mcl_mobs:spawn_specific(
|
||||||
"Plains",
|
"Plains",
|
||||||
"Desert",
|
"Desert",
|
||||||
"ColdTaiga",
|
"ColdTaiga",
|
||||||
|
"MushroomIsland",
|
||||||
"IcePlainsSpikes",
|
"IcePlainsSpikes",
|
||||||
"SunflowerPlains",
|
"SunflowerPlains",
|
||||||
"IcePlains",
|
"IcePlains",
|
||||||
|
@ -724,6 +654,7 @@ mcl_mobs:spawn_specific(
|
||||||
"ExtremeHills_beach",
|
"ExtremeHills_beach",
|
||||||
"ColdTaiga_beach",
|
"ColdTaiga_beach",
|
||||||
"Swampland_shore",
|
"Swampland_shore",
|
||||||
|
"MushroomIslandShore",
|
||||||
"JungleM_shore",
|
"JungleM_shore",
|
||||||
"Jungle_shore",
|
"Jungle_shore",
|
||||||
"MesaPlateauFM_sandlevel",
|
"MesaPlateauFM_sandlevel",
|
||||||
|
@ -762,6 +693,7 @@ mcl_mobs:spawn_specific(
|
||||||
"Forest_deep_ocean",
|
"Forest_deep_ocean",
|
||||||
"JungleM_deep_ocean",
|
"JungleM_deep_ocean",
|
||||||
"FlowerForest_deep_ocean",
|
"FlowerForest_deep_ocean",
|
||||||
|
"MushroomIsland_ocean",
|
||||||
"MegaTaiga_ocean",
|
"MegaTaiga_ocean",
|
||||||
"StoneBeach_deep_ocean",
|
"StoneBeach_deep_ocean",
|
||||||
"IcePlainsSpikes_deep_ocean",
|
"IcePlainsSpikes_deep_ocean",
|
||||||
|
@ -771,6 +703,7 @@ mcl_mobs:spawn_specific(
|
||||||
"MesaBryce_deep_ocean",
|
"MesaBryce_deep_ocean",
|
||||||
"ExtremeHills+_deep_ocean",
|
"ExtremeHills+_deep_ocean",
|
||||||
"ExtremeHills_ocean",
|
"ExtremeHills_ocean",
|
||||||
|
"MushroomIsland_deep_ocean",
|
||||||
"Forest_ocean",
|
"Forest_ocean",
|
||||||
"MegaTaiga_deep_ocean",
|
"MegaTaiga_deep_ocean",
|
||||||
"JungleEdge_ocean",
|
"JungleEdge_ocean",
|
||||||
|
@ -796,6 +729,7 @@ mcl_mobs:spawn_specific(
|
||||||
"RoofedForest_underground",
|
"RoofedForest_underground",
|
||||||
"Jungle_underground",
|
"Jungle_underground",
|
||||||
"Swampland_underground",
|
"Swampland_underground",
|
||||||
|
"MushroomIsland_underground",
|
||||||
"BirchForest_underground",
|
"BirchForest_underground",
|
||||||
"Plains_underground",
|
"Plains_underground",
|
||||||
"MesaPlateauF_underground",
|
"MesaPlateauF_underground",
|
||||||
|
@ -832,32 +766,15 @@ mcl_mobs:spawn_specific(
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether",
|
"Nether"
|
||||||
"SoulsandValley",
|
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
11,
|
7,
|
||||||
30,
|
30,
|
||||||
27500,
|
27500,
|
||||||
4,
|
4,
|
||||||
mcl_vars.mg_nether_min,
|
mcl_vars.mg_nether_min,
|
||||||
mcl_vars.mg_nether_max)
|
mcl_vars.mg_nether_max)
|
||||||
|
|
||||||
-- Warped Forest spawn (common)
|
|
||||||
mcl_mobs:spawn_specific(
|
|
||||||
"mobs_mc:enderman",
|
|
||||||
"nether",
|
|
||||||
"ground",
|
|
||||||
{
|
|
||||||
"WarpedForest"
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
11,
|
|
||||||
30,
|
|
||||||
5000,
|
|
||||||
4,
|
|
||||||
mcl_vars.mg_nether_min,
|
|
||||||
mcl_vars.mg_nether_max)
|
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "#252525", "#151515", 0)
|
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)
|
||||||
|
|
|
@ -38,4 +38,4 @@ mcl_mobs:register_mob("mobs_mc:endermite", {
|
||||||
reach = 1,
|
reach = 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
mcl_mobs:register_egg("mobs_mc:endermite", S("Endermite"), "#161616", "#6d6d6d", 0)
|
mcl_mobs:register_egg("mobs_mc:endermite", S("Endermite"), "mobs_mc_spawn_icon_endermite.png", 0)
|
||||||
|
|
|
@ -23,7 +23,6 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
|
||||||
collisionbox = {-2, 5, -2, 2, 9, 2},
|
collisionbox = {-2, 5, -2, 2, 9, 2},
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_ghast.b3d",
|
mesh = "mobs_mc_ghast.b3d",
|
||||||
spawn_in_group = 1,
|
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_ghast.png"},
|
{"mobs_mc_ghast.png"},
|
||||||
},
|
},
|
||||||
|
@ -65,14 +64,6 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
|
||||||
makes_footstep_sound = false,
|
makes_footstep_sound = false,
|
||||||
instant_death = true,
|
instant_death = true,
|
||||||
fire_resistant = true,
|
fire_resistant = true,
|
||||||
can_spawn = function(pos)
|
|
||||||
if not minetest.get_item_group(minetest.get_node(pos).name,"solid") then return false end
|
|
||||||
local p1=vector.offset(pos,-2,1,-2)
|
|
||||||
local p2=vector.offset(pos,2,5,2)
|
|
||||||
local nn = minetest.find_nodes_in_area(p1,p2,{"air"})
|
|
||||||
if #nn< 41 then return false end
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
do_custom = function(self)
|
do_custom = function(self)
|
||||||
if self.firing == true then
|
if self.firing == true then
|
||||||
self.base_texture = {"mobs_mc_ghast_firing.png"}
|
self.base_texture = {"mobs_mc_ghast_firing.png"}
|
||||||
|
@ -90,14 +81,12 @@ mcl_mobs:spawn_specific(
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether",
|
"Nether"
|
||||||
"SoulsandValley",
|
|
||||||
"BasaltDelta",
|
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
7,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
72000,
|
18000,
|
||||||
2,
|
2,
|
||||||
mcl_vars.mg_nether_min,
|
mcl_vars.mg_nether_min,
|
||||||
mcl_vars.mg_nether_max)
|
mcl_vars.mg_nether_max)
|
||||||
|
@ -116,12 +105,7 @@ mcl_mobs:register_arrow("mobs_mc:fireball", {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
damage_groups = {fleshy = 6},
|
damage_groups = {fleshy = 6},
|
||||||
}, nil)
|
}, nil)
|
||||||
local p = self.object:get_pos()
|
mcl_mobs:boom(self, self.object:get_pos(), 1, true)
|
||||||
if p then
|
|
||||||
mcl_mobs:boom(self, p, 1, true)
|
|
||||||
else
|
|
||||||
mcl_mobs:boom(self, player:get_pos(), 1, true)
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
hit_mob = function(self, mob)
|
hit_mob = function(self, mob)
|
||||||
|
@ -141,4 +125,4 @@ mcl_mobs:register_arrow("mobs_mc:fireball", {
|
||||||
|
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:ghast", S("Ghast"), "#f9f9f9", "#bcbcbc", 0)
|
mcl_mobs:register_egg("mobs_mc:ghast", S("Ghast"), "mobs_mc_spawn_icon_ghast.png", 0)
|
||||||
|
|
|
@ -8,8 +8,6 @@ mcl_mobs:register_mob("mobs_mc:guardian", {
|
||||||
description = S("Guardian"),
|
description = S("Guardian"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
spawn_in_group_min = 2,
|
|
||||||
spawn_in_group = 4,
|
|
||||||
hp_min = 30,
|
hp_min = 30,
|
||||||
hp_max = 30,
|
hp_max = 30,
|
||||||
xp_min = 10,
|
xp_min = 10,
|
||||||
|
@ -104,4 +102,4 @@ mcl_mobs:register_mob("mobs_mc:guardian", {
|
||||||
--mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10)
|
--mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:guardian", S("Guardian"), "#5a8272", "#f17d31", 0)
|
mcl_mobs:register_egg("mobs_mc:guardian", S("Guardian"), "mobs_mc_spawn_icon_guardian.png", 0)
|
||||||
|
|
|
@ -112,6 +112,5 @@ mcl_mobs:register_mob("mobs_mc:guardian_elder", {
|
||||||
-- mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18)
|
-- mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "#ceccba", "#747693", 0)
|
mcl_mobs:register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "mobs_mc_spawn_icon_guardian_elder.png", 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,30 +34,6 @@ local horse_extra_texture = function(horse)
|
||||||
return textures
|
return textures
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_drops(self)
|
|
||||||
self.drops = {}
|
|
||||||
table.insert(self.drops,
|
|
||||||
{name = "mcl_mobitems:leather",
|
|
||||||
chance = 1,
|
|
||||||
min = 0,
|
|
||||||
max = 2,
|
|
||||||
looting = "common",
|
|
||||||
})
|
|
||||||
if self._saddle then
|
|
||||||
table.insert(self.drops,{name = "mcl_mobitems:saddle",
|
|
||||||
chance = 1,
|
|
||||||
min = 1,
|
|
||||||
max = 1,})
|
|
||||||
end
|
|
||||||
if self._chest then
|
|
||||||
table.insert(self.drops,{name = "mcl_chests:chest",
|
|
||||||
chance = 1,
|
|
||||||
min = 1,
|
|
||||||
max = 1,})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Helper functions to determine equipment rules
|
-- Helper functions to determine equipment rules
|
||||||
local can_equip_horse_armor = function(entity_id)
|
local can_equip_horse_armor = function(entity_id)
|
||||||
return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse"
|
return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse"
|
||||||
|
@ -105,27 +81,11 @@ for b=1, #horse_base do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- in e7898352d890c2414af653eba624939df9c0b8b4 (0.76-dev) all items from mobs_mc were moved to mcl_mobitems
|
|
||||||
-- this results in existing horses wearing armor would still have the old texture filename in their
|
|
||||||
-- properties this function updates them. It should be removed some time in the future when we can be
|
|
||||||
-- reasonably sure all horses that want it get the new nexture.
|
|
||||||
local function update_textures(self)
|
|
||||||
local old = "mobs_mc_horse_armor_"
|
|
||||||
local txt = self.object:get_properties().textures
|
|
||||||
if txt[2]:find(old) then
|
|
||||||
txt[2] = txt[2]:gsub(old,"mcl_mobitems_horse_armor_")
|
|
||||||
self.object:set_properties({textures=txt})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Horse
|
-- Horse
|
||||||
local horse = {
|
local horse = {
|
||||||
description = S("Horse"),
|
description = S("Horse"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
spawn_in_group_min = 2,
|
|
||||||
spawn_in_group = 6,
|
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_horse.b3d",
|
mesh = "mobs_mc_horse.b3d",
|
||||||
visual_size = {x=3.0, y=3.0},
|
visual_size = {x=3.0, y=3.0},
|
||||||
|
@ -178,7 +138,7 @@ local horse = {
|
||||||
max = 2,
|
max = 2,
|
||||||
looting = "common",},
|
looting = "common",},
|
||||||
},
|
},
|
||||||
on_spawn = update_textures,
|
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
|
||||||
-- set needed values if not already present
|
-- set needed values if not already present
|
||||||
|
@ -261,27 +221,6 @@ local horse = {
|
||||||
local iname = item:get_name()
|
local iname = item:get_name()
|
||||||
local heal = 0
|
local heal = 0
|
||||||
|
|
||||||
if self._inv_id then
|
|
||||||
if not self._chest and item:get_name() == "mcl_chests:chest" then
|
|
||||||
item:take_item()
|
|
||||||
clicker:set_wielded_item(item)
|
|
||||||
self._chest = true
|
|
||||||
-- Update texture
|
|
||||||
if not self._naked_texture then
|
|
||||||
-- Base horse texture without chest or saddle
|
|
||||||
self._naked_texture = self.base_texture[2]
|
|
||||||
end
|
|
||||||
local tex = horse_extra_texture(self)
|
|
||||||
self.base_texture = tex
|
|
||||||
self.object:set_properties({textures = self.base_texture})
|
|
||||||
get_drops(self)
|
|
||||||
return
|
|
||||||
elseif self._chest and clicker:get_player_control().sneak then
|
|
||||||
mcl_entity_invs.show_inv_form(self,clicker)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Taming
|
-- Taming
|
||||||
self.temper = self.temper or (math.random(1,100))
|
self.temper = self.temper or (math.random(1,100))
|
||||||
|
|
||||||
|
@ -385,7 +324,6 @@ local horse = {
|
||||||
self.base_texture = tex
|
self.base_texture = tex
|
||||||
self.object:set_properties({textures = self.base_texture})
|
self.object:set_properties({textures = self.base_texture})
|
||||||
minetest.sound_play({name = "mcl_armor_equip_leather"}, {gain=0.5, max_hear_distance=12, pos=self.object:get_pos()}, true)
|
minetest.sound_play({name = "mcl_armor_equip_leather"}, {gain=0.5, max_hear_distance=12, pos=self.object:get_pos()}, true)
|
||||||
get_drops(self)
|
|
||||||
|
|
||||||
-- Put on horse armor if tamed
|
-- Put on horse armor if tamed
|
||||||
elseif can_equip_horse_armor(self.name) and not self.driver and not self._horse_armor
|
elseif can_equip_horse_armor(self.name) and not self.driver and not self._horse_armor
|
||||||
|
@ -538,8 +476,6 @@ local d = 0.86 -- donkey scale
|
||||||
local donkey = table.copy(horse)
|
local donkey = table.copy(horse)
|
||||||
donkey.description = S("Donkey")
|
donkey.description = S("Donkey")
|
||||||
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
||||||
donkey.spawn_in_group = 3
|
|
||||||
donkey.spawn_in_group_min = 1
|
|
||||||
donkey.animation = {
|
donkey.animation = {
|
||||||
speed_normal = 25,
|
speed_normal = 25,
|
||||||
stand_start = 0, stand_end = 0,
|
stand_start = 0, stand_end = 0,
|
||||||
|
@ -564,9 +500,8 @@ donkey.collisionbox = {
|
||||||
donkey.jump = true
|
donkey.jump = true
|
||||||
donkey.jump_height = 3.75 -- can clear 1 block height
|
donkey.jump_height = 3.75 -- can clear 1 block height
|
||||||
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:donkey", donkey)
|
mcl_mobs:register_mob("mobs_mc:donkey", donkey)
|
||||||
mcl_entity_invs.register_inv("mobs_mc:donkey","Donkey",15,true)
|
|
||||||
-- Mule
|
-- Mule
|
||||||
local m = 0.94
|
local m = 0.94
|
||||||
local mule = table.copy(donkey)
|
local mule = table.copy(donkey)
|
||||||
|
@ -584,7 +519,6 @@ mule.collisionbox = {
|
||||||
horse.collisionbox[6] * m,
|
horse.collisionbox[6] * m,
|
||||||
}
|
}
|
||||||
mcl_mobs:register_mob("mobs_mc:mule", mule)
|
mcl_mobs:register_mob("mobs_mc:mule", mule)
|
||||||
mcl_entity_invs.register_inv("mobs_mc:mule","Mule",15,true)
|
|
||||||
|
|
||||||
--===========================
|
--===========================
|
||||||
--Spawn Function
|
--Spawn Function
|
||||||
|
@ -594,14 +528,41 @@ mcl_mobs:spawn_specific(
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"flat",
|
"flat",
|
||||||
|
"IcePlainsSpikes",
|
||||||
|
"ColdTaiga",
|
||||||
|
"ColdTaiga_beach",
|
||||||
|
"ColdTaiga_beach_water",
|
||||||
|
"MegaTaiga",
|
||||||
|
"MegaSpruceTaiga",
|
||||||
|
"ExtremeHills",
|
||||||
|
"ExtremeHills_beach",
|
||||||
|
"ExtremeHillsM",
|
||||||
|
"ExtremeHills+",
|
||||||
|
"ExtremeHills+_snowtop",
|
||||||
|
"StoneBeach",
|
||||||
"Plains",
|
"Plains",
|
||||||
"Plains_beach",
|
"Plains_beach",
|
||||||
"SunflowerPlains",
|
"SunflowerPlains",
|
||||||
|
"Taiga",
|
||||||
|
"Taiga_beach",
|
||||||
|
"Forest",
|
||||||
|
"Forest_beach",
|
||||||
|
"FlowerForest",
|
||||||
|
"FlowerForest_beach",
|
||||||
|
"BirchForest",
|
||||||
|
"BirchForestM",
|
||||||
|
"RoofedForest",
|
||||||
"Savanna",
|
"Savanna",
|
||||||
"Savanna_beach",
|
"Savanna_beach",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
"Savanna_beach",
|
"Jungle",
|
||||||
"Plains_beach",
|
"Jungle_shore",
|
||||||
|
"JungleM",
|
||||||
|
"JungleM_shore",
|
||||||
|
"JungleEdge",
|
||||||
|
"JungleEdgeM",
|
||||||
|
"Swampland",
|
||||||
|
"Swampland_shore"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
|
@ -611,22 +572,20 @@ minetest.LIGHT_MAX+1,
|
||||||
mobs_mc.water_level+3,
|
mobs_mc.water_level+3,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
|
|
||||||
mcl_mobs:spawn_specific(
|
mcl_mobs:spawn_specific(
|
||||||
"mobs_mc:donkey",
|
"mobs_mc:donkey",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"flat",
|
"Mesa",
|
||||||
"Plains",
|
"MesaPlateauFM_grasstop",
|
||||||
"Plains_beach",
|
"MesaPlateauF",
|
||||||
"SunflowerPlains",
|
"MesaPlateauFM",
|
||||||
"Savanna",
|
"MesaPlateauF_grasstop",
|
||||||
"Savanna_beach",
|
"MesaBryce",
|
||||||
"SavannaM",
|
|
||||||
"Savanna_beach",
|
|
||||||
"Plains_beach",
|
|
||||||
},
|
},
|
||||||
9,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
|
@ -635,8 +594,8 @@ mobs_mc.water_level+3,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:horse", S("Horse"), "#c09e7d", "#eee500", 0)
|
mcl_mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
|
||||||
mcl_mobs:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "#68684f", "#e5e5d8", 0)
|
mcl_mobs:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0)
|
||||||
--mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "#2a5a37", "#84d080", 0)
|
--mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
|
||||||
mcl_mobs:register_egg("mobs_mc:donkey", S("Donkey"), "#534539", "#867566", 0)
|
mcl_mobs:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0)
|
||||||
mcl_mobs:register_egg("mobs_mc:mule", S("Mule"), "#1b0200", "#51331d", 0)
|
mcl_mobs:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0)
|
||||||
|
|
|
@ -114,7 +114,6 @@ dofile(path .. "/squid.lua") -- Animation, sound and egg texture by daufinsyd
|
||||||
dofile(path .. "/villager.lua") -- KrupnoPavel Mesh and animation by toby109tt / https://github.com/22i
|
dofile(path .. "/villager.lua") -- KrupnoPavel Mesh and animation by toby109tt / https://github.com/22i
|
||||||
|
|
||||||
-- Illagers and witch
|
-- Illagers and witch
|
||||||
dofile(path .. "/pillager.lua") -- Mesh by KrupnoPavel and MrRar, animation by MrRar
|
|
||||||
dofile(path .. "/villager_evoker.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
dofile(path .. "/villager_evoker.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||||
dofile(path .. "/villager_vindicator.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
dofile(path .. "/villager_vindicator.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||||
dofile(path .. "/villager_zombie.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
dofile(path .. "/villager_zombie.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||||
|
@ -144,7 +143,4 @@ dofile(path .. "/spider.lua") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 li
|
||||||
dofile(path .. "/vex.lua") -- KrupnoPavel
|
dofile(path .. "/vex.lua") -- KrupnoPavel
|
||||||
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||||
|
|
||||||
dofile(path .. "/cod.lua")
|
dofile(path .. "/phantom.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||||
dofile(path .. "/salmon.lua")
|
|
||||||
dofile(path .. "/tropical_fish.lua")
|
|
||||||
dofile(path .. "/dolphin.lua")
|
|
||||||
|
|
|
@ -22,9 +22,6 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", {
|
||||||
collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7},
|
collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7},
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_iron_golem.b3d",
|
mesh = "mobs_mc_iron_golem.b3d",
|
||||||
head_swivel = "head.control",
|
|
||||||
bone_eye_height = 3.38,
|
|
||||||
curiosity = 10,
|
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_iron_golem.png"},
|
{"mobs_mc_iron_golem.png"},
|
||||||
},
|
},
|
||||||
|
@ -40,7 +37,6 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", {
|
||||||
run_velocity = 1.2,
|
run_velocity = 1.2,
|
||||||
-- Approximation
|
-- Approximation
|
||||||
damage = 14,
|
damage = 14,
|
||||||
knock_back = false,
|
|
||||||
reach = 3,
|
reach = 3,
|
||||||
group_attack = true,
|
group_attack = true,
|
||||||
attacks_monsters = true,
|
attacks_monsters = true,
|
||||||
|
@ -96,7 +92,8 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", {
|
||||||
|
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:iron_golem", S("Iron Golem"), "#3b3b3b", "#f57223", 0)
|
mcl_mobs:register_egg("mobs_mc:iron_golem", S("Iron Golem"), "mobs_mc_spawn_icon_iron_golem.png", 0)
|
||||||
|
|
||||||
|
|
||||||
--[[ This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function of the node.
|
--[[ This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function of the node.
|
||||||
This summons an iron golen if placing the pumpkin created an iron golem summon pattern:
|
This summons an iron golen if placing the pumpkin created an iron golem summon pattern:
|
||||||
|
|
|
@ -24,52 +24,15 @@ local carpets = {
|
||||||
unicolor_light_blue = { "mcl_wool:light_blue_carpet", "light_blue" },
|
unicolor_light_blue = { "mcl_wool:light_blue_carpet", "light_blue" },
|
||||||
}
|
}
|
||||||
|
|
||||||
local function get_drops(self)
|
|
||||||
self.drops = {}
|
|
||||||
table.insert(self.drops,
|
|
||||||
{name = "mcl_mobitems:leather",
|
|
||||||
chance = 1,
|
|
||||||
min = 0,
|
|
||||||
max = 2,
|
|
||||||
looting = "common",
|
|
||||||
})
|
|
||||||
if self.carpet then
|
|
||||||
table.insert(self.drops,{name = self.carpet,
|
|
||||||
chance = 1,
|
|
||||||
min = 1,
|
|
||||||
max = 1,})
|
|
||||||
end
|
|
||||||
if self._has_chest then
|
|
||||||
table.insert(self.drops,{name = "mcl_chests:chest",
|
|
||||||
chance = 1,
|
|
||||||
min = 1,
|
|
||||||
max = 1,})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mcl_mobs:register_mob("mobs_mc:llama", {
|
mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
description = S("Llama"),
|
description = S("Llama"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
passive = false,
|
|
||||||
attack_type = "shoot",
|
|
||||||
shoot_interval = 5.5,
|
|
||||||
arrow = "mobs_mc:llamaspit",
|
|
||||||
shoot_offset = 1, --3.5 *would* be a good value visually but it somehow messes with the projectiles trajectory
|
|
||||||
spawn_in_group_min = 4,
|
|
||||||
spawn_in_group = 6,
|
|
||||||
|
|
||||||
head_swivel = "head.control",
|
|
||||||
bone_eye_height = 11,
|
|
||||||
head_eye_height = 3,
|
|
||||||
horrizonatal_head_height=0,
|
|
||||||
curiosity = 60,
|
|
||||||
head_yaw = "z",
|
|
||||||
|
|
||||||
hp_min = 15,
|
hp_min = 15,
|
||||||
hp_max = 30,
|
hp_max = 30,
|
||||||
xp_min = 1,
|
xp_min = 1,
|
||||||
xp_max = 3,
|
xp_max = 3,
|
||||||
|
passive = false,
|
||||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
|
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_llama.b3d",
|
mesh = "mobs_mc_llama.b3d",
|
||||||
|
@ -80,8 +43,9 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
{"blank.png", "blank.png", "mobs_mc_llama_white.png"},
|
{"blank.png", "blank.png", "mobs_mc_llama_white.png"},
|
||||||
{"blank.png", "blank.png", "mobs_mc_llama.png"},
|
{"blank.png", "blank.png", "mobs_mc_llama.png"},
|
||||||
},
|
},
|
||||||
|
visual_size = {x=3, y=3},
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
runaway = false,
|
runaway = true,
|
||||||
walk_velocity = 1,
|
walk_velocity = 1,
|
||||||
run_velocity = 4.4,
|
run_velocity = 4.4,
|
||||||
follow_velocity = 4.4,
|
follow_velocity = 4.4,
|
||||||
|
@ -101,28 +65,36 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
distance = 16,
|
distance = 16,
|
||||||
},
|
},
|
||||||
animation = {
|
animation = {
|
||||||
stand_start = 0, stand_end = 0,
|
speed_normal = 24,
|
||||||
walk_start = 0, walk_end = 40, walk_speed = 35,
|
run_speed = 60,
|
||||||
run_start = 0, run_end = 40, run_speed = 50,
|
run_start = 0,
|
||||||
},
|
run_end = 40,
|
||||||
child_animations = {
|
stand_start = 0,
|
||||||
stand_start = 41, stand_end = 41,
|
stand_end = 0,
|
||||||
walk_start = 41, walk_end = 81, walk_speed = 50,
|
walk_start = 0,
|
||||||
run_start = 41, run_end = 81, run_speed = 75,
|
walk_end = 40,
|
||||||
|
hurt_start = 118,
|
||||||
|
hurt_end = 154,
|
||||||
|
death_start = 154,
|
||||||
|
death_end = 179,
|
||||||
|
eat_start = 49,
|
||||||
|
eat_end = 78,
|
||||||
|
look_start = 78,
|
||||||
|
look_end = 108,
|
||||||
},
|
},
|
||||||
follow = { "mcl_farming:wheat_item", "mcl_farming:hay_block" },
|
follow = { "mcl_farming:wheat_item", "mcl_farming:hay_block" },
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
|
||||||
-- set needed values if not already present
|
-- set needed values if not already present
|
||||||
if not self.v3 then
|
if not self.v2 then
|
||||||
self.v3 = 0
|
self.v2 = 0
|
||||||
self.max_speed_forward = 4
|
self.max_speed_forward = 4
|
||||||
self.max_speed_reverse = 2
|
self.max_speed_reverse = 2
|
||||||
self.accel = 4
|
self.accel = 4
|
||||||
self.terrain_type = 3
|
self.terrain_type = 3
|
||||||
self.driver_attach_at = {x = 0, y = 12.7, z = -5}
|
self.driver_attach_at = {x = 0, y = 4.17, z = -1.5}
|
||||||
self.driver_eye_offset = {x = 0, y = 6, z = 0}
|
self.driver_eye_offset = {x = 0, y = 3, z = 0}
|
||||||
self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y}
|
self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -157,20 +129,6 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
if item:get_name() == "mcl_farming:hay_block" then
|
if item:get_name() == "mcl_farming:hay_block" then
|
||||||
-- Breed with hay bale
|
-- Breed with hay bale
|
||||||
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
|
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
|
||||||
elseif not self._has_chest and item:get_name() == "mcl_chests:chest" then
|
|
||||||
item:take_item()
|
|
||||||
clicker:set_wielded_item(item)
|
|
||||||
self._has_chest = true
|
|
||||||
self.base_texture = table.copy(self.base_texture)
|
|
||||||
self.base_texture[1] = self.base_texture[3]
|
|
||||||
self.object:set_properties({
|
|
||||||
textures = self.base_texture,
|
|
||||||
})
|
|
||||||
get_drops(self)
|
|
||||||
return
|
|
||||||
elseif self._has_chest and clicker:get_player_control().sneak then
|
|
||||||
mcl_entity_invs.show_inv_form(self,clicker," - Strength "..math.floor(self._inv_size / 3))
|
|
||||||
return
|
|
||||||
else
|
else
|
||||||
-- Feed with anything else
|
-- Feed with anything else
|
||||||
if mcl_mobs:feed_tame(self, clicker, 1, false, true) then return end
|
if mcl_mobs:feed_tame(self, clicker, 1, false, true) then return end
|
||||||
|
@ -179,6 +137,7 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
|
|
||||||
-- Make sure tamed llama is mature and being clicked by owner only
|
-- Make sure tamed llama is mature and being clicked by owner only
|
||||||
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
|
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
|
||||||
|
|
||||||
-- Place carpet
|
-- Place carpet
|
||||||
if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then
|
if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then
|
||||||
for group, carpetdata in pairs(carpets) do
|
for group, carpetdata in pairs(carpets) do
|
||||||
|
@ -195,7 +154,16 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
textures = self.base_texture,
|
textures = self.base_texture,
|
||||||
})
|
})
|
||||||
self.carpet = item:get_name()
|
self.carpet = item:get_name()
|
||||||
get_drops(self)
|
self.drops = {
|
||||||
|
{name = "mcl_mobitems:leather",
|
||||||
|
chance = 1,
|
||||||
|
min = 0,
|
||||||
|
max = 2,},
|
||||||
|
{name = item:get_name(),
|
||||||
|
chance = 1,
|
||||||
|
min = 1,
|
||||||
|
max = 1,},
|
||||||
|
}
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -203,12 +171,19 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
|
|
||||||
-- detatch player already riding llama
|
-- detatch player already riding llama
|
||||||
if self.driver and clicker == self.driver then
|
if self.driver and clicker == self.driver then
|
||||||
|
|
||||||
mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1})
|
mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1})
|
||||||
|
|
||||||
-- attach player to llama
|
-- attach player to llama
|
||||||
elseif not self.driver then
|
elseif not self.driver then
|
||||||
|
|
||||||
self.object:set_properties({stepheight = 1.1})
|
self.object:set_properties({stepheight = 1.1})
|
||||||
mcl_mobs.attach(self, clicker)
|
mcl_mobs.attach(self, clicker)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Used to capture llama
|
||||||
|
elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then
|
||||||
|
mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
@ -233,44 +208,7 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_spawn = function(self)
|
|
||||||
if not self._inv_size then
|
|
||||||
local r = math.random(1000)
|
|
||||||
if r < 80 then
|
|
||||||
self._inv_size = 15
|
|
||||||
elseif r < 160 then
|
|
||||||
self._inv_size = 12
|
|
||||||
elseif r < 488 then
|
|
||||||
self._inv_size = 9
|
|
||||||
elseif r < 816 then
|
|
||||||
self._inv_size = 6
|
|
||||||
else
|
|
||||||
self._inv_size = 3
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
mcl_entity_invs.register_inv("mobs_mc:llama","Llama",nil,true)
|
|
||||||
|
|
||||||
-- spit arrow (weapon)
|
|
||||||
mcl_mobs:register_arrow("mobs_mc:llamaspit", {
|
|
||||||
visual = "sprite",
|
|
||||||
visual_size = {x = 0.10, y = 0.10},
|
|
||||||
textures = {"mobs_mc_llama_spit.png"},
|
|
||||||
velocity = 5,
|
|
||||||
hit_player = function(self, player)
|
|
||||||
player:punch(self.object, 1.0, {
|
|
||||||
full_punch_interval = 1.0,
|
|
||||||
damage_groups = {fleshy = 1},
|
|
||||||
}, nil)
|
|
||||||
end,
|
|
||||||
|
|
||||||
hit_mob = function(self, mob)
|
|
||||||
end,
|
|
||||||
|
|
||||||
hit_node = function(self, pos, node)
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
|
|
||||||
--spawn
|
--spawn
|
||||||
|
@ -279,15 +217,19 @@ mcl_mobs:spawn_specific(
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Savanna",
|
"Mesa",
|
||||||
"SavannaM",
|
"MesaPlateauFM_grasstop",
|
||||||
"SavannaM_beach",
|
"MesaPlateauF",
|
||||||
"Savanna_beach",
|
"MesaPlateauFM",
|
||||||
"Savanna_ocean",
|
"MesaPlateauF_grasstop",
|
||||||
"ExtremeHills",
|
"MesaBryce",
|
||||||
"ExtremeHills_beach",
|
"Jungle",
|
||||||
"ExtremeHillsM",
|
"Jungle_shore",
|
||||||
}, --FIXME: Needs Windswept Forest when that is added.
|
"JungleM",
|
||||||
|
"JungleM_shore",
|
||||||
|
"JungleEdge",
|
||||||
|
"JungleEdgeM",
|
||||||
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
|
@ -297,4 +239,4 @@ mobs_mc.water_level+15,
|
||||||
mcl_vars.mg_overworld_max)
|
mcl_vars.mg_overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mcl_mobs:register_egg("mobs_mc:llama", S("Llama"), "#c09e7d", "#995f40", 0)
|
mcl_mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0)
|
||||||
|
|
|
@ -1,58 +1,64 @@
|
||||||
# textdomain: mobs_mc
|
# textdomain: mobs_mc
|
||||||
|
Agent=Agente
|
||||||
Bat=Murciélago
|
Bat=Murciélago
|
||||||
Blaze=Blaze
|
Blaze=Blaze
|
||||||
Chicken=Pollo
|
Chicken=Pollo
|
||||||
Cod=Bacalao
|
|
||||||
Cow=Vaca
|
Cow=Vaca
|
||||||
Mooshroom=Champivaca
|
Mooshroom=Champiñaca
|
||||||
Creeper=Creeper
|
Creeper=Creeper
|
||||||
Dolphin=Delfín
|
Ender Dragon=Enderdragón
|
||||||
Ender Dragon=Ender Dragon
|
|
||||||
Enderman=Enderman
|
Enderman=Enderman
|
||||||
Endermite=Endermite
|
Endermite=Endermite
|
||||||
Ghast=Ghast
|
Ghast=Ghast
|
||||||
|
Elder Guardian=Gran guardián
|
||||||
Guardian=Guardián
|
Guardian=Guardián
|
||||||
Elder Guardian=Guardián Anciano
|
|
||||||
Donkey=Burro
|
|
||||||
Horse=Caballo
|
Horse=Caballo
|
||||||
|
Skeleton Horse=Caballo esquelético
|
||||||
|
Zombie Horse=Caballo zombie
|
||||||
|
Donkey=Burro
|
||||||
Mule=Mula
|
Mule=Mula
|
||||||
Skeleton Horse=Caballo esqueleto
|
|
||||||
Zombie Horse=Caballo zombi
|
|
||||||
Iron Golem=Golem de hierro
|
Iron Golem=Golem de hierro
|
||||||
Llama=Llama
|
Llama=Llama
|
||||||
Cat=Gato
|
|
||||||
Ocelot=Ocelote
|
Ocelot=Ocelote
|
||||||
Parrot=Loro
|
Parrot=Loro
|
||||||
Pig=Cerdo
|
Pig=Cerdo
|
||||||
Polar Bear=Oso polar
|
Polar Bear=Oso polar
|
||||||
Killer Bunny=Conejo asesino
|
|
||||||
Rabbit=Conejo
|
Rabbit=Conejo
|
||||||
Salmon=Salmón
|
Killer Bunny=Conejo asesino
|
||||||
Sheep=Oveja
|
Sheep=Oveja
|
||||||
Shulker=Shulker
|
Shulker=Shulker
|
||||||
Silverfish=Lepisma
|
Silverfish=Lepisma
|
||||||
Skeleton=Esqueleto
|
Skeleton=Esqueleto
|
||||||
Stray=Esqueleto glacial
|
Stray=Esqueleto
|
||||||
Wither Skeleton=Esqueleto del Wither
|
Wither Skeleton=Esqueleto wither
|
||||||
Magma Cube=Cubo de Magma
|
Magma Cube=Cubo de Magma
|
||||||
Slime=Slime
|
Slime=Slime
|
||||||
Snow Golem=Golem de nieve
|
Snow Golem=Golem de nieve
|
||||||
Cave Spider=Araña de las cuevas
|
|
||||||
Spider=Araña
|
Spider=Araña
|
||||||
|
Cave Spider=Araña de las cuevas
|
||||||
Squid=Calamar
|
Squid=Calamar
|
||||||
Vex=Ánima
|
Vex=Ánima
|
||||||
Master=Maestro
|
|
||||||
Villager=Aldeano
|
|
||||||
Evoker=Invocador
|
Evoker=Invocador
|
||||||
Illusioner=Illusionista
|
Illusioner=Illusionista
|
||||||
|
Villager=Aldeano
|
||||||
Vindicator=Vindicador
|
Vindicator=Vindicador
|
||||||
Zombie Villager=Aldeano zombi
|
Zombie Villager=Aldeano zombie
|
||||||
Witch=Bruja
|
Witch=Bruja
|
||||||
Wither=Wither
|
Wither=Wither
|
||||||
Wolf=Lobo
|
Wolf=Lobo
|
||||||
Baby Husk=Bebé Zombi Momificado
|
Husk=Husk
|
||||||
Baby Zombie=Bebé Zombi
|
Zombie=Zombie
|
||||||
Husk=Zombi Momificado
|
Zombie Pigman=Cerdo Zombie
|
||||||
Zombie=Zombi
|
Farmer=Granjero
|
||||||
Baby Zombie Pigman=Bebé Hombrecerdo Zombi
|
Fisherman=Pescador
|
||||||
Zombie Pigman=Hombrecerdo Zombi
|
Fletcher=Flechador
|
||||||
|
Shepherd=Sacerdote
|
||||||
|
Librarian=Bibliotecario
|
||||||
|
Cartographer=Cartógrafo
|
||||||
|
Armorer=Armero
|
||||||
|
Leatherworker=Peletero
|
||||||
|
Butcher=Carnicero
|
||||||
|
Weapon Smith=Herrero de Armas
|
||||||
|
Tool Smith=Herrero de Herramientas
|
||||||
|
Cleric=Sacerdote
|
||||||
|
Nitwit=Simple
|
||||||
|
|
|
@ -62,8 +62,3 @@ Weapon Smith=Fabriquant d'arme
|
||||||
Tool Smith=Fabriquant d'outil
|
Tool Smith=Fabriquant d'outil
|
||||||
Cleric=Clerc
|
Cleric=Clerc
|
||||||
Nitwit=Crétin
|
Nitwit=Crétin
|
||||||
Cod=Morue
|
|
||||||
Salmon=Saumon
|
|
||||||
Dolphin=Dauphin
|
|
||||||
Pillager=Pilleur
|
|
||||||
Tropical fish=Poisson tropical
|
|
|
@ -62,8 +62,3 @@ Weapon Smith=
|
||||||
Tool Smith=
|
Tool Smith=
|
||||||
Cleric=
|
Cleric=
|
||||||
Nitwit=
|
Nitwit=
|
||||||
Cod=
|
|
||||||
Salmon=
|
|
||||||
Dolphin=
|
|
||||||
Pillager=
|
|
||||||
Tropical fish=
|
|