Compare commits
16 Commits
master
...
mobs_head_
Author | SHA1 | Date |
---|---|---|
epCode | e5ff73af3a | |
epCode | d0d7facfd7 | |
epCode | 65b0908135 | |
epCode | 7d68c4faf3 | |
epCode | 7eee604074 | |
epCode | e5a090168f | |
epCode | 7e14870e38 | |
epCode | daa8a5c3ea | |
epCode | 2909de882a | |
epCode | 1d4046beea | |
epCode | cbb4c93e0c | |
epCode | 761cb8b366 | |
epCode | 9ece73a92f | |
epCode | b991bb5291 | |
epCode | 36ddec9812 | |
epCode | a2a06cc3ee |
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`
|
||||
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
|
||||
|
||||
### Mobs
|
||||
## Mobs
|
||||
* Mobs: `ENTITIES/mcl_mobs`
|
||||
|
||||
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.
|
||||
|
|
19
CREDITS.md
|
@ -27,11 +27,6 @@
|
|||
* Code-Sploit
|
||||
* NO11
|
||||
* kabou
|
||||
* rudzik8
|
||||
* chmodsayshello
|
||||
* PrarieWind
|
||||
* RandomLegoBrick
|
||||
* SumianVoice
|
||||
|
||||
## Contributors
|
||||
* Laurent Rocher
|
||||
|
@ -76,12 +71,6 @@
|
|||
* Sven792
|
||||
* aldum
|
||||
* Dieter44
|
||||
* Pepebotella
|
||||
* MrRar
|
||||
* Lazerbeak12345
|
||||
* mrminer
|
||||
* Thunder1035
|
||||
* opfromthestart
|
||||
|
||||
## MineClone5
|
||||
* kay27
|
||||
|
@ -89,12 +78,10 @@
|
|||
* epCode
|
||||
* NO11
|
||||
* j45
|
||||
* chmodsayshello
|
||||
* 3raven
|
||||
* PrarieWind
|
||||
* Gustavo1
|
||||
* CableGuy67
|
||||
* MrRar
|
||||
|
||||
## Mineclonia
|
||||
* erlehmann
|
||||
|
@ -147,9 +134,6 @@
|
|||
* yutyo
|
||||
* NO11
|
||||
* kay27
|
||||
* MysticTempest
|
||||
* RandomLegoBrick
|
||||
* cora
|
||||
|
||||
## Translations
|
||||
* Wuzzy
|
||||
|
@ -159,8 +143,6 @@
|
|||
* pitchum
|
||||
* todoporlalibertad
|
||||
* Marcin Serwin
|
||||
* Pepebotella
|
||||
* Emojigit
|
||||
|
||||
## Funders
|
||||
* 40W
|
||||
|
@ -168,6 +150,5 @@
|
|||
## Special thanks
|
||||
* celeron55 for creating Minetest
|
||||
* 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
|
||||
* 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.
|
||||
Developed by many people. Not developed or endorsed by Mojang AB.
|
||||
|
||||
Version: 0.79 (in development)
|
||||
Version: 0.75 (in development)
|
||||
|
||||
### Gameplay
|
||||
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
|
||||
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
||||
based on the Minetest engine with polished features, usable in both
|
||||
singleplayer and multiplayer. Currently, a lot of **Minecraft Java
|
||||
Edition** features are already implemented and polishing existing
|
||||
singleplayer and multiplayer. Currently, most of **Minecraft Java
|
||||
Edition 1.12.2** features are already implemented and polishing existing
|
||||
features are prioritized over new feature requests.
|
||||
- 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
|
||||
Minecraft experiences are prioritized over those that don't fulfill this
|
||||
scope.
|
||||
|
@ -108,7 +108,8 @@ playerbase on low spec computers, optimizations are hard to investigate.
|
|||
This game is currently in **beta** stage.
|
||||
It is playable, but not yet feature-complete.
|
||||
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:
|
||||
|
||||
|
@ -123,7 +124,7 @@ The following main features are available:
|
|||
* Most blocks in the overworld
|
||||
* Water and lava
|
||||
* Weather
|
||||
* 28 biomes + 5 Nether Biomes
|
||||
* 28 biomes
|
||||
* The Nether, a fiery underworld in another dimension
|
||||
* Redstone circuits (partially)
|
||||
* Minecarts (partial)
|
||||
|
@ -161,7 +162,7 @@ The following features are incomplete:
|
|||
* Special minecarts
|
||||
* 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
|
||||
* 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
|
||||
* Red Nether Brick Fence
|
||||
* 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:
|
||||
|
||||
|
|
|
@ -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
|
|
@ -161,9 +161,9 @@ minetest.register_on_dieplayer(function(player, mt_reason)
|
|||
if mt_reason.approved then
|
||||
mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason))
|
||||
end
|
||||
minetest.log("action","Player "..player:get_player_name().." died at "..minetest.pos_to_string(vector.round(player:get_pos())))
|
||||
end)
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -337,6 +337,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc
|
|||
if not obj:is_player() then
|
||||
return
|
||||
end
|
||||
|
||||
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
|
||||
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
|
|
|
@ -28,10 +28,11 @@ end)
|
|||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
if timer >= 0.6 then
|
||||
if timer >= 0.3 then
|
||||
for _, player in pairs(get_connected_players()) do
|
||||
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
|
||||
local node = get_node(npos)
|
||||
if node then
|
||||
|
|
|
@ -13,21 +13,11 @@ local function is_group(pos, group)
|
|||
end
|
||||
|
||||
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)
|
||||
return is_group(pos, "ice")
|
||||
end
|
||||
|
||||
local function is_fire(pos)
|
||||
return is_group(pos, "set_on_fire")
|
||||
end
|
||||
|
||||
local function get_sign(i)
|
||||
if i == 0 then
|
||||
return 0
|
||||
|
@ -206,8 +196,6 @@ end
|
|||
|
||||
function boat.on_step(self, dtime, moveresult)
|
||||
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)
|
||||
local v_factor = 1
|
||||
|
@ -216,21 +204,16 @@ function boat.on_step(self, dtime, moveresult)
|
|||
local on_water = true
|
||||
local on_ice = false
|
||||
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}
|
||||
if not is_water(waterp) then
|
||||
on_water = false
|
||||
if not in_water and is_ice(waterp) then
|
||||
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
|
||||
v_slowdown = 0.04
|
||||
v_factor = 0.5
|
||||
end
|
||||
elseif in_water and not in_river_water then
|
||||
elseif in_water then
|
||||
on_water = false
|
||||
in_water = true
|
||||
v_factor = 0.75
|
||||
|
@ -362,18 +345,7 @@ function boat.on_step(self, dtime, moveresult)
|
|||
else
|
||||
p.y = p.y + 1
|
||||
local is_obsidian_boat = self.object:get_luaentity()._itemstring == "mcl_boats:boat_obsidian"
|
||||
if is_river_water(p) 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
|
||||
if is_water(p) or is_obsidian_boat then
|
||||
-- Inside water: Slowly sink
|
||||
local y = self.object:get_velocity().y
|
||||
y = y - 0.01
|
||||
|
|
|
@ -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.
|
||||
Spruce Boat=Bateau en Sapin
|
||||
Water vehicle=Véhicule aquatique
|
||||
Sneak to dismount=Se baisser pour descendre
|
||||
Obsidian Boat=Bateau en Obsidienne
|
||||
Sneak to dismount=
|
|
@ -10,4 +10,3 @@ Rightclick on a water source to place the boat. Rightclick the boat to enter it.
|
|||
Spruce Boat=
|
||||
Water vehicle=
|
||||
Sneak to dismount=
|
||||
Obsidian Boat=
|
|
@ -1,4 +1,3 @@
|
|||
name = mcl_burning
|
||||
description = Burning Objects for MineClone2
|
||||
author = Fleckenstein
|
||||
depends = mcl_weather
|
|
@ -1,55 +1,66 @@
|
|||
-- Dripping Water Mod
|
||||
-- by kddekadenz
|
||||
-- License of code, textures & sounds: CC0
|
||||
|
||||
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"
|
||||
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
|
||||
-- License of code, textures & sounds: CC0
|
||||
|
||||
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({
|
||||
label = "Create drops",
|
||||
nodenames = nodes,
|
||||
neighbors = {"group:" .. liquid},
|
||||
interval = interval,
|
||||
chance = chance,
|
||||
interval = 2,
|
||||
chance = 22,
|
||||
action = function(pos)
|
||||
local r = math.ceil(interval / 20)
|
||||
local nn=minetest.find_nodes_in_area(vector.offset(pos,-r,0,-r),vector.offset(pos,r,0,r),nodes)
|
||||
--start a bunch of particle cycles to be able to get away
|
||||
--with longer abm cycles
|
||||
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
|
||||
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1, 0)).name, liquid) ~= 0
|
||||
and minetest.get_node(vector.offset(pos, 0, -1, 0)).name == "air" then
|
||||
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
|
||||
minetest.add_entity(vector.offset(pos, x, -0.520, z), "mcl_dripping:drop_" .. liquid)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
register_drop("water", 1, "", {"group:opaque", "group:leaves"},60,10)
|
||||
register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"},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"})
|
|
@ -59,8 +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:leather", "mcl:killCow")
|
||||
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")
|
||||
|
||||
local function check_pickup_achievements(object, player)
|
||||
if has_awards then
|
||||
|
@ -318,14 +316,18 @@ function minetest.handle_node_drops(pos, drops, digger)
|
|||
-- Spawn item and apply random speed
|
||||
local obj = minetest.add_item(dpos, drop_item)
|
||||
if obj then
|
||||
-- set the velocity multiplier to the stored amount or if the game dug this node, apply a bigger velocity
|
||||
local v = 1
|
||||
if digger and digger:is_player() then
|
||||
obj:get_luaentity().random_velocity = 1
|
||||
else
|
||||
obj:get_luaentity().random_velocity = 1.6
|
||||
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
|
||||
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()._insta_collect = false
|
||||
end
|
||||
end
|
||||
|
@ -404,33 +406,9 @@ minetest.register_entity(":__builtin:item", {
|
|||
-- Number of seconds this item entity has existed so far
|
||||
age = 0,
|
||||
|
||||
-- Multiplier for initial random velocity when the item is spawned
|
||||
random_velocity = 1,
|
||||
|
||||
-- How old it has become in the collection animation
|
||||
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)
|
||||
self.itemstring = itemstring
|
||||
if self.itemstring == "" then
|
||||
|
@ -483,9 +461,27 @@ minetest.register_entity(":__builtin:item", {
|
|||
glow = glow,
|
||||
}
|
||||
self.object:set_properties(prop)
|
||||
if item_drop_settings.random_item_velocity == true and self.age < 1 then
|
||||
minetest.after(0, self.apply_random_vel, self)
|
||||
if item_drop_settings.random_item_velocity == true then
|
||||
minetest.after(0, function(self)
|
||||
if not self or not self.object or not self.object:get_luaentity() then
|
||||
return
|
||||
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,
|
||||
|
||||
get_staticdata = function(self)
|
||||
|
@ -539,9 +535,9 @@ minetest.register_entity(":__builtin:item", {
|
|||
self.itemstring = data.itemstring
|
||||
self.always_collect = data.always_collect
|
||||
if data.age then
|
||||
self.age = data.age
|
||||
self.age = data.age + dtime_s
|
||||
else
|
||||
self.age = self.age
|
||||
self.age = dtime_s
|
||||
end
|
||||
--remember collection data
|
||||
-- If true, can collect item without delay
|
||||
|
@ -574,7 +570,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
self._forcetimer = 0
|
||||
|
||||
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:set_item(self.itemstring)
|
||||
end,
|
||||
|
@ -604,13 +600,12 @@ minetest.register_entity(":__builtin:item", {
|
|||
end
|
||||
-- Merge the remote stack into this one
|
||||
|
||||
-- local pos = object:get_pos()
|
||||
-- pos.y = pos.y + ((total_count - count) / max_count) * 0.15
|
||||
-- self.object:move_to(pos)
|
||||
local pos = object:get_pos()
|
||||
pos.y = pos.y + ((total_count - count) / max_count) * 0.15
|
||||
self.object:move_to(pos)
|
||||
|
||||
self.age = 0 -- Handle as new entity
|
||||
own_stack:set_count(total_count)
|
||||
self.random_velocity = 0
|
||||
self:set_item(own_stack:to_string())
|
||||
|
||||
entity._removed = true
|
||||
|
@ -649,53 +644,33 @@ minetest.register_entity(":__builtin:item", {
|
|||
local node = minetest.get_node_or_nil(p)
|
||||
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
|
||||
self.object:set_properties({
|
||||
textures = {"mcl_clock:clock_" .. (mcl_worlds.clock_works(p) and mcl_clock.old_time or mcl_clock.random_frame)}
|
||||
})
|
||||
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 self._magnet_active and (self._collector_timer == nil or (self._collector_timer > item_drop_settings.magnet_time)) then
|
||||
self._magnet_active = false
|
||||
enable_physics(self.object, self)
|
||||
return
|
||||
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
|
||||
|
||||
local nn = node.name
|
||||
local def = minetest.registered_nodes[nn]
|
||||
local lg = minetest.get_item_group(nn, "lava")
|
||||
local fg = minetest.get_item_group(nn, "fire")
|
||||
local dg = minetest.get_item_group(nn, "destroys_items")
|
||||
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.
|
||||
if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then
|
||||
if self.age > 2 then
|
||||
if dg ~= 2 then
|
||||
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
|
||||
end
|
||||
|
@ -718,7 +693,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
end
|
||||
|
||||
-- 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 cx = (p.x % 1) - 0.5
|
||||
local cz = (p.z % 1) - 0.5
|
||||
|
@ -759,8 +734,8 @@ minetest.register_entity(":__builtin:item", {
|
|||
local newv = vector.multiply(shootdir, 3)
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
self.object:set_velocity(newv)
|
||||
disable_physics(self.object, self, false, false)
|
||||
|
||||
disable_physics(self.object, self, false, false)
|
||||
|
||||
if shootdir.y == 0 then
|
||||
self._force = newv
|
||||
|
@ -799,8 +774,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
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.
|
||||
if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then
|
||||
self._flowing = true
|
||||
if def and def.liquidtype == "flowing" or def.liquidtype == "source" then
|
||||
|
||||
--[[ 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.
|
||||
|
@ -822,29 +796,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
})
|
||||
return
|
||||
end
|
||||
if is_in_water and def.liquidtype == "source" 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
|
||||
elseif self._flowing == true then
|
||||
-- Disable flowing physics if not on/in flowing liquid
|
||||
self._flowing = false
|
||||
enable_physics(self.object, self, true)
|
||||
|
@ -853,34 +805,28 @@ minetest.register_entity(":__builtin:item", {
|
|||
|
||||
-- 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 def = minetest.registered_nodes[nn]
|
||||
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]
|
||||
or is_floating or is_on_floor then
|
||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||
-- Merge with close entities of the same item
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
|
||||
local obj = object:get_luaentity()
|
||||
if obj and obj.name == "__builtin:item"
|
||||
and obj.physical_state == false then
|
||||
if self:try_merge_with(own_stack, object, obj) then
|
||||
return
|
||||
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and not minetest.registered_nodes[nn].groups.slippery and v.y == 0 then
|
||||
if self.physical_state then
|
||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||
-- Merge with close entities of the same item
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
|
||||
local obj = object:get_luaentity()
|
||||
if obj and obj.name == "__builtin:item"
|
||||
and obj.physical_state == false then
|
||||
if self:try_merge_with(own_stack, object, obj) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
-- don't disable if underwater
|
||||
if not is_in_water then
|
||||
disable_physics(self.object, self)
|
||||
end
|
||||
disable_physics(self.object, self)
|
||||
end
|
||||
else
|
||||
if self._magnet_active == false and not is_floating then
|
||||
if self._magnet_active == false then
|
||||
enable_physics(self.object, self)
|
||||
end
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
|
||||
|
|
|
@ -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é
|
||||
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é
|
||||
Sneak to dismount=Se baisser pour descendre
|
||||
Sneak to dismount=
|
|
@ -21,7 +21,7 @@ local function register_rail(itemstring, tiles, def_extras, creative)
|
|||
stack_max = 64,
|
||||
groups = groups,
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 0.7,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 0.7,
|
||||
after_destruct = function(pos)
|
||||
-- Scan for minecarts in this pos and force them to execute their "floating" check.
|
||||
|
|
|
@ -91,7 +91,7 @@ minetest.register_chatcommand("clearmobs",{
|
|||
if o.is_mob then
|
||||
if param == "all" or
|
||||
( param == "nametagged" and o.nametag ) or
|
||||
( param == "" and ( not o.nametag or o.nametag == "" ) and not o.tamed ) or
|
||||
( param == "" and not o.nametag and not o.tamed ) or
|
||||
( num and num > 0 and vector.distance(p:get_pos(),o.object:get_pos()) <= num ) then
|
||||
o.object:remove()
|
||||
end
|
||||
|
@ -125,6 +125,14 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement
|
|||
end
|
||||
|
||||
|
||||
local function dir_to_pitch(dir)
|
||||
--local dir2 = vector.normalize(dir)
|
||||
local xz = math.abs(dir.x) + math.abs(dir.z)
|
||||
return -math.atan2(-dir.y, xz)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- play sound
|
||||
local mob_sound = function(self, soundname, is_opinion, fixed_pitch)
|
||||
|
||||
|
@ -213,11 +221,11 @@ end
|
|||
local collision = function(self)
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return {0,0} end
|
||||
local vel = self.object:get_velocity()
|
||||
local x = 0
|
||||
local z = 0
|
||||
local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5
|
||||
|
||||
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
|
||||
|
||||
local ent = object:get_luaentity()
|
||||
|
@ -248,20 +256,18 @@ local set_velocity = function(self, v)
|
|||
end
|
||||
|
||||
-- halt mob if it has been ordered to stay
|
||||
if self.order == "stand" or self.order == "sit" then
|
||||
if self.order == "stand" then
|
||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
return
|
||||
end
|
||||
|
||||
local yaw = (self.object:get_yaw() or 0) + self.rotate
|
||||
local vv = self.object:get_velocity()
|
||||
if vv then
|
||||
self.object:set_velocity({
|
||||
x = (sin(yaw) * -v) + c_x,
|
||||
y = vv.y,
|
||||
z = (cos(yaw) * v) + c_y,
|
||||
})
|
||||
end
|
||||
|
||||
self.object:set_velocity({
|
||||
x = (sin(yaw) * -v) + c_x,
|
||||
y = self.object:get_velocity().y,
|
||||
z = (cos(yaw) * v) + c_y,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
|
@ -300,13 +306,9 @@ local function update_roll(self)
|
|||
|
||||
if is_Fleckenstein then
|
||||
cbox[2], cbox[5] = -cbox[5], -cbox[2]
|
||||
self.object:set_properties({collisionbox = cbox})
|
||||
-- This leads to child mobs having the wrong collisionbox
|
||||
-- and seeing as it seems to be nothing but an easter egg
|
||||
-- i've put it inside the if. Which just makes it be upside
|
||||
-- down lol.
|
||||
end
|
||||
|
||||
self.object:set_properties({collisionbox = cbox})
|
||||
end
|
||||
|
||||
-- set and return valid yaw
|
||||
|
@ -409,15 +411,15 @@ local set_animation = function(self, anim, fixed_frame)
|
|||
|
||||
if flight_check(self) and self.fly and anim == "walk" then anim = "fly" end
|
||||
|
||||
self._current_animation = self._current_animation or ""
|
||||
self.animation.current = self.animation.current or ""
|
||||
|
||||
if (anim == self._current_animation
|
||||
if (anim == self.animation.current
|
||||
or not self.animation[anim .. "_start"]
|
||||
or not self.animation[anim .. "_end"]) and self.state ~= "die" then
|
||||
return
|
||||
end
|
||||
|
||||
self._current_animation = anim
|
||||
self.animation.current = anim
|
||||
|
||||
local a_start = self.animation[anim .. "_start"]
|
||||
local a_end
|
||||
|
@ -1907,11 +1909,13 @@ local specific_attack = function(list, what)
|
|||
return false
|
||||
end
|
||||
|
||||
-- find someone to attack
|
||||
-- monster find someone to attack
|
||||
local monster_attack = function(self)
|
||||
if not damage_enabled
|
||||
|
||||
if self.type ~= "monster"
|
||||
or not damage_enabled
|
||||
or minetest.is_creative_enabled("")
|
||||
or self.passive ~= false
|
||||
or self.passive
|
||||
or self.state == "attack"
|
||||
or day_docile(self) then
|
||||
return
|
||||
|
@ -1927,9 +1931,10 @@ local monster_attack = function(self)
|
|||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
|
||||
if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then
|
||||
type = ""
|
||||
elseif (self.type == "monster" or self._aggro) then
|
||||
else
|
||||
player = objs[n]
|
||||
type = "player"
|
||||
name = "player"
|
||||
|
@ -2286,9 +2291,6 @@ end
|
|||
local function go_to_pos(entity,b)
|
||||
if not entity then return end
|
||||
local s=entity.object:get_pos()
|
||||
if not b then
|
||||
--self.state = "stand"
|
||||
return end
|
||||
if vector.distance(b,s) < 1 then
|
||||
--set_velocity(entity,0)
|
||||
return true
|
||||
|
@ -2311,52 +2313,15 @@ local function check_doors(self)
|
|||
local def = minetest.registered_nodes[n.name]
|
||||
local closed = n.name:find("_b_1")
|
||||
if t < 0.3 or t > 0.8 then
|
||||
if not closed and def.on_rightclick then def.on_rightclick(d,n,self) end
|
||||
if not closed then def.on_rightclick(d,n,self) end
|
||||
else
|
||||
if closed and def.on_rightclick then def.on_rightclick(d,n,self) end
|
||||
if closed then def.on_rightclick(d,n,self) end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local gowp_etime = 0
|
||||
|
||||
local function check_gowp(self,dtime)
|
||||
gowp_etime = gowp_etime + dtime
|
||||
if gowp_etime < 0.2 then return end
|
||||
gowp_etime = 0
|
||||
local p = self.object:get_pos()
|
||||
if not p or not self._target then return end
|
||||
if vector.distance(p,self._target) < 1 then
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self.current_target = nil
|
||||
self.state = "stand"
|
||||
if self.callback_arrived then return self.callback_arrived(self) end
|
||||
return true
|
||||
end
|
||||
if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 2 ) then
|
||||
self.current_target = table.remove(self.waypoints, 1)
|
||||
--minetest.log("nextwp:".. tostring(self.current_target) )
|
||||
go_to_pos(self,self.current_target)
|
||||
return
|
||||
elseif self.current_target then
|
||||
go_to_pos(self,self.current_target)
|
||||
end
|
||||
|
||||
if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then
|
||||
self.waypoints=minetest.find_path(p,self._target,150,1,4)
|
||||
if not self.waypoints then self.state = "walk" end --give up
|
||||
self.current_target = nil
|
||||
return
|
||||
end
|
||||
if not self.current_target then
|
||||
--minetest.log("no path")
|
||||
self.state = "walk"
|
||||
end
|
||||
end
|
||||
|
||||
-- execute current state (stand, walk, run, attacks)
|
||||
-- returns true if mob has died
|
||||
local do_states = function(self, dtime)
|
||||
|
@ -2369,8 +2334,9 @@ local do_states = function(self, dtime)
|
|||
|
||||
local s = self.object:get_pos()
|
||||
local objs = minetest.get_objects_inside_radius(s, 3)
|
||||
local lp
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
lp = objs[n]:get_pos()
|
||||
break
|
||||
|
@ -2378,7 +2344,7 @@ local do_states = function(self, dtime)
|
|||
end
|
||||
|
||||
-- look at any players nearby, otherwise turn randomly
|
||||
if lp and self.look_at_players then
|
||||
if self.look_at_players then
|
||||
|
||||
local vec = {
|
||||
x = lp.x - s.x,
|
||||
|
@ -2394,13 +2360,9 @@ local do_states = function(self, dtime)
|
|||
|
||||
yaw = set_yaw(self, yaw, 8)
|
||||
end
|
||||
if self.order == "sit" then
|
||||
set_animation(self, "sit")
|
||||
set_velocity(self, 0)
|
||||
else
|
||||
set_animation(self, "stand")
|
||||
set_velocity(self, 0)
|
||||
end
|
||||
|
||||
set_velocity(self, 0)
|
||||
set_animation(self, "stand")
|
||||
|
||||
-- npc's ordered to stand stay standing
|
||||
if self.type ~= "npc"
|
||||
|
@ -2418,7 +2380,32 @@ local do_states = function(self, dtime)
|
|||
end
|
||||
|
||||
elseif self.state == "gowp" then
|
||||
check_gowp(self,dtime)
|
||||
local p = self.object:get_pos()
|
||||
if not p or not self._target then return end
|
||||
if vector.distance(p,self._target) < 2 or ( self.waypoints and #self.waypoints == 0 ) then
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self.current_target = nil
|
||||
self.state = "walk"
|
||||
if self.callback_arrived then return self.callback_arrived(self) end
|
||||
return true
|
||||
end
|
||||
if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 1.5 ) then
|
||||
self.current_target = table.remove(self.waypoints, 1)
|
||||
--minetest.log("nextwp:".. tostring(self.current_target) )
|
||||
elseif self.current_target then
|
||||
go_to_pos(self,self.current_target)
|
||||
end
|
||||
|
||||
if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then
|
||||
self.waypoints=minetest.find_path(p,self._target,150,1,4)
|
||||
self.current_target = nil
|
||||
return
|
||||
end
|
||||
if not self.current_target then
|
||||
--minetest.log("no path")
|
||||
self.state = "walk"
|
||||
end
|
||||
|
||||
elseif self.state == "walk" then
|
||||
local s = self.object:get_pos()
|
||||
|
@ -2929,12 +2916,7 @@ local plane_adjacents = {
|
|||
vector.new(0,0,-1),
|
||||
}
|
||||
|
||||
|
||||
local gopath_last = os.time()
|
||||
function mcl_mobs:gopath(self,target,callback_arrived)
|
||||
if os.time() - gopath_last < 15 then return end
|
||||
gopath_last = os.time()
|
||||
--minetest.log("gowp")
|
||||
local p = self.object:get_pos()
|
||||
local t = vector.offset(target,0,1,0)
|
||||
local wp = minetest.find_path(p,t,150,1,4)
|
||||
|
@ -2954,15 +2936,11 @@ function mcl_mobs:gopath(self,target,callback_arrived)
|
|||
if wp and #wp > 0 then
|
||||
self._target = t
|
||||
self.callback_arrived = callback_arrived
|
||||
table.remove(wp,1)
|
||||
self.waypoints = wp
|
||||
self.state = "gowp"
|
||||
return true
|
||||
else
|
||||
self.state = "walk"
|
||||
self.waypoints = nil
|
||||
self.current_target = nil
|
||||
-- minetest.log("no path found")
|
||||
--minetest.log("no path found")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2994,7 +2972,7 @@ local function damage_mob(self,reason,damage)
|
|||
if damage > 0 then
|
||||
self.health = self.health - damage
|
||||
|
||||
effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil)
|
||||
effect(pos, 5, "mcl_particles_smoke.png", 1, 2, 2, nil)
|
||||
|
||||
if check_for_death(self, reason, {type = reason}) then
|
||||
return true
|
||||
|
@ -3004,7 +2982,6 @@ end
|
|||
|
||||
local function check_entity_cramming(self)
|
||||
local p = self.object:get_pos()
|
||||
if not p then return end
|
||||
local oo = minetest.get_objects_inside_radius(p,1)
|
||||
local mobs = {}
|
||||
for _,o in pairs(oo) do
|
||||
|
@ -3350,11 +3327,11 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
and (self.child == false or self.type == "monster")
|
||||
and hitter:get_player_name() ~= self.owner
|
||||
and not mcl_mobs.invis[ name ] then
|
||||
|
||||
if not die then
|
||||
-- attack whoever punched mob
|
||||
self.state = ""
|
||||
do_attack(self, hitter)
|
||||
self._aggro= true
|
||||
end
|
||||
|
||||
-- alert others to the attack
|
||||
|
@ -3366,6 +3343,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
obj = objs[n]:get_luaentity()
|
||||
|
||||
if obj then
|
||||
|
||||
-- only alert members of same mob or friends
|
||||
if obj.group_attack
|
||||
and obj.state ~= "attack"
|
||||
|
@ -3375,7 +3353,6 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
elseif type(obj.group_attack) == "table" then
|
||||
for i=1, #obj.group_attack do
|
||||
if obj.name == obj.group_attack[i] then
|
||||
obj._aggro = true
|
||||
do_attack(obj, hitter)
|
||||
break
|
||||
end
|
||||
|
@ -3470,10 +3447,7 @@ local mob_activate = function(self, staticdata, def, dtime)
|
|||
def.textures = {def.textures}
|
||||
end
|
||||
|
||||
local c = 1
|
||||
if #def.textures > c then c = #def.textures end
|
||||
|
||||
self.base_texture = def.textures[math.random(c)]
|
||||
self.base_texture = def.textures[random(1, #def.textures)]
|
||||
self.base_mesh = def.mesh
|
||||
self.base_size = self.visual_size
|
||||
self.base_colbox = self.collisionbox
|
||||
|
@ -3605,27 +3579,12 @@ local mob_activate = function(self, staticdata, def, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
local function check_aggro(self,dtime)
|
||||
if not self._aggro or not self.attack then return end
|
||||
if not self._check_aggro_timer or self._check_aggro_timer > 5 then
|
||||
self._check_aggro_timer = 0
|
||||
if not self.attack:get_pos() or vector.distance(self.attack:get_pos(),self.object:get_pos()) > 128 then
|
||||
self._aggro = nil
|
||||
self.attack = nil
|
||||
self.state = "stand"
|
||||
end
|
||||
end
|
||||
self._check_aggro_timer = self._check_aggro_timer + dtime
|
||||
end
|
||||
|
||||
-- main mob function
|
||||
local mob_step = function(self, dtime)
|
||||
check_item_pickup(self)
|
||||
check_aggro(self,dtime)
|
||||
if not self.fire_resistant then
|
||||
mcl_burning.tick(self.object, dtime, self)
|
||||
-- mcl_burning.tick may remove object immediately
|
||||
if not self.object:get_pos() then return end
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
|
@ -3694,6 +3653,60 @@ local mob_step = function(self, dtime)
|
|||
|
||||
-- end rotation
|
||||
|
||||
if self.head_swivel and type(self.head_swivel) == "string" then
|
||||
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
|
||||
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 10)) do
|
||||
if obj:is_player() and not self.attack then
|
||||
if not self._locked_object then
|
||||
if math.random(50/self.curiosity) == 1 then
|
||||
self._locked_object = obj
|
||||
end
|
||||
else
|
||||
if math.random(200*self.curiosity) == 1 then
|
||||
self._locked_object = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.attack then
|
||||
self._locked_object = self.attack
|
||||
end
|
||||
|
||||
if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then
|
||||
local _locked_object_eye_height = 1.5
|
||||
if self._locked_object:is_player() then
|
||||
_locked_object_eye_height = self._locked_object:get_properties().eye_height
|
||||
end
|
||||
local self_rot = self.object:get_rotation()
|
||||
local player_pos = self._locked_object:get_pos()
|
||||
local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0)))
|
||||
local mob_yaw = math.deg(-(-(self_rot.y)-(-minetest.dir_to_yaw(direction_player))))--+self.head_yaw_offset
|
||||
local mob_pitch = math.deg(-dir_to_pitch(direction_player))
|
||||
if (mob_yaw < -60 or mob_yaw > 60) and not (self.attack and self.type == "monster") then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.multiply(oldr, 0.9))
|
||||
elseif self.attack and self.type == "monster" then
|
||||
if self.head_yaw == "y" then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.new(mob_pitch, mob_yaw, 0))
|
||||
elseif self.head_yaw == "z" then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.new(mob_pitch, 0, -mob_yaw))
|
||||
end
|
||||
else
|
||||
if self.head_yaw == "y" then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, ((mob_yaw-oldr.y)*.3)+oldr.y, 0))
|
||||
elseif self.head_yaw == "z" then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, 0, -(((mob_yaw-oldr.y)*.3)+oldr.y)*3))
|
||||
end
|
||||
end
|
||||
elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.multiply(oldr, 0.9))
|
||||
else
|
||||
self.object:set_bone_position(self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), vector.new(0,0,0))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- run custom function (defined in mob lua file)
|
||||
if self.do_custom then
|
||||
|
||||
|
@ -3933,6 +3946,13 @@ end
|
|||
minetest.register_entity(name, {
|
||||
|
||||
use_texture_alpha = def.use_texture_alpha,
|
||||
head_swivel = def.head_swivel or nil, -- name of head bone
|
||||
head_yaw_offset = def.head_yaw_offset or 0, -- name of head bone
|
||||
bone_eye_height = def.bone_eye_height or 1.4, -- mob eye height
|
||||
head_eye_height = def.head_eye_height or def.bone_eye_height or 0, -- factor for staqring at players
|
||||
curiosity = def.curiosity or 1, -- factor for staqring at players
|
||||
head_yaw = def.head_yaw or "y", -- factor for staqring at players
|
||||
horrizonatal_head_height = def.horrizonatal_head_height or 0, -- factor for staqring at players
|
||||
stepheight = def.stepheight or 0.6,
|
||||
name = name,
|
||||
description = def.description,
|
||||
|
@ -3954,7 +3974,7 @@ minetest.register_entity(name, {
|
|||
xp_max = def.xp_max or 0,
|
||||
xp_timestamp = 0,
|
||||
breath_max = def.breath_max or 15,
|
||||
breathes_in_water = def.breathes_in_water or false,
|
||||
breathes_in_water = def.breathes_in_water or false,
|
||||
physical = true,
|
||||
collisionbox = collisionbox,
|
||||
selectionbox = def.selectionbox or def.collisionbox,
|
||||
|
@ -4042,7 +4062,6 @@ minetest.register_entity(name, {
|
|||
teleport = teleport,
|
||||
do_teleport = def.do_teleport,
|
||||
spawn_class = def.spawn_class,
|
||||
can_spawn = def.can_spawn,
|
||||
ignores_nametag = def.ignores_nametag or false,
|
||||
rain_damage = def.rain_damage or 0,
|
||||
glow = def.glow,
|
||||
|
@ -4059,8 +4078,6 @@ minetest.register_entity(name, {
|
|||
fire_resistant = def.fire_resistant or false,
|
||||
fire_damage_resistant = def.fire_damage_resistant or false,
|
||||
ignited_by_sunlight = def.ignited_by_sunlight or false,
|
||||
spawn_in_group = def.spawn_in_group,
|
||||
spawn_in_group_min = def.spawn_in_group_min,
|
||||
-- End of MCL2 extensions
|
||||
|
||||
on_spawn = def.on_spawn,
|
||||
|
@ -4386,73 +4403,77 @@ end
|
|||
|
||||
|
||||
-- feeding, taming and breeding (thanks blert2112)
|
||||
function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame, notake)
|
||||
function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame)
|
||||
if not self.follow then
|
||||
return false
|
||||
end
|
||||
|
||||
-- can eat/tame with item in hand
|
||||
if self.nofollow or follow_holding(self, clicker) then
|
||||
local consume_food = false
|
||||
|
||||
-- tame if not still a baby
|
||||
-- if not in creative then take item
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
|
||||
if tame and not self.child then
|
||||
if not self.owner or self.owner == "" then
|
||||
self.tamed = true
|
||||
self.owner = clicker:get_player_name()
|
||||
consume_food = true
|
||||
end
|
||||
local item = clicker:get_wielded_item()
|
||||
|
||||
item:take_item()
|
||||
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
|
||||
-- increase health
|
||||
mob_sound(self, "eat", nil, true)
|
||||
|
||||
if self.health < self.hp_max and not consume_food then
|
||||
consume_food = true
|
||||
self.health = min(self.health + 4, self.hp_max)
|
||||
-- increase health
|
||||
self.health = self.health + 4
|
||||
|
||||
if self.health >= self.hp_max then
|
||||
|
||||
self.health = self.hp_max
|
||||
|
||||
if self.htimer < 1 then
|
||||
self.htimer = 5
|
||||
end
|
||||
self.object:set_hp(self.health)
|
||||
end
|
||||
|
||||
-- make children grow quicker
|
||||
|
||||
if not consume_food and self.child == true then
|
||||
consume_food = true
|
||||
-- deduct 10% of the time to adulthood
|
||||
self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1)
|
||||
end
|
||||
|
||||
-- breed animals
|
||||
|
||||
if breed and not consume_food and self.hornytimer == 0 and not self.horny then
|
||||
self.food = (self.food or 0) + 1
|
||||
consume_food = true
|
||||
if self.food >= feed_count then
|
||||
self.food = 0
|
||||
self.horny = true
|
||||
end
|
||||
end
|
||||
self.object:set_hp(self.health)
|
||||
|
||||
update_tag(self)
|
||||
-- play a sound if the animal used the item and take the item if not in creative
|
||||
if consume_food then
|
||||
-- don't consume food if clicker is in creative
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) and not notake then
|
||||
local item = clicker:get_wielded_item()
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
-- always play the eat sound if food is used, even in creative
|
||||
mob_sound(self, "eat", nil, true)
|
||||
|
||||
else
|
||||
-- make sound when the mob doesn't want food
|
||||
-- make children grow quicker
|
||||
if self.child == true then
|
||||
|
||||
-- deduct 10% of the time to adulthood
|
||||
self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- feed and tame
|
||||
self.food = (self.food or 0) + 1
|
||||
if self.food >= feed_count then
|
||||
|
||||
self.food = 0
|
||||
|
||||
if breed and self.hornytimer == 0 then
|
||||
self.horny = true
|
||||
end
|
||||
|
||||
if tame then
|
||||
|
||||
self.tamed = true
|
||||
|
||||
if not self.owner or self.owner == "" then
|
||||
self.owner = clicker:get_player_name()
|
||||
end
|
||||
end
|
||||
|
||||
-- make sound when fed so many times
|
||||
mob_sound(self, "random", true)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -4502,6 +4523,31 @@ function mcl_mobs:spawn_child(pos, mob_type)
|
|||
return child
|
||||
end
|
||||
|
||||
|
||||
-- compatibility function for old entities to new modpack entities
|
||||
function mcl_mobs:alias_mob(old_name, new_name)
|
||||
|
||||
-- spawn egg
|
||||
minetest.register_alias(old_name, new_name)
|
||||
|
||||
-- entity
|
||||
minetest.register_entity(":" .. old_name, {
|
||||
|
||||
physical = false,
|
||||
|
||||
on_step = function(self)
|
||||
|
||||
if minetest.registered_entities[new_name] then
|
||||
minetest.add_entity(self.object:get_pos(), new_name)
|
||||
end
|
||||
|
||||
self.object:remove()
|
||||
end
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
|
|
|
@ -15,7 +15,7 @@ local math_cos = math.cos
|
|||
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 vector_distance = vector.distance
|
||||
--local vector_distance = vector.distance
|
||||
local vector_new = vector.new
|
||||
local vector_floor = vector.floor
|
||||
|
||||
|
@ -23,18 +23,9 @@ local table_copy = table.copy
|
|||
local table_remove = table.remove
|
||||
|
||||
local pairs = pairs
|
||||
local dbg_spawn_attempts = 0
|
||||
local dbg_spawn_succ = 0
|
||||
-- range for mob count
|
||||
local aoc_range = 136
|
||||
|
||||
local mob_cap = {
|
||||
monster = 70,
|
||||
animal =10,
|
||||
ambient =15,
|
||||
water = 5, --currently unused
|
||||
water_ambient = 20, --currently unused
|
||||
}
|
||||
-- range for mob count
|
||||
local aoc_range = 32
|
||||
|
||||
--do mobs spawn?
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
|
@ -72,7 +63,6 @@ local list_of_all_biomes = {
|
|||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"MangroveSwamp_underground",
|
||||
|
||||
-- ocean:
|
||||
|
||||
|
@ -136,8 +126,6 @@ local list_of_all_biomes = {
|
|||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"MangroveSwamp_ocean",
|
||||
"MangroveSwamp_deep_ocean",
|
||||
|
||||
-- water or beach?
|
||||
|
||||
|
@ -161,15 +149,10 @@ local list_of_all_biomes = {
|
|||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MangroveSwamp_shore",
|
||||
|
||||
-- dimension biome:
|
||||
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"CrimsonForest",
|
||||
"WarpedForest",
|
||||
"SoulsandValley",
|
||||
"End",
|
||||
|
||||
-- Overworld regular:
|
||||
|
@ -179,8 +162,6 @@ local list_of_all_biomes = {
|
|||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+_snowtop",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
|
@ -199,6 +180,7 @@ local list_of_all_biomes = {
|
|||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
|
@ -207,30 +189,14 @@ local list_of_all_biomes = {
|
|||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"MangroveSwamp",
|
||||
}
|
||||
|
||||
-- count how many mobs are in an area
|
||||
local function count_mobs(pos,r,mob_type)
|
||||
local function count_mobs(pos)
|
||||
local num = 0
|
||||
for _,l in pairs(minetest.luaentities) do
|
||||
if l and l.is_mob and (mob_type == nil or l.type == mob_type) then
|
||||
local p = l.object:get_pos()
|
||||
if p and vector_distance(p,pos) < r then
|
||||
num = num + 1
|
||||
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
|
||||
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do
|
||||
if object and object:get_luaentity() and object:get_luaentity().is_mob then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
return num
|
||||
|
@ -323,7 +289,7 @@ function mcl_mobs:spawn_setup(def)
|
|||
spawn_dictionary[#spawn_dictionary + 1] = {
|
||||
name = name,
|
||||
dimension = dimension,
|
||||
type_of_spawning = type_of_spawning,
|
||||
type_of_spawning = type_of_spawning,
|
||||
biomes = biomes,
|
||||
min_light = min_light,
|
||||
max_light = max_light,
|
||||
|
@ -410,94 +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"
|
||||
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 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.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 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
|
||||
|
||||
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 = minetest.add_entity(sp,mob.name)
|
||||
if o then dbg_spawn_succ = dbg_spawn_succ + 1 end
|
||||
end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
if mobs_spawn then
|
||||
|
||||
local perlin_noise
|
||||
|
||||
local function spawn_a_mob(pos, dimension, y_min, y_max)
|
||||
--create a disconnected clone of the spawn dictionary
|
||||
--prevents memory leak
|
||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||
local dimension = dimension or mcl_worlds.pos_to_dimension(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(
|
||||
{x = goal_pos.x, y = y_min, z = goal_pos.z},
|
||||
{x = goal_pos.x, y = y_max, z = goal_pos.z},
|
||||
|
@ -506,10 +391,41 @@ if mobs_spawn then
|
|||
if #spawning_position_list <= 0 then return end
|
||||
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)
|
||||
local noise = perlin_noise:get_3d(spawning_position)
|
||||
local current_summary_chance = summary_chance
|
||||
table.shuffle(mob_library_worker_table)
|
||||
while #mob_library_worker_table > 0 do
|
||||
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||
local mob_index = 1
|
||||
|
@ -521,30 +437,23 @@ if mobs_spawn then
|
|||
step_chance = step_chance + mob_chance
|
||||
end
|
||||
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
|
||||
if spawn_check(spawning_position,mob_def) then
|
||||
if mob_def.type_of_spawning == "water" then
|
||||
spawning_position = get_water_spawn(spawning_position)
|
||||
if not spawning_position then
|
||||
return
|
||||
end
|
||||
end
|
||||
if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(pos) then
|
||||
return
|
||||
end
|
||||
if mob_def
|
||||
and spawning_position.y >= mob_def.min_height
|
||||
and spawning_position.y <= mob_def.max_height
|
||||
and mob_def.dimension == dimension
|
||||
and biome_check(mob_def.biomes, gotten_biome)
|
||||
and gotten_light >= mob_def.min_light
|
||||
and gotten_light <= mob_def.max_light
|
||||
and (is_ground or mob_def.type_of_spawning ~= "ground")
|
||||
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
|
||||
and (not is_farm_animal(mob_def.name) or is_grass)
|
||||
and (mob_type ~= "npc" or has_bed)
|
||||
then
|
||||
--everything is correct, spawn mob
|
||||
local object
|
||||
if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then
|
||||
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
|
||||
object = minetest.add_entity(spawning_position, mob_def.name)
|
||||
end
|
||||
|
||||
|
||||
local object = minetest.add_entity(spawning_position, mob_def.name)
|
||||
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
|
||||
current_summary_chance = current_summary_chance - mob_chance
|
||||
|
@ -573,14 +482,3 @@ if mobs_spawn then
|
|||
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
|
||||
remove_schem(p, schem)
|
||||
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
|
||||
|
@ -52,9 +46,6 @@ end
|
|||
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
|
||||
local old_on_place = wither_head.on_place
|
||||
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)
|
||||
end
|
||||
return old_on_place(itemstack, placer, pointed)
|
||||
minetest.after(0, wither_spawn, pointed.above)
|
||||
old_on_place(itemstack, placer, pointed)
|
||||
end
|
||||
|
|
|
@ -7,7 +7,6 @@ mcl_mobs:register_mob("mobs_mc:bat", {
|
|||
type = "animal",
|
||||
spawn_class = "ambient",
|
||||
can_despawn = true,
|
||||
spawn_in_group = 8,
|
||||
passive = true,
|
||||
hp_min = 6,
|
||||
hp_max = 6,
|
||||
|
|
|
@ -16,8 +16,6 @@ mcl_mobs:register_mob("mobs_mc:blaze", {
|
|||
description = S("Blaze"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 3,
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 10,
|
||||
|
|
|
@ -25,6 +25,13 @@ mcl_mobs:register_mob("mobs_mc:chicken", {
|
|||
textures = {
|
||||
{"mobs_mc_chicken.png"},
|
||||
},
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 1.8,
|
||||
head_eye_height = 1.5,
|
||||
curiosity = 10,
|
||||
head_yaw="z",
|
||||
-------------------------------
|
||||
visual_size = {x=2.2, y=2.2},
|
||||
|
||||
makes_footstep_sound = true,
|
||||
|
@ -74,7 +81,7 @@ mcl_mobs:register_mob("mobs_mc:chicken", {
|
|||
fear_height = 4,
|
||||
|
||||
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:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
|
||||
end,
|
||||
|
@ -122,6 +129,8 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
|
|
|
@ -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"), "extra_mobs_spawn_icon_cod.png", 0)
|
|
@ -17,6 +17,14 @@ local cow_def = {
|
|||
"mobs_mc_cow.png",
|
||||
"blank.png",
|
||||
}, },
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 3.4,
|
||||
head_eye_height = 1.1,
|
||||
horrizonatal_head_height=-.7,
|
||||
curiosity = 2,
|
||||
head_yaw="z",
|
||||
-------------------------------
|
||||
visual_size = {x=2.8, y=2.8},
|
||||
makes_footstep_sound = true,
|
||||
walk_velocity = 1,
|
||||
|
@ -48,7 +56,7 @@ local cow_def = {
|
|||
run_end = 40,
|
||||
},
|
||||
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 self.child then
|
||||
|
@ -83,11 +91,9 @@ mcl_mobs:register_mob("mobs_mc:cow", cow_def)
|
|||
local mooshroom_def = table.copy(cow_def)
|
||||
mooshroom_def.description = S("Mooshroom")
|
||||
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
||||
mooshroom_def.spawn_in_group_min = 4
|
||||
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.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 self.child then
|
||||
|
@ -153,12 +159,17 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
|
|
|
@ -12,7 +12,6 @@ local S = minetest.get_translator("mobs_mc")
|
|||
mcl_mobs:register_mob("mobs_mc:creeper", {
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group = 1,
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 5,
|
||||
|
@ -25,6 +24,11 @@ mcl_mobs:register_mob("mobs_mc:creeper", {
|
|||
{"mobs_mc_creeper.png",
|
||||
"mobs_mc_empty.png"},
|
||||
},
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 2.35,
|
||||
curiosity = 2,
|
||||
-------------------------------
|
||||
visual_size = {x=3, y=3},
|
||||
sounds = {
|
||||
attack = "tnt_ignite",
|
||||
|
@ -275,6 +279,7 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -301,6 +306,7 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -339,6 +345,7 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -348,6 +355,7 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -373,6 +381,7 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
|
|
@ -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"), "extra_mobs_spawn_icon_dolphin.png", 0)
|
|
@ -219,7 +219,6 @@ local select_enderman_animation = function(animation_type)
|
|||
end
|
||||
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
local spawners = {}
|
||||
|
||||
mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||
description = S("Enderman"),
|
||||
|
@ -258,48 +257,23 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
|||
},
|
||||
animation = select_enderman_animation("normal"),
|
||||
_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)
|
||||
-- PARTICLE BEHAVIOUR HERE.
|
||||
local enderpos = self.object:get_pos()
|
||||
if self._particle_timer and self._particle_timer >= 1 then
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
if not spawners[player] then spawners[player] = {} end
|
||||
local dst = vector.distance(player:get_pos(),enderpos)
|
||||
if dst < 128 and not spawners[player][self.object] then
|
||||
self._particle_timer = 0
|
||||
spawners[player][self.object] = minetest.add_particlespawner({
|
||||
amount = 5,
|
||||
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,
|
||||
vertical = false,
|
||||
time = 0,
|
||||
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
|
||||
elseif not self._particle_timer then
|
||||
self._particle_timer = 0
|
||||
local chanceOfParticle = math.random(0, 1)
|
||||
if chanceOfParticle == 1 then
|
||||
minetest.add_particle({
|
||||
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},
|
||||
velocity = {x=math.random(-.25,.25), y=math.random(-.25,.25), z=math.random(-.25,.25)},
|
||||
acceleration = {x=math.random(-.5,.5), y=math.random(-.5,.5), z=math.random(-.5,.5)},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_portals_particle"..math.random(1, 5)..".png",
|
||||
})
|
||||
end
|
||||
self._particle_timer = self._particle_timer + dtime
|
||||
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
|
||||
enderpos = self.object:get_pos()
|
||||
local dim = mcl_worlds.pos_to_dimension(enderpos)
|
||||
if dim == "overworld" then
|
||||
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
|
||||
|
@ -335,24 +309,24 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
|||
else return end
|
||||
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
|
||||
if self.state == "attack" then
|
||||
if self.attack then
|
||||
local target = self.attack
|
||||
local pos = target:get_pos()
|
||||
if pos ~= nil then
|
||||
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
|
||||
self:teleport(target)
|
||||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
--self:teleport(nil)
|
||||
--self.state = ""
|
||||
--else
|
||||
if self.attack then
|
||||
local target = self.attack
|
||||
local pos = target:get_pos()
|
||||
if pos ~= nil then
|
||||
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
|
||||
self:teleport(target)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else --if not attacking try to tp to the dark
|
||||
if minetest.get_node_light(enderpos) > minetest.LIGHT_MAX then
|
||||
self:teleport(nil)
|
||||
end
|
||||
--end
|
||||
end
|
||||
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
||||
-- Check for arrows and people nearby.
|
||||
|
||||
enderpos = self.object:get_pos()
|
||||
local enderpos = self.object:get_pos()
|
||||
enderpos.y = enderpos.y + 1.5
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 2)
|
||||
for n = 1, #objs do
|
||||
|
@ -616,13 +590,6 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
|||
attack_type = "dogfight",
|
||||
})
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
for _,s in pairs(spawners[player]) do
|
||||
minetest.delete_particlespawner(s)
|
||||
end
|
||||
spawners[player] = nil
|
||||
end)
|
||||
|
||||
|
||||
-- End spawn
|
||||
mcl_mobs:spawn_specific(
|
||||
|
@ -660,6 +627,7 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -686,6 +654,7 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -724,6 +693,7 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -733,6 +703,7 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -758,6 +729,7 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -794,32 +766,15 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"SoulsandVall3ey",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
11,
|
||||
7,
|
||||
30,
|
||||
27500,
|
||||
4,
|
||||
mcl_vars.mg_nether_min,
|
||||
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
|
||||
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)
|
||||
|
|
|
@ -23,7 +23,6 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
|
|||
collisionbox = {-2, 5, -2, 2, 9, 2},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_ghast.b3d",
|
||||
spawn_in_group = 1,
|
||||
textures = {
|
||||
{"mobs_mc_ghast.png"},
|
||||
},
|
||||
|
@ -65,14 +64,6 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
|
|||
makes_footstep_sound = false,
|
||||
instant_death = 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)
|
||||
if self.firing == true then
|
||||
self.base_texture = {"mobs_mc_ghast_firing.png"}
|
||||
|
@ -90,14 +81,12 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"SoulsandValley",
|
||||
"BasaltDelta",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
72000,
|
||||
18000,
|
||||
2,
|
||||
mcl_vars.mg_nether_min,
|
||||
mcl_vars.mg_nether_max)
|
||||
|
@ -116,12 +105,7 @@ mcl_mobs:register_arrow("mobs_mc:fireball", {
|
|||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 6},
|
||||
}, nil)
|
||||
local p = self.object:get_pos()
|
||||
if p then
|
||||
mcl_mobs:boom(self, p, 1, true)
|
||||
else
|
||||
mcl_mobs:boom(self, player:get_pos(), 1, true)
|
||||
end
|
||||
mcl_mobs:boom(self, self.object:get_pos(), 1, true)
|
||||
end,
|
||||
|
||||
hit_mob = function(self, mob)
|
||||
|
|
|
@ -8,14 +8,12 @@ mcl_mobs:register_mob("mobs_mc:guardian", {
|
|||
description = S("Guardian"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 4,
|
||||
hp_min = 30,
|
||||
hp_max = 30,
|
||||
xp_min = 10,
|
||||
xp_max = 10,
|
||||
breath_max = -1,
|
||||
passive = false,
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
pathfinding = 1,
|
||||
view_range = 16,
|
||||
|
|
|
@ -100,8 +100,6 @@ local horse = {
|
|||
description = S("Horse"),
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 6,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_horse.b3d",
|
||||
visual_size = {x=3.0, y=3.0},
|
||||
|
@ -492,8 +490,6 @@ local d = 0.86 -- donkey scale
|
|||
local donkey = table.copy(horse)
|
||||
donkey.description = S("Donkey")
|
||||
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
||||
donkey.spawn_in_group = 3
|
||||
donkey.spawn_in_group_min = 1
|
||||
donkey.animation = {
|
||||
speed_normal = 25,
|
||||
stand_start = 0, stand_end = 0,
|
||||
|
@ -546,14 +542,41 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
"Taiga",
|
||||
"Taiga_beach",
|
||||
"Forest",
|
||||
"Forest_beach",
|
||||
"FlowerForest",
|
||||
"FlowerForest_beach",
|
||||
"BirchForest",
|
||||
"BirchForestM",
|
||||
"RoofedForest",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
"SavannaM",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"Jungle",
|
||||
"Jungle_shore",
|
||||
"JungleM",
|
||||
"JungleM_shore",
|
||||
"JungleEdge",
|
||||
"JungleEdgeM",
|
||||
"Swampland",
|
||||
"Swampland_shore"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -563,22 +586,20 @@ minetest.LIGHT_MAX+1,
|
|||
mobs_mc.water_level+3,
|
||||
mcl_vars.mg_overworld_max)
|
||||
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:donkey",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
"SavannaM",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
},
|
||||
9,
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
|
|
|
@ -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
|
||||
|
||||
-- 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_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
|
||||
|
@ -143,8 +142,3 @@ dofile(path .. "/slime+magma_cube.lua") -- Wuzzy
|
|||
dofile(path .. "/spider.lua") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
|
||||
dofile(path .. "/vex.lua") -- KrupnoPavel
|
||||
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||
|
||||
dofile(path .. "/cod.lua")
|
||||
dofile(path .. "/salmon.lua")
|
||||
dofile(path .. "/tropical_fish.lua")
|
||||
dofile(path .. "/dolphin.lua")
|
||||
|
|
|
@ -28,17 +28,11 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
|||
description = S("Llama"),
|
||||
type = "animal",
|
||||
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,
|
||||
hp_min = 15,
|
||||
hp_max = 30,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
passive = false,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_llama.b3d",
|
||||
|
@ -51,7 +45,7 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
|||
},
|
||||
visual_size = {x=3, y=3},
|
||||
makes_footstep_sound = true,
|
||||
runaway = false,
|
||||
runaway = true,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 4.4,
|
||||
follow_velocity = 4.4,
|
||||
|
@ -217,46 +211,24 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
|||
|
||||
})
|
||||
|
||||
-- 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)
|
||||
mob:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 1},
|
||||
}, nil)
|
||||
end,
|
||||
|
||||
hit_node = function(self, pos, node)
|
||||
end
|
||||
})
|
||||
|
||||
--spawn
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:llama",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Savanna",
|
||||
"SavannaM",
|
||||
"SavannaM_beach",
|
||||
"Savanna_beach",
|
||||
"Savanna_ocean",
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"Jungle",
|
||||
"Jungle_shore",
|
||||
"JungleM",
|
||||
"JungleM_shore",
|
||||
"JungleEdge",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -1,58 +1,64 @@
|
|||
# textdomain: mobs_mc
|
||||
Agent=Agente
|
||||
Bat=Murciélago
|
||||
Blaze=Blaze
|
||||
Chicken=Pollo
|
||||
Cod=Bacalao
|
||||
Cow=Vaca
|
||||
Mooshroom=Champivaca
|
||||
Mooshroom=Champiñaca
|
||||
Creeper=Creeper
|
||||
Dolphin=Delfín
|
||||
Ender Dragon=Ender Dragon
|
||||
Ender Dragon=Enderdragón
|
||||
Enderman=Enderman
|
||||
Endermite=Endermite
|
||||
Ghast=Ghast
|
||||
Elder Guardian=Gran guardián
|
||||
Guardian=Guardián
|
||||
Elder Guardian=Guardián Anciano
|
||||
Donkey=Burro
|
||||
Horse=Caballo
|
||||
Skeleton Horse=Caballo esquelético
|
||||
Zombie Horse=Caballo zombie
|
||||
Donkey=Burro
|
||||
Mule=Mula
|
||||
Skeleton Horse=Caballo esqueleto
|
||||
Zombie Horse=Caballo zombi
|
||||
Iron Golem=Golem de hierro
|
||||
Llama=Llama
|
||||
Cat=Gato
|
||||
Ocelot=Ocelote
|
||||
Parrot=Loro
|
||||
Pig=Cerdo
|
||||
Polar Bear=Oso polar
|
||||
Killer Bunny=Conejo asesino
|
||||
Rabbit=Conejo
|
||||
Salmon=Salmón
|
||||
Killer Bunny=Conejo asesino
|
||||
Sheep=Oveja
|
||||
Shulker=Shulker
|
||||
Silverfish=Lepisma
|
||||
Skeleton=Esqueleto
|
||||
Stray=Esqueleto glacial
|
||||
Wither Skeleton=Esqueleto del Wither
|
||||
Stray=Esqueleto
|
||||
Wither Skeleton=Esqueleto wither
|
||||
Magma Cube=Cubo de Magma
|
||||
Slime=Slime
|
||||
Snow Golem=Golem de nieve
|
||||
Cave Spider=Araña de las cuevas
|
||||
Spider=Araña
|
||||
Cave Spider=Araña de las cuevas
|
||||
Squid=Calamar
|
||||
Vex=Ánima
|
||||
Master=Maestro
|
||||
Villager=Aldeano
|
||||
Evoker=Invocador
|
||||
Illusioner=Illusionista
|
||||
Villager=Aldeano
|
||||
Vindicator=Vindicador
|
||||
Zombie Villager=Aldeano zombi
|
||||
Zombie Villager=Aldeano zombie
|
||||
Witch=Bruja
|
||||
Wither=Wither
|
||||
Wolf=Lobo
|
||||
Baby Husk=Bebé Zombi Momificado
|
||||
Baby Zombie=Bebé Zombi
|
||||
Husk=Zombi Momificado
|
||||
Zombie=Zombi
|
||||
Baby Zombie Pigman=Bebé Hombrecerdo Zombi
|
||||
Zombie Pigman=Hombrecerdo Zombi
|
||||
Husk=Husk
|
||||
Zombie=Zombie
|
||||
Zombie Pigman=Cerdo Zombie
|
||||
Farmer=Granjero
|
||||
Fisherman=Pescador
|
||||
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
|
||||
Cleric=Clerc
|
||||
Nitwit=Crétin
|
||||
Cod=Morue
|
||||
Salmon=Saumon
|
||||
Dolphin=Dauphin
|
||||
Pillager=Pilleur
|
||||
Tropical fish=Poisson tropical
|
|
@ -62,8 +62,3 @@ Weapon Smith=
|
|||
Tool Smith=
|
||||
Cleric=
|
||||
Nitwit=
|
||||
Cod=
|
||||
Salmon=
|
||||
Dolphin=
|
||||
Pillager=
|
||||
Tropical fish=
|
|
@ -30,8 +30,6 @@ local ocelot = {
|
|||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
can_despawn = true,
|
||||
spawn_in_group = 3,
|
||||
spawn_in_group_min = 1,
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 1,
|
||||
|
|
|
@ -13,53 +13,6 @@ local shoulders = {
|
|||
right = vector.new(3.75,10.5,0)
|
||||
}
|
||||
|
||||
local function table_get_rand(tbl)
|
||||
local keys = {}
|
||||
for k in pairs(tbl) do
|
||||
table.insert(keys, k)
|
||||
end
|
||||
return tbl[keys[math.random(#keys)]]
|
||||
end
|
||||
|
||||
local function get_random_mob_sound()
|
||||
local t = table.copy(minetest.registered_entities)
|
||||
table.shuffle(t)
|
||||
for _,e in pairs(t) do
|
||||
if e.is_mob and e.sounds and #e.sounds > 0 then
|
||||
return table_get_rand(e.sounds)
|
||||
end
|
||||
end
|
||||
return minetest.registered_entities["mobs_mc:parrot"].sounds.random
|
||||
end
|
||||
|
||||
local function imitate_mob_sound(self,mob)
|
||||
local snd = mob.sounds.random
|
||||
if not snd or mob.name == "mobs_mc:parrot" or math.random(20) == 1 then
|
||||
snd = get_random_mob_sound()
|
||||
end
|
||||
return minetest.sound_play(snd, {
|
||||
pos = self.object:get_pos(),
|
||||
gain = 1.0,
|
||||
pitch = 2.5,
|
||||
max_hear_distance = self.sounds and self.sounds.distance or 32
|
||||
}, true)
|
||||
end
|
||||
|
||||
local function check_mobimitate(self,dtime)
|
||||
if not self._mobimitate_timer or self._mobimitate_timer > 30 then
|
||||
self._mobimitate_timer = 0
|
||||
for _,o in pairs(minetest.get_objects_inside_radius(self.object:get_pos(),20)) do
|
||||
local l = o:get_luaentity()
|
||||
if l and l.is_mob and l.name ~= "mobs_mc:parrot" then
|
||||
imitate_mob_sound(self,l)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
self._mobimitate_timer = self._mobimitate_timer + dtime
|
||||
|
||||
end
|
||||
|
||||
--find a free shoulder or return nil
|
||||
local function get_shoulder(player)
|
||||
local sh = "left"
|
||||
|
@ -100,8 +53,7 @@ local function check_perch(self,dtime)
|
|||
local n1 = minetest.get_node(vector.offset(p:get_pos(),0,-0.6,0)).name
|
||||
local n2 = minetest.get_node(vector.offset(p:get_pos(),0,0,0)).name
|
||||
local n3 = minetest.get_node(vector.offset(p:get_pos(),0,1,0)).name
|
||||
if ( n1 == "air" or minetest.get_item_group(n2,"water") > 0 or minetest.get_item_group(n2,"lava") > 0) and
|
||||
not minetest.is_creative_enabled(p:get_player_name()) then
|
||||
if n1 == "air" or minetest.get_item_group(n2,"water") > 0 or minetest.get_item_group(n2,"lava") > 0 then
|
||||
o:set_detach()
|
||||
self.detach_timer = 0
|
||||
return
|
||||
|
@ -127,7 +79,7 @@ end
|
|||
|
||||
mcl_mobs:register_mob("mobs_mc:parrot", {
|
||||
description = S("Parrot"),
|
||||
type = "passive",
|
||||
type = "npc",
|
||||
spawn_class = "passive",
|
||||
pathfinding = 1,
|
||||
hp_min = 6,
|
||||
|
@ -207,7 +159,6 @@ mcl_mobs:register_mob("mobs_mc:parrot", {
|
|||
end,
|
||||
do_custom = function(self,dtime)
|
||||
check_perch(self,dtime)
|
||||
check_mobimitate(self,dtime)
|
||||
end,
|
||||
do_punch = function(self,puncher) --do_punch is the mcl_mobs_redo variant - it gets called by on_punch later....
|
||||
if self.object:get_attach() == puncher then
|
||||
|
|
|
@ -15,10 +15,19 @@ mcl_mobs:register_mob("mobs_mc:pig", {
|
|||
visual = "mesh",
|
||||
mesh = "mobs_mc_pig.b3d",
|
||||
textures = {{
|
||||
"blank.png", -- baby
|
||||
"mobs_mc_pig.png", -- base
|
||||
"blank.png", -- saddle
|
||||
"mobs_mc_pig.png", -- base
|
||||
"blank.png",
|
||||
}},
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 2.9,
|
||||
head_eye_height = 0.8,
|
||||
horrizonatal_head_height=-.4,
|
||||
curiosity = 3,
|
||||
head_yaw="z",
|
||||
-------------------------------
|
||||
|
||||
visual_size = {x=2.5, y=2.5},
|
||||
makes_footstep_sound = true,
|
||||
walk_velocity = 1,
|
||||
|
@ -99,7 +108,7 @@ mcl_mobs:register_mob("mobs_mc:pig", {
|
|||
local wielditem = clicker:get_wielded_item()
|
||||
-- Feed pig
|
||||
if wielditem:get_name() ~= "mcl_mobitems:carrot_on_a_stick" then
|
||||
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
|
||||
end
|
||||
if mcl_mobs:protect(self, clicker) then return end
|
||||
|
||||
|
@ -111,9 +120,9 @@ mcl_mobs:register_mob("mobs_mc:pig", {
|
|||
local item = clicker:get_wielded_item()
|
||||
if item:get_name() == "mcl_mobitems:saddle" and self.saddle ~= "yes" then
|
||||
self.base_texture = {
|
||||
"blank.png", -- baby
|
||||
"mobs_mc_pig.png", -- base
|
||||
"mobs_mc_pig_saddle.png", -- saddle
|
||||
"mobs_mc_pig.png", -- base
|
||||
"blank.png", -- baby
|
||||
}
|
||||
self.object:set_properties({
|
||||
textures = self.base_texture
|
||||
|
@ -194,12 +203,17 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
local S = minetest.get_translator("mobs_mc")
|
||||
|
||||
local function reload(self)
|
||||
if not self.object:get_pos() then return end
|
||||
minetest.sound_play("mcl_bows_crossbow_drawback_1", {object = self.object, max_hear_distance=16}, true)
|
||||
local props = self.object:get_properties()
|
||||
if not props then return end
|
||||
props.textures[2] = "mcl_bows_crossbow_3.png^[resize:16x16"
|
||||
self.object:set_properties(props)
|
||||
end
|
||||
|
||||
local function reset_animation(self, animation)
|
||||
if not self.object:get_pos() or self._current_animation ~= animation then return end
|
||||
self._current_animation = "stand_reload" -- Mobs Redo won't set the animation unless we do this
|
||||
mcl_mobs:set_animation(self, animation)
|
||||
end
|
||||
|
||||
pillager = {
|
||||
description = S("Pillager"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
hp_min = 24,
|
||||
hp_max = 24,
|
||||
xp_min = 6,
|
||||
xp_max = 6,
|
||||
breath_max = -1,
|
||||
eye_height = 1.5,
|
||||
shoot_interval = 3,
|
||||
shoot_offset = 1.5,
|
||||
armor = {fleshy = 100},
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3},
|
||||
pathfinding = 1,
|
||||
group_attack = true,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_pillager.b3d",
|
||||
visual_size = {x=2.75, y=2.75},
|
||||
makes_footstep_sound = true,
|
||||
walk_velocity = 1.2,
|
||||
run_velocity = 4,
|
||||
view_range = 16,
|
||||
fear_height = 4,
|
||||
arrow = "mcl_bows:arrow_entity",
|
||||
attack_type = "dogshoot", -- Alternate punching/shooting
|
||||
reach = 0, -- Punching max distance
|
||||
damage = 0, -- Punching damage
|
||||
dogshoot_switch = 1, -- Start of shooting
|
||||
dogshoot_count_max = 5, -- Max time spent shooting (standing)
|
||||
dogshoot_count2_max = 1, -- Max time spent punching (running)
|
||||
sounds = {
|
||||
random = "mobs_mc_pillager_grunt2",
|
||||
war_cry = "mobs_mc_pillager_grunt1",
|
||||
death = "mobs_mc_pillager_ow2",
|
||||
damage = "mobs_mc_pillager_ow1",
|
||||
distance = 16,
|
||||
},
|
||||
textures = {
|
||||
{
|
||||
"mobs_mc_pillager.png", -- Skin
|
||||
"mcl_bows_crossbow_3.png^[resize:16x16", -- Wielded item
|
||||
}
|
||||
},
|
||||
drops = {
|
||||
{
|
||||
name = "mcl_bows:arrow",
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,
|
||||
looting = "common",
|
||||
},
|
||||
{
|
||||
name = "mcl_bows:crossbow",
|
||||
chance = 100 / 8.5,
|
||||
min = 1,
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
},
|
||||
},
|
||||
animation = {
|
||||
unloaded_walk_start = 1, unloaded_walk_end = 40,
|
||||
unloaded_stand_start = 41, unloaded_stand_end = 60,
|
||||
reload_stand_start = 61, reload_stand_end = 100, reload_stand_speed = 20,
|
||||
stand_start = 101, stand_end = 109, stand_speed = 6,
|
||||
walk_start = 111, walk_end = 150, walk_speed = 30,
|
||||
run_start = 111, run_end = 150, run_speed = 50,
|
||||
reload_run_start = 151, reload_run_end = 190, reload_run_speed = 20,
|
||||
die_start = 191, die_end = 192, die_speed = 15,
|
||||
stand_unloaded_start = 40, stand_unloaded_end = 59,
|
||||
die_loop = false,
|
||||
},
|
||||
shoot_arrow = function(self, pos, dir)
|
||||
minetest.sound_play("mcl_bows_crossbow_shoot", {object = self.object, max_hear_distance=16}, true)
|
||||
local props = self.object:get_properties()
|
||||
props.textures[2] = "mcl_bows_crossbow_0.png^[resize:16x16"
|
||||
self.object:set_properties(props)
|
||||
local old_anim = self._current_animation
|
||||
if old_anim == "run" or old_anim == "walk" then
|
||||
mcl_mobs:set_animation(self, "reload_run")
|
||||
end
|
||||
if old_anim == "stand" then
|
||||
mcl_mobs:set_animation(self, "reload_stand")
|
||||
end
|
||||
self._current_animation = old_anim -- Mobs Redo will imediately reset the animation otherwise
|
||||
minetest.after(1, reload, self)
|
||||
minetest.after(2, reset_animation, self, old_anim)
|
||||
|
||||
-- 2-4 damage per arrow
|
||||
local dmg = math.max(4, math.random(2, 8))
|
||||
mcl_bows_s.shoot_arrow_crossbow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg)
|
||||
|
||||
-- While we are at it, change the sounds since there is no way to do this in Mobs Redo
|
||||
if self.sounds and self.sounds.random then
|
||||
self.sounds = table.copy(self.sounds)
|
||||
self.sounds.random = "mobs_mc_pillager_grunt" .. math.random(2)
|
||||
end
|
||||
|
||||
-- Randomize reload time
|
||||
self.shoot_interval = math.random(3, 4)
|
||||
end,
|
||||
}
|
||||
|
||||
mcl_mobs:register_mob("mobs_mc:pillager", pillager)
|
||||
mcl_mobs:register_egg("mobs_mc:pillager", S("Pillager"), "mobs_mc_spawn_icon_pillager.png", 0)
|
|
@ -76,6 +76,7 @@ mcl_mobs:spawn_specific(
|
|||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -6,10 +6,9 @@ local rabbit = {
|
|||
description = S("Rabbit"),
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 3,
|
||||
passive = true,
|
||||
reach = 1,
|
||||
|
||||
hp_min = 3,
|
||||
hp_max = 3,
|
||||
xp_min = 1,
|
||||
|
@ -75,7 +74,7 @@ local rabbit = {
|
|||
},
|
||||
on_rightclick = function(self, clicker)
|
||||
-- Feed, tame protect or capture
|
||||
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:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end
|
||||
end,
|
||||
|
@ -133,9 +132,18 @@ mcl_mobs:spawn_specific(
|
|||
"Desert",
|
||||
"FlowerForest",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -1,228 +0,0 @@
|
|||
--MCmobs v0.4
|
||||
--maikerumine
|
||||
--made for MC like Survival game
|
||||
--License for code WTFPL and otherwise stated in readmes
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
--###################
|
||||
--################### salmon
|
||||
--###################
|
||||
|
||||
local salmon = {
|
||||
type = "animal",
|
||||
spawn_class = "water",
|
||||
can_despawn = true,
|
||||
passive = true,
|
||||
hp_min = 3,
|
||||
hp_max = 3,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
armor = 100,
|
||||
spawn_in_group = 5,
|
||||
tilt_swim = true,
|
||||
collisionbox = {-0.4, 0.0, -0.4, 0.4, 0.79, 0.4},
|
||||
visual = "mesh",
|
||||
mesh = "extra_mobs_salmon.b3d",
|
||||
textures = {
|
||||
{"extra_mobs_salmon.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:salmon_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,
|
||||
swim = true,
|
||||
fly = true,
|
||||
fly_in = "mcl_core:water_source",
|
||||
breathes_in_water = true,
|
||||
jump = false,
|
||||
view_range = 16,
|
||||
runaway = true,
|
||||
fear_height = 4,
|
||||
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_salmon")
|
||||
awards.unlock(clicker:get_player_name(), "mcl:tacticalFishing")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
mcl_mobs:register_mob("mobs_mc:salmon", salmon)
|
||||
|
||||
|
||||
--spawning TODO: in schools
|
||||
local water = 0
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:salmon",
|
||||
"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:salmon", S("Salmon"), "extra_mobs_spawn_icon_salmon.png", 0)
|
|
@ -61,7 +61,14 @@ mcl_mobs:register_mob("mobs_mc:sheep", {
|
|||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
|
||||
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 3.3,
|
||||
head_eye_height = 1.1,
|
||||
horrizonatal_head_height=-.7,
|
||||
curiosity = 6,
|
||||
head_yaw="z",
|
||||
-------------------------------
|
||||
visual = "mesh",
|
||||
visual_size = {x=3, y=3},
|
||||
mesh = "mobs_mc_sheepfur.b3d",
|
||||
|
@ -70,8 +77,6 @@ mcl_mobs:register_mob("mobs_mc:sheep", {
|
|||
color = "unicolor_white",
|
||||
makes_footstep_sound = true,
|
||||
walk_velocity = 1,
|
||||
runaway = true,
|
||||
runaway_from = {"mobs_mc:wolf"},
|
||||
drops = {
|
||||
{name = "mcl_mobitems:mutton",
|
||||
chance = 1,
|
||||
|
@ -197,7 +202,7 @@ mcl_mobs:register_mob("mobs_mc:sheep", {
|
|||
on_rightclick = function(self, clicker)
|
||||
local item = clicker:get_wielded_item()
|
||||
|
||||
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 item:get_name() == "mcl_tools:shears" and not self.gotten and not self.child then
|
||||
|
@ -348,7 +353,7 @@ mcl_mobs:spawn_specific(
|
|||
"Swampland",
|
||||
"Swampland_shore"
|
||||
},
|
||||
9,
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
|
|
|
@ -31,6 +31,11 @@ local skeleton = {
|
|||
"mcl_bows_bow_0.png", -- bow
|
||||
"mobs_mc_skeleton.png", -- skeleton
|
||||
} },
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 2.35,
|
||||
curiosity = .1,
|
||||
-------------------------------
|
||||
visual_size = {x=1, y=1},
|
||||
makes_footstep_sound = true,
|
||||
textures = {
|
||||
|
@ -162,6 +167,7 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -188,6 +194,7 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -226,6 +233,7 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -235,6 +243,7 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -260,6 +269,7 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -297,10 +307,10 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"SoulsandValley",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
7,
|
||||
30,
|
||||
10000,
|
||||
3,
|
||||
|
|
|
@ -101,8 +101,7 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"SoulsandValley",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
|
|
|
@ -402,8 +402,7 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -419,8 +418,7 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -435,8 +433,7 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -446,6 +443,11 @@ minetest.LIGHT_MAX+1,
|
|||
mmin,
|
||||
mmax)
|
||||
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_tiny", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_small", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_big", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
mcl_mobs:register_egg("mobs_mc:magma_cube_big", S("Magma Cube"), "mobs_mc_spawn_icon_magmacube.png")
|
||||
mcl_mobs:register_egg("mobs_mc:slime_big", S("Slime"), "mobs_mc_spawn_icon_slime.png")
|
||||
|
|
|
@ -33,6 +33,12 @@ local spider = {
|
|||
textures = {
|
||||
{"mobs_mc_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"},
|
||||
},
|
||||
--EXPERIMENTAL
|
||||
head_swivel = "Head_Control",
|
||||
bone_eye_height = 1,
|
||||
curiosity = 10,
|
||||
head_yaw="z",
|
||||
-------------------------------
|
||||
visual_size = {x=3, y=3},
|
||||
makes_footstep_sound = false,
|
||||
sounds = {
|
||||
|
@ -109,6 +115,7 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -135,6 +142,7 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -173,6 +181,7 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -182,6 +191,7 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -207,6 +217,7 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
|
Before Width: | Height: | Size: 766 B |
Before Width: | Height: | Size: 443 B |
Before Width: | Height: | Size: 830 B |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 353 B |
Before Width: | Height: | Size: 275 B |
Before Width: | Height: | Size: 978 B |
Before Width: | Height: | Size: 917 B |
Before Width: | Height: | Size: 939 B |
Before Width: | Height: | Size: 919 B |
Before Width: | Height: | Size: 921 B |
Before Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 923 B |
Before Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 938 B |
Before Width: | Height: | Size: 904 B |
Before Width: | Height: | Size: 932 B |
Before Width: | Height: | Size: 930 B |
Before Width: | Height: | Size: 930 B |
Before Width: | Height: | Size: 307 B |