Merge pull request 'merge beacon-branch into fork beacon branch' (#7) from MineClone2/MineClone2:beacons into beacon-"fork"

Reviewed-on: #7
This commit is contained in:
chmodsayshello 2022-07-23 09:30:48 +00:00
commit 121bbb6910
366 changed files with 7524 additions and 1157 deletions

2
API.md
View File

@ -42,7 +42,7 @@ A lot of things are possible by using one of the APIs in the mods. Note that not
* Buckets: `ITEMS/mcl_buckets` * Buckets: `ITEMS/mcl_buckets`
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers` * Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
## Mobs ### Mobs
* Mobs: `ENTITIES/mcl_mobs` * Mobs: `ENTITIES/mcl_mobs`
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short. MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.

View File

@ -27,6 +27,10 @@
* Code-Sploit * Code-Sploit
* NO11 * NO11
* kabou * kabou
* rudzik8
* chmodsayshello
* PrarieWind
* RandomLegoBrick
## Contributors ## Contributors
* Laurent Rocher * Laurent Rocher
@ -71,6 +75,10 @@
* Sven792 * Sven792
* aldum * aldum
* Dieter44 * Dieter44
* Pepebotella
* MrRar
* Lazerbeak12345
* mrminer
## MineClone5 ## MineClone5
* kay27 * kay27
@ -78,10 +86,12 @@
* epCode * epCode
* NO11 * NO11
* j45 * j45
* chmodsayshello
* 3raven * 3raven
* PrarieWind * PrarieWind
* Gustavo1 * Gustavo1
* CableGuy67 * CableGuy67
* MrRar
## Mineclonia ## Mineclonia
* erlehmann * erlehmann
@ -134,6 +144,9 @@
* yutyo * yutyo
* NO11 * NO11
* kay27 * kay27
* MysticTempest
* RandomLegoBrick
* cora
## Translations ## Translations
* Wuzzy * Wuzzy
@ -143,6 +156,8 @@
* pitchum * pitchum
* todoporlalibertad * todoporlalibertad
* Marcin Serwin * Marcin Serwin
* Pepebotella
* Emojigit
## Funders ## Funders
* 40W * 40W
@ -150,5 +165,6 @@
## Special thanks ## Special thanks
* celeron55 for creating Minetest * celeron55 for creating Minetest
* Jordach for the jukebox music compilation from Big Freaking Dig * Jordach for the jukebox music compilation from Big Freaking Dig
* wsor for working tirelessly in the shadows for the good of all of us, particularly helping with solving contentDB and copyright issues.
* The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game * The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game
* Notch and Jeb for being the major forces behind Minecraft * Notch and Jeb for being the major forces behind Minecraft

View File

@ -2,7 +2,7 @@
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils. An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
Developed by many people. Not developed or endorsed by Mojang AB. Developed by many people. Not developed or endorsed by Mojang AB.
Version: 0.75 (in development) Version: 0.78 (in development)
### Gameplay ### Gameplay
You start in a randomly-generated world made entirely of cubes. You can explore You start in a randomly-generated world made entirely of cubes. You can explore
@ -91,11 +91,11 @@ The MineClone2 repository is hosted at Mesehub. To contribute or report issues,
## Target ## Target
- Crucially, create a stable, moddable, free/libre clone of Minecraft - Crucially, create a stable, moddable, free/libre clone of Minecraft
based on the Minetest engine with polished features, usable in both based on the Minetest engine with polished features, usable in both
singleplayer and multiplayer. Currently, most of **Minecraft Java singleplayer and multiplayer. Currently, a lot of **Minecraft Java
Edition 1.12.2** features are already implemented and polishing existing Edition** features are already implemented and polishing existing
features are prioritized over new feature requests. features are prioritized over new feature requests.
- With lessened priority yet strictly, implement features targetting - With lessened priority yet strictly, implement features targetting
**Minecraft version 1.17 + OptiFine** (OptiFine only as far as supported **Current Minecraft versions + OptiFine** (OptiFine only as far as supported
by the Minetest Engine). This means features in parity with the listed by the Minetest Engine). This means features in parity with the listed
Minecraft experiences are prioritized over those that don't fulfill this Minecraft experiences are prioritized over those that don't fulfill this
scope. scope.
@ -108,8 +108,7 @@ playerbase on low spec computers, optimizations are hard to investigate.
This game is currently in **beta** stage. This game is currently in **beta** stage.
It is playable, but not yet feature-complete. It is playable, but not yet feature-complete.
Backwards-compability is not entirely guaranteed, updating your world might cause small bugs. Backwards-compability is not entirely guaranteed, updating your world might cause small bugs.
If you want to use the git version of MineClone2 in production, consider using the production branch. 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.
It is updated weekly and contains relatively stable code for servers.
The following main features are available: The following main features are available:
@ -124,7 +123,7 @@ The following main features are available:
* Most blocks in the overworld * Most blocks in the overworld
* Water and lava * Water and lava
* Weather * Weather
* 28 biomes * 28 biomes + 5 Nether Biomes
* The Nether, a fiery underworld in another dimension * The Nether, a fiery underworld in another dimension
* Redstone circuits (partially) * Redstone circuits (partially)
* Minecarts (partial) * Minecarts (partial)
@ -162,7 +161,7 @@ The following features are incomplete:
* Special minecarts * Special minecarts
* A couple of non-trivial blocks and items * A couple of non-trivial blocks and items
Bonus features (not found in Minecraft 1.12): Bonus features (not found in Minecraft):
* Built-in crafting guide which shows you crafting and smelting recipes * Built-in crafting guide which shows you crafting and smelting recipes
* In-game help system containing extensive help about gameplay basics, blocks, items and more * In-game help system containing extensive help about gameplay basics, blocks, items and more
@ -175,6 +174,9 @@ Bonus features (not found in Minecraft 1.12):
* Nether Brick Fence Gate * Nether Brick Fence Gate
* Red Nether Brick Fence * Red Nether Brick Fence
* Red Nether Brick Fence Gate * Red Nether Brick Fence Gate
* Structure replacements - these small variants of Minecraft structures serve as replacements until we can get large structures working:
* Woodland Cabin (Mansions)
* Nether Outpost (Fortress)
Technical differences from Minecraft: Technical differences from Minecraft:

View File

@ -1,2 +1,2 @@
name = MineClone 2 title = MineClone 2
description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more. description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more.

View File

@ -110,9 +110,11 @@ end
local boat = { local boat = {
physical = true, physical = true,
pointable = true,
-- Warning: Do not change the position of the collisionbox top surface, -- Warning: Do not change the position of the collisionbox top surface,
-- lowering it causes the boat to fall through the world if underwater -- lowering it causes the boat to fall through the world if underwater
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5}, collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.3, 0.7},
visual = "mesh", visual = "mesh",
mesh = "mcl_boats_boat.b3d", mesh = "mcl_boats_boat.b3d",
textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"}, textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"},

View File

@ -134,6 +134,7 @@ function mcl_burning.set_on_fire(obj, burn_time)
end end
function mcl_burning.extinguish(obj) function mcl_burning.extinguish(obj)
if not obj:get_pos() then return end
if mcl_burning.is_burning(obj) then if mcl_burning.is_burning(obj) then
local storage = mcl_burning.get_storage(obj) local storage = mcl_burning.get_storage(obj)
if obj:is_player() then if obj:is_player() then

View File

@ -1,66 +1,55 @@
-- Dripping Water Mod -- Dripping Water Mod
-- by kddekadenz -- by kddekadenz
local math = math
-- License of code, textures & sounds: CC0 -- License of code, textures & sounds: CC0
local function register_drop(liquid, glow, sound, nodes) local math = math
minetest.register_entity("mcl_dripping:drop_" .. liquid, { local function make_drop(pos,liquid,sound,interval)
hp_max = 1, local pt = {
physical = true, velocity = vector.new(0,0,0),
collide_with_objects = false, collision_removal = false,
collisionbox = {-0.01, 0.01, -0.01, 0.01, 0.01, 0.01}, }
glow = glow, local t = math.random() + math.random(1, interval)
pointable = false, minetest.after(t,function()
visual = "sprite", local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
visual_size = {x = 0.1, y = 0.1}, pt.pos = vector.offset(pos,x,-0.52,z)
textures = {""}, pt.acceleration = vector.new(0,0,0)
spritediv = {x = 1, y = 1}, pt.collisiondetection = false
initial_sprite_basepos = {x = 0, y = 0}, pt.expirationtime = t
static_save = false,
_dropped = false, pt.texture="[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"
on_activate = function(self) minetest.add_particle(pt)
self.object:set_properties({ minetest.after(t,function()
textures = {"[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"} pt.acceleration = vector.new(0,-5,0)
}) pt.collisiondetection = true
end, pt.expirationtime = math.random() + math.random(1, interval/2)
on_step = function(self, dtime) minetest.add_particle(pt)
local k = math.random(1, 222) minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = pos, gain = 0.5, max_hear_distance = 8}, true)
local ownpos = self.object:get_pos() end)
if k == 1 then end)
self.object:set_acceleration(vector.new(0, -5, 0)) end
end
if minetest.get_node(vector.offset(ownpos, 0, 0.5, 0)).name == "air" then local function register_drop(liquid, glow, sound, nodes, interval, chance)
self.object:set_acceleration(vector.new(0, -5, 0))
end
if minetest.get_node(vector.offset(ownpos, 0, -0.1, 0)).name ~= "air" then
local ent = self.object:get_luaentity()
if not ent._dropped then
ent._dropped = true
minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = ownpos, gain = 0.5, max_hear_distance = 8}, true)
end
if k < 3 then
self.object:remove()
end
end
end,
})
minetest.register_abm({ minetest.register_abm({
label = "Create drops", label = "Create drops",
nodenames = nodes, nodenames = nodes,
neighbors = {"group:" .. liquid}, neighbors = {"group:" .. liquid},
interval = 2, interval = interval,
chance = 22, chance = chance,
action = function(pos) action = function(pos)
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1, 0)).name, liquid) ~= 0 local r = math.ceil(interval / 20)
and minetest.get_node(vector.offset(pos, 0, -1, 0)).name == "air" then local nn=minetest.find_nodes_in_area(vector.offset(pos,-r,0,-r),vector.offset(pos,r,0,r),nodes)
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100 --start a bunch of particle cycles to be able to get away
minetest.add_entity(vector.offset(pos, x, -0.520, z), "mcl_dripping:drop_" .. liquid) --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
end end
end, end,
}) })
end end
register_drop("water", 1, "", {"group:opaque", "group:leaves"}) 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"}) register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"},60,10)

View File

@ -59,6 +59,8 @@ mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod") mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow") mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds") mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
mcl_item_entity.register_pickup_achievement("mcl_core:crying_obsidian", "mcl:whosCuttingOnions")
mcl_item_entity.register_pickup_achievement("mcl_nether:ancient_debris", "mcl:hiddenInTheDepths")
local function check_pickup_achievements(object, player) local function check_pickup_achievements(object, player)
if has_awards then if has_awards then
@ -78,7 +80,6 @@ local function enable_physics(object, luaentity, ignore_check)
object:set_properties({ object:set_properties({
physical = true physical = true
}) })
object:set_velocity({x=0,y=0,z=0})
object:set_acceleration({x=0,y=-get_gravity(),z=0}) object:set_acceleration({x=0,y=-get_gravity(),z=0})
end end
end end
@ -536,9 +537,9 @@ minetest.register_entity(":__builtin:item", {
self.itemstring = data.itemstring self.itemstring = data.itemstring
self.always_collect = data.always_collect self.always_collect = data.always_collect
if data.age then if data.age then
self.age = data.age + dtime_s self.age = data.age
else else
self.age = dtime_s self.age = self.age
end end
--remember collection data --remember collection data
-- If true, can collect item without delay -- If true, can collect item without delay
@ -774,8 +775,8 @@ minetest.register_entity(":__builtin:item", {
return return
end end
-- Move item around on flowing liquids -- 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 def.liquidtype == "flowing" then if def and def.liquidtype == "flowing" or def.liquidtype == "source" then
--[[ Get flowing direction (function call from flowlib), if there's a liquid. --[[ Get flowing direction (function call from flowlib), if there's a liquid.
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
@ -784,11 +785,11 @@ minetest.register_entity(":__builtin:item", {
-- Just to make sure we don't manipulate the speed for no reason -- Just to make sure we don't manipulate the speed for no reason
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
local f = 1.39 local f = 1.2
-- Set new item moving speed into the direciton of the liquid -- Set new item moving speed into the direciton of the liquid
local newv = vector.multiply(vec, f) local newv = vector.multiply(vec, f)
self.object:set_acceleration({x = 0, y = 0, z = 0}) -- Swap to acceleration instead of a static speed to better mimic MC mechanics.
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) self.object:set_acceleration({x = newv.x, y = -0.22, z = newv.z})
self.physical_state = true self.physical_state = true
self._flowing = true self._flowing = true
@ -808,7 +809,7 @@ minetest.register_entity(":__builtin:item", {
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local v = self.object:get_velocity() local v = self.object:get_velocity()
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and v.y == 0 then 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 if self.physical_state then
local own_stack = ItemStack(self.object:get_luaentity().itemstring) local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-- Merge with close entities of the same item -- Merge with close entities of the same item

View File

@ -21,7 +21,7 @@ local function register_rail(itemstring, tiles, def_extras, creative)
stack_max = 64, stack_max = 64,
groups = groups, groups = groups,
sounds = mcl_sounds.node_sound_metal_defaults(), sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 3.5, _mcl_blast_resistance = 0.7,
_mcl_hardness = 0.7, _mcl_hardness = 0.7,
after_destruct = function(pos) after_destruct = function(pos)
-- Scan for minecarts in this pos and force them to execute their "floating" check. -- Scan for minecarts in this pos and force them to execute their "floating" check.

View File

@ -91,7 +91,7 @@ minetest.register_chatcommand("clearmobs",{
if o.is_mob then if o.is_mob then
if param == "all" or if param == "all" or
( param == "nametagged" and o.nametag ) or ( param == "nametagged" and o.nametag ) or
( param == "" and not o.nametag and not o.tamed ) or ( param == "" and ( not o.nametag or o.nametag == "" ) and not o.tamed ) or
( num and num > 0 and vector.distance(p:get_pos(),o.object:get_pos()) <= num ) then ( num and num > 0 and vector.distance(p:get_pos(),o.object:get_pos()) <= num ) then
o.object:remove() o.object:remove()
end end
@ -298,9 +298,13 @@ local function update_roll(self)
if is_Fleckenstein then if is_Fleckenstein then
cbox[2], cbox[5] = -cbox[5], -cbox[2] 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 end
self.object:set_properties({collisionbox = cbox})
end end
-- set and return valid yaw -- set and return valid yaw
@ -1901,11 +1905,10 @@ local specific_attack = function(list, what)
return false return false
end end
-- monster find someone to attack -- find someone to attack
local monster_attack = function(self) local monster_attack = function(self)
if self.type ~= "monster" if not damage_enabled
or not damage_enabled
or minetest.is_creative_enabled("") or minetest.is_creative_enabled("")
or self.passive or self.passive
or self.state == "attack" or self.state == "attack"
@ -1923,10 +1926,9 @@ local monster_attack = function(self)
for n = 1, #objs do for n = 1, #objs do
if objs[n]:is_player() then if objs[n]:is_player() then
if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then
type = "" type = ""
else elseif (self.type == "monster" or self._aggro) then
player = objs[n] player = objs[n]
type = "player" type = "player"
name = "player" name = "player"
@ -2283,6 +2285,9 @@ end
local function go_to_pos(entity,b) local function go_to_pos(entity,b)
if not entity then return end if not entity then return end
local s=entity.object:get_pos() local s=entity.object:get_pos()
if not b then
--self.state = "stand"
return end
if vector.distance(b,s) < 1 then if vector.distance(b,s) < 1 then
--set_velocity(entity,0) --set_velocity(entity,0)
return true return true
@ -2305,15 +2310,52 @@ local function check_doors(self)
local def = minetest.registered_nodes[n.name] local def = minetest.registered_nodes[n.name]
local closed = n.name:find("_b_1") local closed = n.name:find("_b_1")
if t < 0.3 or t > 0.8 then if t < 0.3 or t > 0.8 then
if not closed then def.on_rightclick(d,n,self) end if not closed and def.on_rightclick then def.on_rightclick(d,n,self) end
else else
if closed then def.on_rightclick(d,n,self) end if closed and def.on_rightclick then def.on_rightclick(d,n,self) end
end end
end 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) -- execute current state (stand, walk, run, attacks)
-- returns true if mob has died -- returns true if mob has died
local do_states = function(self, dtime) local do_states = function(self, dtime)
@ -2326,9 +2368,8 @@ local do_states = function(self, dtime)
local s = self.object:get_pos() local s = self.object:get_pos()
local objs = minetest.get_objects_inside_radius(s, 3) local objs = minetest.get_objects_inside_radius(s, 3)
local lp
for n = 1, #objs do for n = 1, #objs do
if objs[n]:is_player() then if objs[n]:is_player() then
lp = objs[n]:get_pos() lp = objs[n]:get_pos()
break break
@ -2336,7 +2377,7 @@ local do_states = function(self, dtime)
end end
-- look at any players nearby, otherwise turn randomly -- look at any players nearby, otherwise turn randomly
if self.look_at_players then if lp and self.look_at_players then
local vec = { local vec = {
x = lp.x - s.x, x = lp.x - s.x,
@ -2372,32 +2413,7 @@ local do_states = function(self, dtime)
end end
elseif self.state == "gowp" then elseif self.state == "gowp" then
local p = self.object:get_pos() check_gowp(self,dtime)
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 elseif self.state == "walk" then
local s = self.object:get_pos() local s = self.object:get_pos()
@ -2908,7 +2924,12 @@ local plane_adjacents = {
vector.new(0,0,-1), vector.new(0,0,-1),
} }
local gopath_last = os.time()
function mcl_mobs:gopath(self,target,callback_arrived) 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 p = self.object:get_pos()
local t = vector.offset(target,0,1,0) local t = vector.offset(target,0,1,0)
local wp = minetest.find_path(p,t,150,1,4) local wp = minetest.find_path(p,t,150,1,4)
@ -2928,11 +2949,15 @@ function mcl_mobs:gopath(self,target,callback_arrived)
if wp and #wp > 0 then if wp and #wp > 0 then
self._target = t self._target = t
self.callback_arrived = callback_arrived self.callback_arrived = callback_arrived
table.remove(wp,1)
self.waypoints = wp self.waypoints = wp
self.state = "gowp" self.state = "gowp"
return true return true
else else
--minetest.log("no path found") self.state = "walk"
self.waypoints = nil
self.current_target = nil
-- minetest.log("no path found")
end end
end end
@ -2964,7 +2989,7 @@ local function damage_mob(self,reason,damage)
if damage > 0 then if damage > 0 then
self.health = self.health - damage self.health = self.health - damage
effect(pos, 5, "mcl_particles_smoke.png", 1, 2, 2, nil) effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil)
if check_for_death(self, reason, {type = reason}) then if check_for_death(self, reason, {type = reason}) then
return true return true
@ -3210,35 +3235,36 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
local die = false local die = false
-- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately.
if damage >= 0.1 then
-- weapon sounds if damage >= 0 then
if weapon:get_definition().sounds ~= nil then -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately.
if damage >= 0.1 then
-- weapon sounds
if weapon:get_definition().sounds ~= nil then
local s = random(0, #weapon:get_definition().sounds) local s = random(0, #weapon:get_definition().sounds)
minetest.sound_play(weapon:get_definition().sounds[s], { minetest.sound_play(weapon:get_definition().sounds[s], {
object = self.object, --hitter, object = self.object, --hitter,
max_hear_distance = 8 max_hear_distance = 8
}, true) }, true)
else else
minetest.sound_play("default_punch", { minetest.sound_play("default_punch", {
object = self.object, object = self.object,
max_hear_distance = 5 max_hear_distance = 5
}, true) }, true)
end
damage_effect(self, damage)
-- do damage
self.health = self.health - damage
-- skip future functions if dead, except alerting others
if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then
die = true
end
end end
damage_effect(self, damage)
-- do damage
self.health = self.health - damage
-- skip future functions if dead, except alerting others
if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then
die = true
end
-- knock back effect (only on full punch) -- knock back effect (only on full punch)
if not die if not die
and self.knock_back and self.knock_back
@ -3318,11 +3344,11 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
and (self.child == false or self.type == "monster") and (self.child == false or self.type == "monster")
and hitter:get_player_name() ~= self.owner and hitter:get_player_name() ~= self.owner
and not mcl_mobs.invis[ name ] then and not mcl_mobs.invis[ name ] then
if not die then if not die then
-- attack whoever punched mob -- attack whoever punched mob
self.state = "" self.state = ""
do_attack(self, hitter) do_attack(self, hitter)
self._aggro= true
end end
-- alert others to the attack -- alert others to the attack
@ -3334,7 +3360,6 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
obj = objs[n]:get_luaentity() obj = objs[n]:get_luaentity()
if obj then if obj then
-- only alert members of same mob or friends -- only alert members of same mob or friends
if obj.group_attack if obj.group_attack
and obj.state ~= "attack" and obj.state ~= "attack"
@ -3344,6 +3369,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
elseif type(obj.group_attack) == "table" then elseif type(obj.group_attack) == "table" then
for i=1, #obj.group_attack do for i=1, #obj.group_attack do
if obj.name == obj.group_attack[i] then if obj.name == obj.group_attack[i] then
obj._aggro = true
do_attack(obj, hitter) do_attack(obj, hitter)
break break
end end
@ -4008,6 +4034,8 @@ minetest.register_entity(name, {
fire_resistant = def.fire_resistant or false, fire_resistant = def.fire_resistant or false,
fire_damage_resistant = def.fire_damage_resistant or false, fire_damage_resistant = def.fire_damage_resistant or false,
ignited_by_sunlight = def.ignited_by_sunlight 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 -- End of MCL2 extensions
on_spawn = def.on_spawn, on_spawn = def.on_spawn,
@ -4333,7 +4361,7 @@ end
-- feeding, taming and breeding (thanks blert2112) -- feeding, taming and breeding (thanks blert2112)
function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame) function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame, notake)
if not self.follow then if not self.follow then
return false return false
end end
@ -4346,7 +4374,7 @@ function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame)
local item = clicker:get_wielded_item() local item = clicker:get_wielded_item()
item:take_item() if not notake then item:take_item() end
clicker:set_wielded_item(item) clicker:set_wielded_item(item)
end end

View File

@ -15,7 +15,7 @@ local math_cos = math.cos
local math_sin = math.sin local math_sin = math.sin
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
--local vector_distance = vector.distance local vector_distance = vector.distance
local vector_new = vector.new local vector_new = vector.new
local vector_floor = vector.floor local vector_floor = vector.floor
@ -25,7 +25,15 @@ local table_remove = table.remove
local pairs = pairs local pairs = pairs
-- range for mob count -- range for mob count
local aoc_range = 32 local aoc_range = 136
local mob_cap = {
monster = 70,
animal =10,
ambient =15,
water = 5, --currently unused
water_ambient = 20, --currently unused
}
--do mobs spawn? --do mobs spawn?
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
@ -153,6 +161,10 @@ local list_of_all_biomes = {
-- dimension biome: -- dimension biome:
"Nether", "Nether",
"BasaltDelta",
"CrimsonForest",
"WarpedForest",
"SoulsandValley",
"End", "End",
-- Overworld regular: -- Overworld regular:
@ -162,6 +174,8 @@ local list_of_all_biomes = {
"Swampland", "Swampland",
"Taiga", "Taiga",
"ExtremeHills", "ExtremeHills",
"ExtremeHillsM",
"ExtremeHills+_snowtop",
"Jungle", "Jungle",
"Savanna", "Savanna",
"BirchForest", "BirchForest",
@ -180,7 +194,6 @@ local list_of_all_biomes = {
"ExtremeHills+_snowtop", "ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop", "MesaPlateauFM_grasstop",
"JungleEdgeM", "JungleEdgeM",
"ExtremeHillsM",
"JungleM", "JungleM",
"BirchForestM", "BirchForestM",
"MesaPlateauF", "MesaPlateauF",
@ -192,11 +205,26 @@ local list_of_all_biomes = {
} }
-- count how many mobs are in an area -- count how many mobs are in an area
local function count_mobs(pos) local function count_mobs(pos,r,mob_type)
local num = 0 local num = 0
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do for _,l in pairs(minetest.luaentities) do
if object and object:get_luaentity() and object:get_luaentity().is_mob then if l and l.is_mob and (mob_type == nil or l.type == mob_type) then
num = num + 1 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
end end
end end
return num return num
@ -289,7 +317,7 @@ function mcl_mobs:spawn_setup(def)
spawn_dictionary[#spawn_dictionary + 1] = { spawn_dictionary[#spawn_dictionary + 1] = {
name = name, name = name,
dimension = dimension, dimension = dimension,
type_of_spawning = type_of_spawning, type_of_spawning = type_of_spawning,
biomes = biomes, biomes = biomes,
min_light = min_light, min_light = min_light,
max_light = max_light, max_light = max_light,
@ -376,11 +404,52 @@ local function is_farm_animal(n)
return n == "mobs_mc:pig" or n == "mobs_mc:cow" or n == "mobs_mc:sheep" or n == "mobs_mc:chicken" or n == "mobs_mc:horse" or n == "mobs_mc:donkey" return n == "mobs_mc:pig" or n == "mobs_mc:cow" or n == "mobs_mc:sheep" or n == "mobs_mc:chicken" or n == "mobs_mc:horse" or n == "mobs_mc:donkey"
end end
local function get_water_spawn(p)
local nn = minetest.find_nodes_in_area(vector.offset(p,-2,-1,-2),vector.offset(p,2,-15,2),{"group:water"})
if nn and #nn > 0 then
return nn[math.random(#nn)]
end
end
local dbg_spawn_attempts = 0
local dbg_spawn_succ = 0
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
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 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
return o
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
})
if mobs_spawn then if mobs_spawn then
local perlin_noise local perlin_noise
local function spawn_a_mob(pos, dimension, y_min, y_max) local function spawn_a_mob(pos, dimension, y_min, y_max)
dbg_spawn_attempts = dbg_spawn_attempts + 1
local dimension = dimension or mcl_worlds.pos_to_dimension(pos) local dimension = dimension or mcl_worlds.pos_to_dimension(pos)
local goal_pos = get_next_mob_spawn_pos(pos) local goal_pos = get_next_mob_spawn_pos(pos)
local spawning_position_list = find_nodes_in_area_under_air( local spawning_position_list = find_nodes_in_area_under_air(
@ -391,9 +460,6 @@ if mobs_spawn then
if #spawning_position_list <= 0 then return end if #spawning_position_list <= 0 then return end
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)] local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
--hard code mob limit in area to 5 for now
if count_mobs(spawning_position) >= 5 then return end
local gotten_node = get_node(spawning_position).name local gotten_node = get_node(spawning_position).name
local gotten_biome = minetest.get_biome_data(spawning_position) local gotten_biome = minetest.get_biome_data(spawning_position)
if not gotten_node or not gotten_biome then return end if not gotten_node or not gotten_biome then return end
@ -407,6 +473,8 @@ if mobs_spawn then
local is_water = get_item_group(gotten_node, "water") ~= 0 local is_water = get_item_group(gotten_node, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 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_ground = not (is_water or is_lava) local is_ground = not (is_water or is_lava)
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0 local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
local has_bed = minetest.find_node_near(pos,25,{"group:bed"}) local has_bed = minetest.find_node_near(pos,25,{"group:bed"})
@ -426,6 +494,7 @@ if mobs_spawn then
perlin_noise = perlin_noise or minetest_get_perlin(noise_params) perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
local noise = perlin_noise:get_3d(spawning_position) local noise = perlin_noise:get_3d(spawning_position)
local current_summary_chance = summary_chance local current_summary_chance = summary_chance
table.shuffle(mob_library_worker_table)
while #mob_library_worker_table > 0 do while #mob_library_worker_table > 0 do
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1 local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
local mob_index = 1 local mob_index = 1
@ -438,7 +507,12 @@ if mobs_spawn then
end end
local mob_def = mob_library_worker_table[mob_index] local mob_def = mob_library_worker_table[mob_index]
local mob_type = minetest.registered_entities[mob_def.name].type local mob_type = minetest.registered_entities[mob_def.name].type
local spawn_in_group = minetest.registered_entities[mob_def.name].spawn_in_group or 4
local mob_count_wide = count_mobs(pos,aoc_range,mob_type)
local mob_count = count_mobs(spawning_position,32,mob_type)
if mob_def if mob_def
and mob_count_wide < (mob_cap[mob_type] or 15)
and mob_count < 5
and spawning_position.y >= mob_def.min_height and spawning_position.y >= mob_def.min_height
and spawning_position.y <= mob_def.max_height and spawning_position.y <= mob_def.max_height
and mob_def.dimension == dimension and mob_def.dimension == dimension
@ -446,14 +520,29 @@ if mobs_spawn then
and gotten_light >= mob_def.min_light and gotten_light >= mob_def.min_light
and gotten_light <= mob_def.max_light and gotten_light <= mob_def.max_light
and (is_ground or mob_def.type_of_spawning ~= "ground") and (is_ground or mob_def.type_of_spawning ~= "ground")
and (mob_def.type_of_spawning ~= "ground" or not is_leaf)
and (mob_def.check_position and mob_def.check_position(spawning_position) or true) 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 (not is_farm_animal(mob_def.name) or is_grass)
and (mob_type ~= "npc" or has_bed) and (mob_type ~= "npc" or has_bed)
and (mob_def.type_of_spawning ~= "water" or is_water)
and not is_bedrock
then then
if mob_def.type_of_spawning == "water" then
spawning_position = get_water_spawn(spawning_position)
if not spawning_position then
return
end
end
--everything is correct, spawn mob --everything is correct, spawn mob
local object = minetest.add_entity(spawning_position, mob_def.name) local object
if spawn_in_group then
object = spawn_group(spawning_position,mob_def,{gotten_node},spawn_in_group,spawn_in_group_min)
else object = minetest.add_entity(spawning_position, mob_def.name)
end
if object then if object then
return mob_def.on_spawn and mob_def.on_spawn(object, pos) return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position)
end end
end end
current_summary_chance = current_summary_chance - mob_chance current_summary_chance = current_summary_chance - mob_chance

View File

@ -46,6 +46,9 @@ end
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"] local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
local old_on_place = wither_head.on_place local old_on_place = wither_head.on_place
function wither_head.on_place(itemstack, placer, pointed) function wither_head.on_place(itemstack, placer, pointed)
minetest.after(0, wither_spawn, pointed.above) local n = minetest.get_node(vector.offset(pointed.above,0,-1,0))
old_on_place(itemstack, placer, pointed) 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)
end end

View File

@ -7,6 +7,7 @@ mcl_mobs:register_mob("mobs_mc:bat", {
type = "animal", type = "animal",
spawn_class = "ambient", spawn_class = "ambient",
can_despawn = true, can_despawn = true,
spawn_in_group = 8,
passive = true, passive = true,
hp_min = 6, hp_min = 6,
hp_max = 6, hp_max = 6,

View File

@ -16,6 +16,8 @@ mcl_mobs:register_mob("mobs_mc:blaze", {
description = S("Blaze"), description = S("Blaze"),
type = "monster", type = "monster",
spawn_class = "hostile", spawn_class = "hostile",
spawn_in_group_min = 2,
spawn_in_group = 3,
hp_min = 20, hp_min = 20,
hp_max = 20, hp_max = 20,
xp_min = 10, xp_min = 10,

View File

@ -122,8 +122,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ExtremeHillsM", "ExtremeHillsM",
"ExtremeHills+", "ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains", "Plains",
"Plains_beach", "Plains_beach",
"SunflowerPlains", "SunflowerPlains",

View File

@ -0,0 +1,274 @@
--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_fishing: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)

View File

@ -83,6 +83,8 @@ mcl_mobs:register_mob("mobs_mc:cow", cow_def)
local mooshroom_def = table.copy(cow_def) local mooshroom_def = table.copy(cow_def)
mooshroom_def.description = S("Mooshroom") mooshroom_def.description = S("Mooshroom")
mooshroom_def.mesh = "mobs_mc_cow.b3d" 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.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
mooshroom_def.on_rightclick = function(self, clicker) mooshroom_def.on_rightclick = function(self, clicker)
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
@ -151,17 +153,12 @@ mcl_mobs:spawn_specific(
"ground", "ground",
{ {
"flat", "flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga", "MegaTaiga",
"MegaSpruceTaiga", "MegaSpruceTaiga",
"ExtremeHills", "ExtremeHills",
"ExtremeHills_beach", "ExtremeHills_beach",
"ExtremeHillsM", "ExtremeHillsM",
"ExtremeHills+", "ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach", "StoneBeach",
"Plains", "Plains",
"Plains_beach", "Plains_beach",

View File

@ -274,7 +274,6 @@ mcl_mobs:spawn_specific(
"Plains", "Plains",
"Desert", "Desert",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -301,7 +300,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",
@ -340,7 +338,6 @@ mcl_mobs:spawn_specific(
"Forest_deep_ocean", "Forest_deep_ocean",
"JungleM_deep_ocean", "JungleM_deep_ocean",
"FlowerForest_deep_ocean", "FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean", "MegaTaiga_ocean",
"StoneBeach_deep_ocean", "StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean", "IcePlainsSpikes_deep_ocean",
@ -350,7 +347,6 @@ mcl_mobs:spawn_specific(
"MesaBryce_deep_ocean", "MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean", "ExtremeHills+_deep_ocean",
"ExtremeHills_ocean", "ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean", "Forest_ocean",
"MegaTaiga_deep_ocean", "MegaTaiga_deep_ocean",
"JungleEdge_ocean", "JungleEdge_ocean",
@ -376,7 +372,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",

View File

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

View File

@ -35,6 +35,7 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", {
}, },
physical = true, physical = true,
damage = 10, damage = 10,
knock_back = false,
jump = true, jump = true,
jump_height = 14, jump_height = 14,
fly = true, fly = true,

View File

@ -627,7 +627,6 @@ mcl_mobs:spawn_specific(
"Plains", "Plains",
"Desert", "Desert",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -654,7 +653,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",
@ -693,7 +691,6 @@ mcl_mobs:spawn_specific(
"Forest_deep_ocean", "Forest_deep_ocean",
"JungleM_deep_ocean", "JungleM_deep_ocean",
"FlowerForest_deep_ocean", "FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean", "MegaTaiga_ocean",
"StoneBeach_deep_ocean", "StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean", "IcePlainsSpikes_deep_ocean",
@ -703,7 +700,6 @@ mcl_mobs:spawn_specific(
"MesaBryce_deep_ocean", "MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean", "ExtremeHills+_deep_ocean",
"ExtremeHills_ocean", "ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean", "Forest_ocean",
"MegaTaiga_deep_ocean", "MegaTaiga_deep_ocean",
"JungleEdge_ocean", "JungleEdge_ocean",
@ -729,7 +725,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",
@ -766,15 +761,32 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"SoulsandVall3ey",
}, },
0, 0,
7, 11,
30, 30,
27500, 27500,
4, 4,
mcl_vars.mg_nether_min, mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max) mcl_vars.mg_nether_max)
-- Warped Forest spawn (common)
mcl_mobs:spawn_specific(
"mobs_mc:enderman",
"nether",
"ground",
{
"WarpedForest"
},
0,
11,
30,
5000,
4,
mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max)
-- spawn eggs -- spawn eggs
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0) mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)

View File

@ -23,6 +23,7 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
collisionbox = {-2, 5, -2, 2, 9, 2}, collisionbox = {-2, 5, -2, 2, 9, 2},
visual = "mesh", visual = "mesh",
mesh = "mobs_mc_ghast.b3d", mesh = "mobs_mc_ghast.b3d",
spawn_in_group = 1,
textures = { textures = {
{"mobs_mc_ghast.png"}, {"mobs_mc_ghast.png"},
}, },
@ -81,12 +82,14 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"SoulsandValley",
"BasaltDelta",
}, },
0, 0,
minetest.LIGHT_MAX+1, 7,
30, 30,
18000, 72000,
2, 2,
mcl_vars.mg_nether_min, mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max) mcl_vars.mg_nether_max)
@ -105,7 +108,12 @@ mcl_mobs:register_arrow("mobs_mc:fireball", {
full_punch_interval = 1.0, full_punch_interval = 1.0,
damage_groups = {fleshy = 6}, damage_groups = {fleshy = 6},
}, nil) }, nil)
mcl_mobs:boom(self, self.object:get_pos(), 1, true) 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
end, end,
hit_mob = function(self, mob) hit_mob = function(self, mob)

View File

@ -8,12 +8,14 @@ mcl_mobs:register_mob("mobs_mc:guardian", {
description = S("Guardian"), description = S("Guardian"),
type = "monster", type = "monster",
spawn_class = "hostile", spawn_class = "hostile",
spawn_in_group_min = 2,
spawn_in_group = 4,
hp_min = 30, hp_min = 30,
hp_max = 30, hp_max = 30,
xp_min = 10, xp_min = 10,
xp_max = 10, xp_max = 10,
breath_max = -1, breath_max = -1,
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
pathfinding = 1, pathfinding = 1,
view_range = 16, view_range = 16,

View File

@ -81,11 +81,27 @@ for b=1, #horse_base do
end end
end end
-- in e7898352d890c2414af653eba624939df9c0b8b4 (0.76-dev) all items from mobs_mc were moved to mcl_mobitems
-- this results in existing horses wearing armor would still have the old texture filename in their
-- properties this function updates them. It should be removed some time in the future when we can be
-- reasonably sure all horses that want it get the new nexture.
local function update_textures(self)
local old = "mobs_mc_horse_armor_"
local txt = self.object:get_properties().textures
if txt[2]:find(old) then
txt[2] = txt[2]:gsub(old,"mcl_mobitems_horse_armor_")
self.object:set_properties({textures=txt})
return
end
end
-- Horse -- Horse
local horse = { local horse = {
description = S("Horse"), description = S("Horse"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
spawn_in_group_min = 2,
spawn_in_group = 6,
visual = "mesh", visual = "mesh",
mesh = "mobs_mc_horse.b3d", mesh = "mobs_mc_horse.b3d",
visual_size = {x=3.0, y=3.0}, visual_size = {x=3.0, y=3.0},
@ -138,7 +154,7 @@ local horse = {
max = 2, max = 2,
looting = "common",}, looting = "common",},
}, },
on_spawn = update_textures,
do_custom = function(self, dtime) do_custom = function(self, dtime)
-- set needed values if not already present -- set needed values if not already present
@ -476,6 +492,8 @@ local d = 0.86 -- donkey scale
local donkey = table.copy(horse) local donkey = table.copy(horse)
donkey.description = S("Donkey") donkey.description = S("Donkey")
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}} donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
donkey.spawn_in_group = 3
donkey.spawn_in_group_min = 1
donkey.animation = { donkey.animation = {
speed_normal = 25, speed_normal = 25,
stand_start = 0, stand_end = 0, stand_start = 0, stand_end = 0,
@ -528,41 +546,14 @@ mcl_mobs:spawn_specific(
"ground", "ground",
{ {
"flat", "flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains", "Plains",
"Plains_beach", "Plains_beach",
"SunflowerPlains", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna", "Savanna",
"Savanna_beach", "Savanna_beach",
"SavannaM", "SavannaM",
"Jungle", "Savanna_beach",
"Jungle_shore", "Plains_beach",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
@ -572,20 +563,22 @@ minetest.LIGHT_MAX+1,
mobs_mc.water_level+3, mobs_mc.water_level+3,
mcl_vars.mg_overworld_max) mcl_vars.mg_overworld_max)
mcl_mobs:spawn_specific( mcl_mobs:spawn_specific(
"mobs_mc:donkey", "mobs_mc:donkey",
"overworld", "overworld",
"ground", "ground",
{ {
"Mesa", "flat",
"MesaPlateauFM_grasstop", "Plains",
"MesaPlateauF", "Plains_beach",
"MesaPlateauFM", "SunflowerPlains",
"MesaPlateauF_grasstop", "Savanna",
"MesaBryce", "Savanna_beach",
"SavannaM",
"Savanna_beach",
"Plains_beach",
}, },
0, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
30, 30,
15000, 15000,

View File

@ -142,3 +142,7 @@ 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 .. "/spider.lua") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
dofile(path .. "/vex.lua") -- KrupnoPavel dofile(path .. "/vex.lua") -- KrupnoPavel
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/cod.lua")
dofile(path .. "/salmon.lua")
dofile(path .. "/dolphin.lua")

View File

@ -37,6 +37,7 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", {
run_velocity = 1.2, run_velocity = 1.2,
-- Approximation -- Approximation
damage = 14, damage = 14,
knock_back = false,
reach = 3, reach = 3,
group_attack = true, group_attack = true,
attacks_monsters = true, attacks_monsters = true,

View File

@ -28,6 +28,8 @@ mcl_mobs:register_mob("mobs_mc:llama", {
description = S("Llama"), description = S("Llama"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
spawn_in_group_min = 4,
spawn_in_group = 6,
hp_min = 15, hp_min = 15,
hp_max = 30, hp_max = 30,
xp_min = 1, xp_min = 1,
@ -217,18 +219,16 @@ mcl_mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"Mesa", "Savanna",
"MesaPlateauFM_grasstop", "SavannaM",
"MesaPlateauF", "SavannaM_beach",
"MesaPlateauFM", "Savanna_beach",
"MesaPlateauF_grasstop", "Savanna_ocean",
"MesaBryce",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge", "JungleEdge",
"JungleEdgeM", "JungleEdgeM",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

View File

@ -1,64 +1,58 @@
# textdomain: mobs_mc # textdomain: mobs_mc
Agent=Agente
Bat=Murciélago Bat=Murciélago
Blaze=Blaze Blaze=Blaze
Chicken=Pollo Chicken=Pollo
Cod=Bacalao
Cow=Vaca Cow=Vaca
Mooshroom=Champiñaca Mooshroom=Champivaca
Creeper=Creeper Creeper=Creeper
Ender Dragon=Enderdragón Dolphin=Delfín
Ender Dragon=Ender Dragon
Enderman=Enderman Enderman=Enderman
Endermite=Endermite Endermite=Endermite
Ghast=Ghast Ghast=Ghast
Elder Guardian=Gran guardián
Guardian=Guardián Guardian=Guardián
Horse=Caballo Elder Guardian=Guardián Anciano
Skeleton Horse=Caballo esquelético
Zombie Horse=Caballo zombie
Donkey=Burro Donkey=Burro
Horse=Caballo
Mule=Mula Mule=Mula
Skeleton Horse=Caballo esqueleto
Zombie Horse=Caballo zombi
Iron Golem=Golem de hierro Iron Golem=Golem de hierro
Llama=Llama Llama=Llama
Cat=Gato
Ocelot=Ocelote Ocelot=Ocelote
Parrot=Loro Parrot=Loro
Pig=Cerdo Pig=Cerdo
Polar Bear=Oso polar Polar Bear=Oso polar
Rabbit=Conejo
Killer Bunny=Conejo asesino Killer Bunny=Conejo asesino
Rabbit=Conejo
Salmon=Salmón
Sheep=Oveja Sheep=Oveja
Shulker=Shulker Shulker=Shulker
Silverfish=Lepisma Silverfish=Lepisma
Skeleton=Esqueleto Skeleton=Esqueleto
Stray=Esqueleto Stray=Esqueleto glacial
Wither Skeleton=Esqueleto wither Wither Skeleton=Esqueleto del Wither
Magma Cube=Cubo de Magma Magma Cube=Cubo de Magma
Slime=Slime Slime=Slime
Snow Golem=Golem de nieve Snow Golem=Golem de nieve
Spider=Araña
Cave Spider=Araña de las cuevas Cave Spider=Araña de las cuevas
Spider=Araña
Squid=Calamar Squid=Calamar
Vex=Ánima Vex=Ánima
Master=Maestro
Villager=Aldeano
Evoker=Invocador Evoker=Invocador
Illusioner=Illusionista Illusioner=Illusionista
Villager=Aldeano
Vindicator=Vindicador Vindicator=Vindicador
Zombie Villager=Aldeano zombie Zombie Villager=Aldeano zombi
Witch=Bruja Witch=Bruja
Wither=Wither Wither=Wither
Wolf=Lobo Wolf=Lobo
Husk=Husk Baby Husk=Bebé Zombi Momificado
Zombie=Zombie Baby Zombie=Bebé Zombi
Zombie Pigman=Cerdo Zombie Husk=Zombi Momificado
Farmer=Granjero Zombie=Zombi
Fisherman=Pescador Baby Zombie Pigman=Bebé Hombrecerdo Zombi
Fletcher=Flechador Zombie Pigman=Hombrecerdo Zombi
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

View File

@ -62,3 +62,6 @@ Weapon Smith=
Tool Smith= Tool Smith=
Cleric= Cleric=
Nitwit= Nitwit=
Cod=
Salmon=
Dolphin=

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -30,6 +30,8 @@ local ocelot = {
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
can_despawn = true, can_despawn = true,
spawn_in_group = 3,
spawn_in_group_min = 1,
hp_min = 10, hp_min = 10,
hp_max = 10, hp_max = 10,
xp_min = 1, xp_min = 1,

View File

@ -13,6 +13,45 @@ local shoulders = {
right = vector.new(3.75,10.5,0) right = vector.new(3.75,10.5,0)
} }
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 then
return e.sounds[math.random(#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 --find a free shoulder or return nil
local function get_shoulder(player) local function get_shoulder(player)
local sh = "left" local sh = "left"
@ -159,6 +198,7 @@ mcl_mobs:register_mob("mobs_mc:parrot", {
end, end,
do_custom = function(self,dtime) do_custom = function(self,dtime)
check_perch(self,dtime) check_perch(self,dtime)
check_mobimitate(self,dtime)
end, end,
do_punch = function(self,puncher) --do_punch is the mcl_mobs_redo variant - it gets called by on_punch later.... 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 if self.object:get_attach() == puncher then

View File

@ -194,17 +194,12 @@ mcl_mobs:spawn_specific(
"ground", "ground",
{ {
"flat", "flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga", "MegaTaiga",
"MegaSpruceTaiga", "MegaSpruceTaiga",
"ExtremeHills", "ExtremeHills",
"ExtremeHills_beach", "ExtremeHills_beach",
"ExtremeHillsM", "ExtremeHillsM",
"ExtremeHills+", "ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach", "StoneBeach",
"Plains", "Plains",
"Plains_beach", "Plains_beach",

View File

@ -76,7 +76,6 @@ mcl_mobs:spawn_specific(
"ColdTaiga", "ColdTaiga",
"IcePlainsSpikes", "IcePlainsSpikes",
"IcePlains", "IcePlains",
"ExtremeHills+_snowtop",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

View File

@ -6,9 +6,10 @@ local rabbit = {
description = S("Rabbit"), description = S("Rabbit"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
spawn_in_group_min = 2,
spawn_in_group = 3,
passive = true, passive = true,
reach = 1, reach = 1,
hp_min = 3, hp_min = 3,
hp_max = 3, hp_max = 3,
xp_min = 1, xp_min = 1,
@ -132,18 +133,9 @@ mcl_mobs:spawn_specific(
"Desert", "Desert",
"FlowerForest", "FlowerForest",
"Taiga", "Taiga",
"ExtremeHills",
"BirchForest",
"MegaSpruceTaiga", "MegaSpruceTaiga",
"MegaTaiga", "MegaTaiga",
"ExtremeHills+",
"Plains",
"ColdTaiga", "ColdTaiga",
"SunflowerPlains",
"RoofedForest",
"MesaPlateauFM_grasstop",
"ExtremeHillsM",
"BirchForestM",
}, },
9, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

View File

@ -0,0 +1,228 @@
--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_fishing: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)

View File

@ -346,7 +346,7 @@ mcl_mobs:spawn_specific(
"Swampland", "Swampland",
"Swampland_shore" "Swampland_shore"
}, },
0, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
30, 30,
15000, 15000,

View File

@ -33,6 +33,7 @@ mcl_mobs:register_mob("mobs_mc:shulker", {
-- TODO: Make shulker dye-able -- TODO: Make shulker dye-able
visual_size = {x=3, y=3}, visual_size = {x=3, y=3},
walk_chance = 0, walk_chance = 0,
knock_back = false,
jump = false, jump = false,
drops = { drops = {
{name = "mcl_mobitems:shulker_shell", {name = "mcl_mobitems:shulker_shell",

View File

@ -162,7 +162,6 @@ mcl_mobs:spawn_specific(
"Plains", "Plains",
"Desert", "Desert",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -189,7 +188,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",
@ -228,7 +226,6 @@ mcl_mobs:spawn_specific(
"Forest_deep_ocean", "Forest_deep_ocean",
"JungleM_deep_ocean", "JungleM_deep_ocean",
"FlowerForest_deep_ocean", "FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean", "MegaTaiga_ocean",
"StoneBeach_deep_ocean", "StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean", "IcePlainsSpikes_deep_ocean",
@ -238,7 +235,6 @@ mcl_mobs:spawn_specific(
"MesaBryce_deep_ocean", "MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean", "ExtremeHills+_deep_ocean",
"ExtremeHills_ocean", "ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean", "Forest_ocean",
"MegaTaiga_deep_ocean", "MegaTaiga_deep_ocean",
"JungleEdge_ocean", "JungleEdge_ocean",
@ -264,7 +260,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",
@ -302,10 +297,10 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "SoulsandValley",
}, },
0, 0,
7, minetest.LIGHT_MAX+1,
30, 30,
10000, 10000,
3, 3,

View File

@ -101,7 +101,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"SoulsandValley",
}, },
0, 0,
7, 7,

View File

@ -402,7 +402,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"BasaltDelta",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
@ -418,7 +419,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"BasaltDelta",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
@ -433,7 +435,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"BasaltDelta",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
@ -443,11 +446,6 @@ minetest.LIGHT_MAX+1,
mmin, mmin,
mmax) 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 -- 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: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") mcl_mobs:register_egg("mobs_mc:slime_big", S("Slime"), "mobs_mc_spawn_icon_slime.png")

View File

@ -109,7 +109,6 @@ mcl_mobs:spawn_specific(
"Plains", "Plains",
"Desert", "Desert",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -136,7 +135,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",
@ -175,7 +173,6 @@ mcl_mobs:spawn_specific(
"Forest_deep_ocean", "Forest_deep_ocean",
"JungleM_deep_ocean", "JungleM_deep_ocean",
"FlowerForest_deep_ocean", "FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean", "MegaTaiga_ocean",
"StoneBeach_deep_ocean", "StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean", "IcePlainsSpikes_deep_ocean",
@ -185,7 +182,6 @@ mcl_mobs:spawn_specific(
"MesaBryce_deep_ocean", "MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean", "ExtremeHills+_deep_ocean",
"ExtremeHills_ocean", "ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean", "Forest_ocean",
"MegaTaiga_deep_ocean", "MegaTaiga_deep_ocean",
"JungleEdge_ocean", "JungleEdge_ocean",
@ -211,7 +207,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -136,8 +136,7 @@ local professions = {
{ {
{ { "mcl_fishing:fish_raw", 6, 15,}, E1 }, { { "mcl_fishing:fish_raw", 6, 15,}, E1 },
{ { "mcl_fishing:salmon_raw", 6, 6, "mcl_core:emerald", 1, 1 },{ "mcl_fishing:salmon_cooked", 6, 6 } }, { { "mcl_fishing:salmon_raw", 6, 6, "mcl_core:emerald", 1, 1 },{ "mcl_fishing:salmon_cooked", 6, 6 } },
-- FIXME missing campfire { { "mcl_core:emerald", 1, 2 },{"mcl_campfires:campfire_lit",1,1} },
-- {{ "mcl_core:emerald", 1, 2 },{"mcl_campfires:campfire",1,1} },
}, },
{ {
{ { "mcl_fishing:salmon_raw", 6, 13,}, E1 }, { { "mcl_fishing:salmon_raw", 6, 13,}, E1 },
@ -427,7 +426,7 @@ local professions = {
"mobs_mc_villager_weaponsmith.png", "mobs_mc_villager_weaponsmith.png",
"mobs_mc_villager_weaponsmith.png", "mobs_mc_villager_weaponsmith.png",
}, },
jobsite = "mcl_furnaces:furnace", --FIXME: grindstone jobsite = "mcl_grindstone:grindstone",
trades = { trades = {
{ {
{ { "mcl_core:coal_lump", 15, 15 }, E1 }, { { "mcl_core:coal_lump", 15, 15 }, E1 },
@ -458,7 +457,7 @@ local professions = {
"mobs_mc_villager_toolsmith.png", "mobs_mc_villager_toolsmith.png",
"mobs_mc_villager_toolsmith.png", "mobs_mc_villager_toolsmith.png",
}, },
jobsite = "mcl_anvils:anvil", --FIXME: smithing table jobsite = "mcl_smithing_table:table",
trades = { trades = {
{ {
{ { "mcl_core:coal_lump", 15, 15 }, E1 }, { { "mcl_core:coal_lump", 15, 15 }, E1 },
@ -613,6 +612,8 @@ local function employ(self,jobsite_pos)
end end
local function look_for_job(self) local function look_for_job(self)
if self.last_jobhunt and os.time() - self.last_jobhunt < 360 then return end
self.last_jobhunt = os.time() + math.random(0,60)
local p = self.object:get_pos() local p = self.object:get_pos()
local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48),jobsites) local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48),jobsites)
for _,n in pairs(nn) do for _,n in pairs(nn) do
@ -628,14 +629,24 @@ local function look_for_job(self)
end end
local function get_a_job(self) local function get_a_job(self)
if self.child then return end
local p = self.object:get_pos() local p = self.object:get_pos()
local nn = minetest.find_nodes_in_area(vector.offset(p,-8,-8,-8),vector.offset(p,8,8,8),jobsites) local n = minetest.find_node_near(p,1,jobsites)
for _,n in pairs(nn) do if n and employ(self,n) then return true end
if n and employ(self,n) then return true end
end
if self.state ~= "gowp" then look_for_job(self) end if self.state ~= "gowp" then look_for_job(self) end
end end
local function check_jobsite(self)
if self._traded or not self._jobsite then return end
local n = mcl_vars.get_node(self._jobsite)
local m = minetest.get_meta(self._jobsite)
if m:get_string("villager") ~= self._id then
self._profession = "unemployed"
self._trades = nil
set_textures(self)
end
end
local function update_max_tradenum(self) local function update_max_tradenum(self)
if not self._trades then if not self._trades then
return return
@ -724,7 +735,10 @@ local function set_trade(trader, player, inv, concrete_tradenum)
local trade = trades[concrete_tradenum] local trade = trades[concrete_tradenum]
inv:set_stack("wanted", 1, ItemStack(trade.wanted[1])) inv:set_stack("wanted", 1, ItemStack(trade.wanted[1]))
local offered = ItemStack(trade.offered) local offered = ItemStack(trade.offered)
mcl_enchanting.load_enchantments(offered) -- Only load enchantments for enchanted items; fixes unnecessary metadata being applied to regular items from villagers.
if mcl_enchanting.is_enchanted(offered:get_name()) then
mcl_enchanting.load_enchantments(offered)
end
inv:set_stack("offered", 1, offered) inv:set_stack("offered", 1, offered)
if trade.wanted[2] then if trade.wanted[2] then
local wanted2 = ItemStack(trade.wanted[2]) local wanted2 = ItemStack(trade.wanted[2])
@ -982,6 +996,11 @@ local trade_inventory = {
elseif listname == "output" then elseif listname == "output" then
if not trader_exists(player:get_player_name()) then if not trader_exists(player:get_player_name()) then
return 0 return 0
-- Begin Award Code
-- May need to be moved if award gets unlocked in the wrong cases.
elseif trader_exists(player:get_player_name()) then
awards.unlock(player:get_player_name(), "mcl:whatAdeal")
-- End Award Code
end end
-- Only allow taking full stack -- Only allow taking full stack
local count = stack:get_count() local count = stack:get_count()
@ -1094,6 +1113,7 @@ local trade_inventory = {
local trader = player_trading_with[name] local trader = player_trading_with[name]
local tradenum = player_tradenum[name] local tradenum = player_tradenum[name]
local trades local trades
trader._traded = true
if trader and trader._trades then if trader and trader._trades then
trades = minetest.deserialize(trader._trades) trades = minetest.deserialize(trader._trades)
end end
@ -1224,6 +1244,7 @@ mcl_mobs:register_mob("mobs_mc:villager", {
-- TODO: sounds -- TODO: sounds
sounds = { sounds = {
random = "mobs_mc_villager", random = "mobs_mc_villager",
damage = "mobs_mc_villager_hurt",
distance = 10, distance = 10,
}, },
animation = { animation = {
@ -1236,10 +1257,12 @@ mcl_mobs:register_mob("mobs_mc:villager", {
run_speed = 25, run_speed = 25,
run_start = 0, run_start = 0,
run_end = 40, run_end = 40,
die_speed = 15, head_shake_start = 210,
die_start = 210, head_shake_end = 220,
die_end = 220, head_shake_loop = false,
die_loop = false, head_nod_start = 210,
head_nod_end = 220,
head_nod_loop = false,
}, },
follow = pick_up, follow = pick_up,
nofollow = true, nofollow = true,
@ -1261,19 +1284,18 @@ mcl_mobs:register_mob("mobs_mc:villager", {
end end
end end
if clicker then if clicker then
mcl_mobs:feed_tame(self, clicker, 1, true, false) mcl_mobs:feed_tame(self, clicker, 1, true, false, true)
return return
end end
return true --do not pick up return true --do not pick up
end, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
local trg=vector.new(0,9,0)
if self._jobsite then if self._jobsite then
mcl_mobs:gopath(self,self._jobsite,function() mcl_mobs:gopath(self,self._jobsite,function()
--minetest.log("arrived at jobsite") --minetest.log("arrived at jobsite")
end) end)
end end
if self.child or self._profession == "unemployed" then if self.child or self._profession == "unemployed" or self._profession == "nitwit" then
return return
end end
-- Initiate trading -- Initiate trading
@ -1344,20 +1366,24 @@ mcl_mobs:register_mob("mobs_mc:villager", {
end end
if self._profession == "unemployed" then if self._profession == "unemployed" then
get_a_job(self) get_a_job(self)
else
check_jobsite(self)
end end
end end
end, end,
on_spawn = function(self) on_spawn = function(self)
if not self._profession then
self._profession = "unemployed"
if math.random(100) == 1 then
self._profession = "nitwit"
end
end
if self._id then if self._id then
set_textures(self) set_textures(self)
return return
end end
self._id=minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random())) self._id=minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random()))
self._profession = "unemployed"
if math.random(100) == 1 then
self._profession = "nitwit"
end
set_textures(self) set_textures(self)
end, end,
on_die = function(self, pos) on_die = function(self, pos)
@ -1376,7 +1402,8 @@ mcl_mobs:register_mob("mobs_mc:villager", {
}) })
--[[
Villager spawning in mcl_villages
mcl_mobs:spawn_specific( mcl_mobs:spawn_specific(
"mobs_mc:villager", "mobs_mc:villager",
"overworld", "overworld",
@ -1406,6 +1433,6 @@ minetest.LIGHT_MAX+1,
4, 4,
mobs_mc.water_level+1, mobs_mc.water_level+1,
mcl_vars.mg_overworld_max) mcl_vars.mg_overworld_max)
--]]
-- spawn eggs -- spawn eggs
mcl_mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0) mcl_mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0)

View File

@ -29,6 +29,7 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", {
description = S("Zombie Villager"), description = S("Zombie Villager"),
type = "monster", type = "monster",
spawn_class = "hostile", spawn_class = "hostile",
spawn_in_group = 1,
hp_min = 20, hp_min = 20,
hp_max = 20, hp_max = 20,
xp_min = 5, xp_min = 5,
@ -119,20 +120,7 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", {
villager_obj:set_yaw(yaw) villager_obj:set_yaw(yaw)
villager.target_yaw = yaw villager.target_yaw = yaw
villager.nametag = self.nametag villager.nametag = self.nametag
local texture = self.base_texture[1]:gsub("zombie", "villager") villager._profession = "unemployed"
if texture == "mobs_mc_villager_villager.png" then
texture = "mobs_mc_villager.png"
end
local textures = {texture}
villager.base_texture = textures
villager_obj:set_properties({textures = textures})
local matches = {}
for prof, tex in pairs(professions) do
if texture == tex then
table.insert(matches, prof)
end
end
villager._profession = matches[math.random(#matches)]
self._curing = nil self._curing = nil
mcl_burning.extinguish(obj) mcl_burning.extinguish(obj)
obj:remove() obj:remove()
@ -160,7 +148,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",
@ -197,7 +184,6 @@ mcl_mobs:spawn_specific(
"Plains", "Plains",
"Desert", "Desert",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -224,7 +210,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",

View File

@ -18,6 +18,7 @@ local wolf = {
xp_max = 3, xp_max = 3,
passive = false, passive = false,
group_attack = true, group_attack = true,
spawn_in_group = 8,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.84, 0.3}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.84, 0.3},
visual = "mesh", visual = "mesh",
mesh = "mobs_mc_wolf.b3d", mesh = "mobs_mc_wolf.b3d",
@ -232,29 +233,22 @@ dog.on_rightclick = function(self, clicker)
end end
mcl_mobs:register_mob("mobs_mc:dog", dog) mcl_mobs:register_mob("mobs_mc:dog", dog)
-- Spawn -- Spawn
mcl_mobs:spawn_specific( mcl_mobs:spawn_specific(
"mobs_mc:wolf", "mobs_mc:wolf",
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "Taiga",
"Swampland", "MegaSpruceTaiga",
"Taiga", "MegaTaiga",
"ExtremeHills", "Forest",
"BirchForest", "ColdTaiga",
"MegaSpruceTaiga", "FlowerForest_beach",
"MegaTaiga", "Forest_beach",
"ExtremeHills+", "ColdTaiga_beach_water",
"Forest", "Taiga_beach",
"Plains", "ColdTaiga_beach",
"ColdTaiga",
"SunflowerPlains",
"RoofedForest",
"MesaPlateauFM_grasstop",
"ExtremeHillsM",
"BirchForestM",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

View File

@ -162,7 +162,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",
@ -198,7 +197,6 @@ mcl_mobs:spawn_specific(
"Forest", "Forest",
"Plains", "Plains",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -225,7 +223,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",
@ -254,7 +251,6 @@ mcl_mobs:spawn_specific(
"RoofedForest_underground", "RoofedForest_underground",
"Jungle_underground", "Jungle_underground",
"Swampland_underground", "Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground", "BirchForest_underground",
"Plains_underground", "Plains_underground",
"MesaPlateauF_underground", "MesaPlateauF_underground",
@ -290,7 +286,6 @@ mcl_mobs:spawn_specific(
"Forest", "Forest",
"Plains", "Plains",
"ColdTaiga", "ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes", "IcePlainsSpikes",
"SunflowerPlains", "SunflowerPlains",
"IcePlains", "IcePlains",
@ -317,7 +312,6 @@ mcl_mobs:spawn_specific(
"ExtremeHills_beach", "ExtremeHills_beach",
"ColdTaiga_beach", "ColdTaiga_beach",
"Swampland_shore", "Swampland_shore",
"MushroomIslandShore",
"JungleM_shore", "JungleM_shore",
"Jungle_shore", "Jungle_shore",
"MesaPlateauFM_sandlevel", "MesaPlateauFM_sandlevel",

View File

@ -118,7 +118,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"CrimsonForest",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,
@ -133,7 +134,8 @@ mcl_mobs:spawn_specific(
"nether", "nether",
"ground", "ground",
{ {
"Nether" "Nether",
"CrimsonForest",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

View File

@ -238,8 +238,8 @@ after(5, function(dtime)
end) end)
minetest.register_chatcommand("lightning", { minetest.register_chatcommand("lightning", {
params = "[<X> <Y> <Z>]", params = "[<X> <Y> <Z> | <player name>]",
description = S("Let lightning strike at the specified position or yourself"), description = S("Let lightning strike at the specified position or player. No parameter will strike yourself."),
privs = { maphack = true }, privs = { maphack = true },
func = function(name, param) func = function(name, param)
local pos = {} local pos = {}
@ -247,21 +247,21 @@ minetest.register_chatcommand("lightning", {
pos.x = tonumber(pos.x) pos.x = tonumber(pos.x)
pos.y = tonumber(pos.y) pos.y = tonumber(pos.y)
pos.z = tonumber(pos.z) pos.z = tonumber(pos.z)
local player_to_strike
if not (pos.x and pos.y and pos.z) then if not (pos.x and pos.y and pos.z) then
pos = nil pos = nil
player_to_strike = minetest.get_player_by_name(param)
if not player_to_strike and param == "" then
player_to_strike = minetest.get_player_by_name(name)
end
end end
if name == "" and pos == nil then if not player_to_strike and pos == nil then
return false, "No position specified and unknown player" return false, "No position specified and unknown player"
end end
if pos then if pos then
lightning.strike(pos) lightning.strike(pos)
else elseif player_to_strike then
local player = minetest.get_player_by_name(name) lightning.strike(player_to_strike:get_pos())
if player then
lightning.strike(player:get_pos())
else
return false, S("No position specified and unknown player")
end
end end
return true return true
end, end,

View File

@ -1,4 +1,3 @@
# textdomain: lightning # textdomain: lightning
@1 was struck by lightning.= Let lightning strike at the specified position or player. No parameter will strike yourself.=
Let lightning strike at the specified position or yourself=
No position specified and unknown player= No position specified and unknown player=

View File

@ -1,8 +1,10 @@
mcl_weather.nether_dust = {} mcl_weather.nether_dust = {}
mcl_weather.nether_dust.particlespawners = {} mcl_weather.nether_dust.particlespawners = {}
local PARTICLES_COUNT_NETHER_DUST = tonumber(minetest.settings:get("mcl_weather_dust_particles")) or 150
local psdef= { local psdef= {
amount = 150, amount = PARTICLES_COUNT_NETHER_DUST,
time = 0, time = 0,
minpos = vector.new(-15,-15,-15), minpos = vector.new(-15,-15,-15),
maxpos =vector.new(15,15,15), maxpos =vector.new(15,15,15),

View File

@ -1,5 +1,5 @@
local PARTICLES_COUNT_RAIN = 800 local PARTICLES_COUNT_RAIN = tonumber(minetest.settings:get("mcl_weather_rain_particles")) or 500
local PARTICLES_COUNT_THUNDER = 1200 local PARTICLES_COUNT_THUNDER = tonumber(minetest.settings:get("mcl_weather_thunder_particles")) or 900
local get_connected_players = minetest.get_connected_players local get_connected_players = minetest.get_connected_players
@ -20,22 +20,20 @@ mcl_weather.rain = {
init_done = false, init_done = false,
} }
local update_sound={} local update_sound={}
local vel=math.random(0,3)
local falling_speed=math.random(10,15)
local size = math.random(1,3)
local psdef= { local psdef= {
amount = mcl_weather.rain.particles_count, amount = mcl_weather.rain.particles_count,
time=0, time=0,
minpos = vector.new(-15,20,-15), minpos = vector.new(-15,20,-15),
maxpos = vector.new(15,25,15), maxpos = vector.new(15,25,15),
minvel = vector.new(-2,-falling_speed-2,-2), minvel = vector.new(-2,-17,-2),
maxvel = vector.new(2,-falling_speed+2,2), maxvel = vector.new(2,-8,2),
minacc = vector.new(0,0,0), minacc = vector.new(0,0,0),
maxacc = vector.new(0,-0.5,0), maxacc = vector.new(0,-0.5,0),
minexptime = 15, minexptime = 1,
maxexptime = 30, maxexptime = 4,
minsize = size, minsize = 4,
maxsize= size*2, maxsize= 8,
collisiondetection = true, collisiondetection = true,
collision_removal = true, collision_removal = true,
vertical = true, vertical = true,
@ -70,9 +68,10 @@ end
-- no no no NO NO f*.. no. no manual particle creatin' PLS!! this sends EVERY particle over the net. -- no no no NO NO f*.. no. no manual particle creatin' PLS!! this sends EVERY particle over the net.
function mcl_weather.rain.add_rain_particles(player) function mcl_weather.rain.add_rain_particles(player)
mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count
local l = false
for k,v in pairs(textures) do for k,v in pairs(textures) do
psdef.texture=v psdef.texture=v
mcl_weather.add_spawner_player(player,"rain"..k,psdef) l = l or mcl_weather.add_spawner_player(player,"rain"..k,psdef)
end end
if l then if l then
update_sound[player:get_player_name()]=true update_sound[player:get_player_name()]=true

View File

@ -146,8 +146,25 @@ mcl_weather.skycolor = {
player:set_stars({visible = false}) player:set_stars({visible = false})
mcl_weather.skycolor.override_day_night_ratio(player, 0.5) mcl_weather.skycolor.override_day_night_ratio(player, 0.5)
elseif dim == "nether" then elseif dim == "nether" then
player:set_sky({ type = "plain", local nether_sky = {
base_color = "#300808", Nether = "#300808",
BasaltDelta = "#685F70",
SoulsandValley = "#1B4745",
CrimsonForest = "#330303",
WarpedForest = "#1A051A"
}
local biometint = nether_sky[minetest.get_biome_name(minetest.get_biome_data(player:get_pos()).biome)]
player:set_sky({
type = "regular",
sky_color = {
day_sky = "#300808",
day_horizon = biometint,
dawn_sky = "#300808",
dawn_horizon = biometint,
night_sky = "#300808",
night_horizon = biometint,
},
clouds = false, clouds = false,
}) })
player:set_sun({visible = false , sunrise_visible = false}) player:set_sun({visible = false , sunrise_visible = false})

View File

@ -2,11 +2,11 @@ local get_connected_players = minetest.get_connected_players
mcl_weather.snow = {} mcl_weather.snow = {}
mcl_weather.snow.particles_count = 15 local PARTICLES_COUNT_SNOW = tonumber(minetest.settings:get("mcl_weather_snow_particles")) or 100
mcl_weather.snow.init_done = false mcl_weather.snow.init_done = false
local psdef= { local psdef= {
amount = 99, amount = PARTICLES_COUNT_SNOW,
time = 0, --stay on til we turn it off time = 0, --stay on til we turn it off
minpos = vector.new(-25,20,-25), minpos = vector.new(-25,20,-25),
maxpos =vector.new(25,25,25), maxpos =vector.new(25,25,25),
@ -14,9 +14,9 @@ local psdef= {
maxvel = vector.new(0.2,-4,0.2), maxvel = vector.new(0.2,-4,0.2),
minacc = vector.new(0,-1,0), minacc = vector.new(0,-1,0),
maxacc = vector.new(0,-4,0), maxacc = vector.new(0,-4,0),
minexptime = 15, minexptime = 3,
maxexptime = 30, maxexptime = 5,
minsize = 0.5, minsize = 2,
maxsize = 5, maxsize = 5,
collisiondetection = true, collisiondetection = true,
collision_removal = true, collision_removal = true,

View File

@ -101,6 +101,17 @@ awards.register_achievement("mcl:bookcase", {
} }
}) })
awards.register_achievement("mcl:buildIronPickaxe", {
title = S("Isn't It Iron Pick"),
description = S("Craft a iron pickaxe using sticks and iron."),
icon = "default_tool_steelpick.png",
trigger = {
type = "craft",
item = "mcl_tools:pick_iron",
target = 1
}
})
-- Item pickup achievements: These are awarded when picking up a certain item. -- Item pickup achievements: These are awarded when picking up a certain item.
-- The achivements are manually given in the mod mcl_item_entity. -- The achivements are manually given in the mod mcl_item_entity.
awards.register_achievement("mcl:diamonds", { awards.register_achievement("mcl:diamonds", {
@ -125,6 +136,18 @@ awards.register_achievement("mcl:mineWood", {
icon = "default_tree.png", icon = "default_tree.png",
}) })
awards.register_achievement("mcl:whosCuttingOnions", {
title = S("Who is Cutting Onions?"),
description = S("Pick up a crying obsidian from the floor."),
icon = "default_obsidian.png^mcl_core_crying_obsidian.png",
})
awards.register_achievement("mcl:hiddenInTheDepths", {
title = S("Hidden in the Depths"),
description = S("Pick up an Ancient Debris from the floor."),
icon = "mcl_nether_ancient_debris_side.png",
})
-- Smelting achivements: These are awarded when picking up an item from a furnace -- Smelting achivements: These are awarded when picking up an item from a furnace
-- output. They are given in mcl_furnaces. -- output. They are given in mcl_furnaces.
awards.register_achievement("mcl:acquireIron", { awards.register_achievement("mcl:acquireIron", {
@ -158,9 +181,89 @@ awards.register_achievement("mcl:snipeSkeleton", {
-- Triggered in mcl_portals -- Triggered in mcl_portals
awards.register_achievement("mcl:buildNetherPortal", { awards.register_achievement("mcl:buildNetherPortal", {
title = S("Into the Nether"), title = S("We Need to Go Deeper"),
description = S("Use obsidian and a fire starter to construct a Nether portal."), description = S("Use obsidian and a fire starter to construct a Nether portal."),
icon = "default_obsidian.png", icon = "mcl_fire_flint_and_steel.png",
})
awards.register_achievement("mcl:enterEndPortal", {
title = S("The End?"),
description = S("Or the beginning?\nHint: Enter an end portal."),
icon = "mcl_end_end_stone.png",
})
awards.register_achievement("mcl:theNether", {
title = S("The Nether"),
description = S("Bring summer clothes.\nHint: Enter the Nether."),
icon = "mcl_nether_netherrack.png",
})
-- Triggered in mcl_totems
awards.register_achievement("mcl:postMortal", {
title = S("Postmortal"),
description = S("Use a Totem of Undying to cheat death."),
icon = "mcl_totems_totem.png",
})
-- Triggered in mcl_beds
awards.register_achievement("mcl:sweetDreams", {
title = S("Sweet Dreams"),
description = S("Sleep in a bed to change your respawn point."),
icon = "mcl_beds_bed_red.png",
})
awards.register_achievement("mcl:notQuiteNineLives", {
title = S('Not Quite "Nine" Lives'),
description = S("Charge a Respawn Anchor to the maximum."),
icon = "respawn_anchor_side4.png",
})
-- Triggered in mobs_mc
awards.register_achievement("mcl:whatAdeal", {
title = S("What A Deal!"),
description = S("Successfully trade with a Villager."),
icon = "mcl_core_emerald.png",
})
awards.register_achievement("mcl:tacticalFishing", {
title = S("Tactical Fishing"),
description = S("Catch a fish... without a fishing rod!"),
icon = "pufferfish_bucket.png",
})
-- Triggered in mcl_fishing
awards.register_achievement("mcl:fishyBusiness", {
title = S("Fishy Business"),
description = S("Catch a fish.\nHint: Catch a fish, salmon, clownfish, or pufferfish."),
icon = "mcl_fishing_fishing_rod.png",
})
-- Triggered in mcl_compass
awards.register_achievement("mcl:countryLode", {
title = S("Country Lode,\nTake Me Home"),
description = S("Use a compass on a Lodestone."),
icon = "lodestone_side4.png",
})
-- Triggered in mcl_smithing_table
awards.register_achievement("mcl:seriousDedication", {
title = S("Serious Dedication"),
description = S("Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices."),
icon = "farming_tool_netheritehoe.png",
})
-- Triggered in mcl_brewing
awards.register_achievement("mcl:localBrewery", {
title = S("Local Brewery"),
description = S("Brew a Potion.\nHint: Take a potion or glass bottle out of the brewing stand."),
icon = "mcl_potions_potion_overlay.png^[colorize:#F82423:"..tostring(127).."^mcl_potions_potion_bottle.png",
})
-- Triggered in mcl_enchanting
awards.register_achievement("mcl:enchanter", {
title = S("Enchanter"),
description = S("Enchant an item using an Enchantment Table."),
icon = "mcl_enchanting_book_enchanted.png",
}) })
-- NON-PC ACHIEVEMENTS (XBox, Pocket Edition, etc.) -- NON-PC ACHIEVEMENTS (XBox, Pocket Edition, etc.)

View File

@ -19,7 +19,7 @@ Getting an Upgrade=
Hit a skeleton, wither skeleton or stray by bow and arrow from a distance of at least 20 meters.= Hit a skeleton, wither skeleton or stray by bow and arrow from a distance of at least 20 meters.=
Hot Topic= Hot Topic=
Into Fire= Into Fire=
Into the Nether= We Need to Go Deeper=
Iron Belly= Iron Belly=
Librarian= Librarian=
Mine emerald ore.= Mine emerald ore.=
@ -47,3 +47,29 @@ Use a crafting table to craft a wooden hoe from wooden planks and sticks.=
Use a crafting table to craft a wooden pickaxe from wooden planks and sticks.= Use a crafting table to craft a wooden pickaxe from wooden planks and sticks.=
Use obsidian and a fire starter to construct a Nether portal.= Use obsidian and a fire starter to construct a Nether portal.=
Use wheat to craft a bread.= Use wheat to craft a bread.=
Who is Cutting Onions?=
Pick up a crying obsidian from the floor.=
Hidden in the Depths=
Pick up an Ancient Debris from the floor.=
The Nether=
Bring summer clothes.@nHint: Enter the Nether.=
Isn't It Iron Pick=
Craft a iron pickaxe using sticks and iron.=
Postmortal=
Use a Totem of Undying to cheat death.=
Sweet Dreams=
Sleep in a bed to change your respawn point.=
Not Quite "Nine" Lives=
Charge a Respawn Anchor to the maximum.=
What A Deal!=
Successfully trade with a Villager.=
Fishy Business=
Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=
Country Lode,@nTake Me Home=
Use a compass on a Lodestone.=
Serious Dedication=
Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices.=
Local Brewery=
Brew a Potion.@nHint: Take a potion or glass bottle out of the brewing stand.=
Enchanter=
Enchant an item using an Enchantment Table.=

18
mods/HUD/mcl_info/API.md Normal file
View File

@ -0,0 +1,18 @@
## mcl_info
An api to make custom entries in the mcl2 debug hud.
### mcl_info.register_debug_field(name,defintion)
Debug field defintion example:
{
level = 3,
--show with debug level 3 and upwards
func = function(player,pos) return minetest.pos_to_string(pos) end,
-- Function that is run for at each debug
-- sample (default: every .63 seconds)
-- It should output a string and determines
-- the content of the debug field.
}
### mcl_info.registered_debug_fields
Table the debug definitions are stored in. Do not modify this directly. If you need to overwrite a field just set it again with mcl_info.register_debug_field().

161
mods/HUD/mcl_info/init.lua Normal file
View File

@ -0,0 +1,161 @@
mcl_info = {}
local refresh_interval = .63
local huds = {}
local default_debug = 0
local after = minetest.after
local get_connected_players = minetest.get_connected_players
local get_biome_name = minetest.get_biome_name
local get_biome_data = minetest.get_biome_data
local format = string.format
local min1, min2, min3 = mcl_vars.mg_overworld_min, mcl_vars.mg_end_min, mcl_vars.mg_nether_min
local max1, max2, max3 = mcl_vars.mg_overworld_max, mcl_vars.mg_end_max, mcl_vars.mg_nether_max + 128
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local storage = minetest.get_mod_storage()
local player_dbg = {}
local function check_setting(s)
return s
end
--return player setting, set it to 2nd argument if supplied
local function player_setting(p,s)
local name = p:get_player_name()
if check_setting(s) then
p:get_meta():set_string("mcl_info_show",s)
player_dbg[name] = tonumber(s)
end
if not player_dbg[name] then
local r = p:get_meta():get_string("mcl_info_show")
if r == nil or r == "" then r = 0 end
player_dbg[name] = tonumber(r)
end
return player_dbg[name]
end
mcl_info.registered_debug_fields = {}
local fields_keyset = {}
function mcl_info.register_debug_field(name,def)
table.insert(fields_keyset,name)
mcl_info.registered_debug_fields[name]=def
end
local function nodeinfo(pos)
local n = minetest.get_node_or_nil(pos)
if not n then return "" end
local l = minetest.get_node_light(pos)
local ld = minetest.get_node_light(pos,0.5)
local r = n.name .. " p1:"..n.param1.." p2:"..n.param2
if l and ld then
r = r .. " Light: "..l.."/"..ld
end
return r
end
local function get_text(player, bits)
local pos = vector.offset(player:get_pos(),0,0.5,0)
local bits = bits
if bits == 0 then return "" end
local r = ""
for _,key in ipairs(fields_keyset) do
local def = mcl_info.registered_debug_fields[key]
if def.level == nil or def.level <= bits then
r = r ..key..": "..tostring(def.func(player,pos)).."\n"
end
end
return r
end
local function info()
for _, player in pairs(get_connected_players()) do
local name = player:get_player_name()
local s = player_setting(player)
local pos = player:get_pos()
local text = get_text(player, s)
local hud = huds[name]
if s and not hud then
local def = {
hud_elem_type = "text",
alignment = {x = 1, y = -1},
scale = {x = 100, y = 100},
position = {x = 0.0073, y = 0.889},
text = text,
style = 5,
["number"] = 0xcccac0,
z_index = 0,
}
local def_bg = table.copy(def)
def_bg.offset = {x = 2, y = 1}
def_bg["number"] = 0
def_bg.z_index = -1
huds[name] = {
player:hud_add(def),
player:hud_add(def_bg),
text,
}
elseif text ~= hud[3] then
hud[3] = text
player:hud_change(huds[name][1], "text", text)
player:hud_change(huds[name][2], "text", text)
end
end
after(refresh_interval, info)
end
info()
minetest.register_on_leaveplayer(function(p)
local name = p:get_player_name()
huds[name] = nil
player_dbg[name] = nil
end)
minetest.register_chatcommand("debug",{
description = S("Set debug bit mask: 0 = disable, 1 = biome name, 2 = coordinates, 3 = all"),
params = S("<bitmask>"),
privs = { debug = true },
func = function(name, params)
local player = minetest.get_player_by_name(name)
if params == "" then return true, "Debug bitmask is "..player_setting(player) end
local dbg = math.floor(tonumber(params) or default_debug)
if dbg < 0 or dbg > 4 then
minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 4))
return false,"Current bitmask: "..player_setting(player)
end
return true, "Debug bit mask set to "..player_setting(player,dbg)
end
})
mcl_info.register_debug_field("Node feet",{
level = 4,
func = function(pl,pos)
return nodeinfo(pos)
end
})
mcl_info.register_debug_field("Node below",{
level = 4,
func = function(pl,pos)
return nodeinfo(vector.offset(pos,0,-1,0))
end
})
mcl_info.register_debug_field("Biome",{
level = 3,
func = function(pl,pos)
local biome_data = get_biome_data(pos)
local biome = biome_data and get_biome_name(biome_data.biome) or "No biome"
if biome_data then
return format("%s (%s), Humidity: %.1f, Temperature: %.1f",biome, biome_data.biome, biome_data.humidity, biome_data.heat)
end
return "No biome"
end
})
mcl_info.register_debug_field("Coords",{
level = 2,
func = function(pl,pos)
return format("x:%.1f y:%.1f z:%.1f", pos.x, pos.y, pos.z)
end
})

View File

@ -0,0 +1,4 @@
# textdomain: mcl_info
Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 3 @= all=Установка отладочной битовой маски: 0 @= отключить, 1 @= биом, 2 @= координаты, 3 @= всё
Error! Possible values are integer numbers from @1 to @2=Ошибка! Допустимые значения - целые числа от @1 до @2
Debug bit mask set to @1=Отладочной битовой маске присвоено значение @1

View File

@ -0,0 +1,4 @@
# textdomain: mcl_info
Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 3 @= all=
Error! Possible values are integer numbers from @1 to @2=
Debug bit mask set to @1=

View File

@ -0,0 +1,3 @@
name = mcl_info
description = Prints biome name and player position
depends = mcl_init

View File

@ -59,8 +59,9 @@ minetest.register_globalstep(function(dtime)
local itemstack = mcl_offhand.get_offhand(player) local itemstack = mcl_offhand.get_offhand(player)
local offhand_item = itemstack:get_name() local offhand_item = itemstack:get_name()
local offhand_hud = mcl_offhand[player].hud local offhand_hud = mcl_offhand[player].hud
if offhand_item ~= "" then local item = minetest.registered_items[offhand_item]
local item_texture = minetest.registered_items[offhand_item].inventory_image .. "^[resize:" .. max_offhand_px .. "x" .. max_offhand_px if offhand_item ~= "" and item then
local item_texture = item.inventory_image .. "^[resize:" .. max_offhand_px .. "x" .. max_offhand_px
local position = {x = 0.5, y = 1} local position = {x = 0.5, y = 1}
local offset = {x = -320, y = -32} local offset = {x = -320, y = -32}

View File

@ -1,3 +1,4 @@
local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
local table = table local table = table
--register stoppers for movestones/pistons --register stoppers for movestones/pistons
@ -328,17 +329,17 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
-- Move object at tip of stack, pushpos is position at tip of stack -- Move object at tip of stack, pushpos is position at tip of stack
local pushpos = vector.add(pos, vector.multiply(dir, #nodestack)) local pushpos = vector.add(pos, vector.multiply(dir, #nodestack))
local objects = minetest.get_objects_inside_radius(pushpos, 1) local objects = minetest.get_objects_inside_radius(pushpos, 1.15)
for _, obj in ipairs(objects) do for _, obj in ipairs(objects) do
table.insert(objects_to_move, obj) table.insert(objects_to_move, obj)
end end
-- Move objects lying/standing on the stack (before it was pushed - oldstack) -- Move objects lying/standing on the stack (before it was pushed - oldstack)
if tonumber(minetest.settings:get("movement_gravity")) > 0 and dir.y == 0 then if GRAVITY > 0 then
-- If gravity positive and dir horizontal, push players standing on the stack -- If gravity positive and dir horizontal, push players standing on the stack
for _, n in ipairs(nodestack) do for _, n in ipairs(nodestack) do
local p_above = vector.add(n.pos, {x=0, y=1, z=0}) local p_above = vector.add(n.pos, {x=0, y=1, z=0})
local objects = minetest.get_objects_inside_radius(p_above, 1) local objects = minetest.get_objects_inside_radius(p_above, 1.15)
for _, obj in ipairs(objects) do for _, obj in ipairs(objects) do
table.insert(objects_to_move, obj) table.insert(objects_to_move, obj)
end end
@ -347,7 +348,10 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
for _, obj in ipairs(objects_to_move) do for _, obj in ipairs(objects_to_move) do
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
if not entity or not mesecon.is_mvps_unmov(entity.name) then local player = obj:is_player()
if not entity or not player and not mesecon.is_mvps_unmov(entity.name) then
local np = vector.add(obj:get_pos(), dir) local np = vector.add(obj:get_pos(), dir)
--move only if destination is not solid --move only if destination is not solid
@ -355,6 +359,30 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
if not ((not minetest.registered_nodes[nn.name]) if not ((not minetest.registered_nodes[nn.name])
or minetest.registered_nodes[nn.name].walkable) then or minetest.registered_nodes[nn.name].walkable) then
obj:set_pos(np) obj:set_pos(np)
-- Launch Player, TNT & mobs like in Minecraft
-- Only doing so if slimeblock is attached.
for _, r in ipairs(mesecon.rules.alldirs) do
local adjpos = vector.add(np, r)
local adjnode = minetest.get_node(adjpos)
if minetest.registered_nodes[adjnode.name] and minetest.registered_nodes[adjnode.name].mvps_sticky then
local np = vector.add(obj:get_pos(), dir)
-- Reset acceleration of all objects before launching.
-- Fixes eggs, & snowballs thrown by dispensers
obj:set_acceleration({x=dir.x, y=-GRAVITY, z=dir.z})
--Need to set velocities differently for players, items & mobs/tnt, and falling anvils.
if player then
obj:add_velocity({x = dir.x * 10, y = dir.y * 13, z = dir.z * 10})
elseif entity.name == "__builtin:item" then
obj:add_velocity({x = dir.x * 9, y = dir.y * 11, z = dir.z * 9})
elseif entity.name == "__builtin:falling_node" then
obj:add_velocity({x = dir.x * 43, y = dir.y * 72, z = dir.z * 43})
else
obj:add_velocity({x = dir.x * 6, y = dir.y * 9, z = dir.z * 6})
end
end
end
end end
end end
end end

View File

@ -117,7 +117,6 @@ for _, def in pairs(bud_def) do
walkable = false, walkable = false,
light_source = def.light_source, light_source = def.light_source,
groups = { groups = {
dig_by_water = 1,
destroy_by_lava_flow = 1, destroy_by_lava_flow = 1,
dig_by_piston = 1, dig_by_piston = 1,
pickaxey = 1, pickaxey = 1,
@ -162,7 +161,6 @@ minetest.register_node("mcl_amethyst:amethyst_cluster",{
walkable = false, walkable = false,
light_source = 7, light_source = 7,
groups = { groups = {
dig_by_water = 1,
destroy_by_lava_flow = 1, destroy_by_lava_flow = 1,
dig_by_piston = 1, dig_by_piston = 1,
pickaxey = 1, pickaxey = 1,

View File

@ -84,6 +84,19 @@ local function distinguish_tool_and_material(input1, input2)
end end
end end
-- Helper function to make sure update_anvil_slots NEVER overstacks the output slot
local function fix_stack_size(stack)
if not stack or stack == "" then return "" end
local count = stack:get_count()
local max_count = stack:get_stack_max()
if count > max_count then
stack:set_count(max_count)
count = max_count
end
return count
end
-- Update the inventory slots of an anvil node. -- Update the inventory slots of an anvil node.
-- meta: Metadata of anvil node -- meta: Metadata of anvil node
local function update_anvil_slots(meta) local function update_anvil_slots(meta)
@ -213,6 +226,7 @@ local function update_anvil_slots(meta)
-- Set the new output slot -- Set the new output slot
if new_output then if new_output then
fix_stack_size(new_output)
inv:set_stack("output", 1, new_output) inv:set_stack("output", 1, new_output)
end end
end end

View File

@ -114,6 +114,10 @@ function mcl_armor.register_set(def)
for k, v in pairs(element_groups) do for k, v in pairs(element_groups) do
groups[k] = v groups[k] = v
end end
local upgrade_item = nil
if def._mcl_upgradable and def._mcl_upgrade_item_material then
upgrade_item = itemstring:gsub("_[%l%d]*$",def._mcl_upgrade_item_material)
end
minetest.register_tool(itemstring, { minetest.register_tool(itemstring, {
description = S(def.description .. " " .. (descriptions[name] or element.description)), description = S(def.description .. " " .. (descriptions[name] or element.description)),
@ -133,6 +137,8 @@ function mcl_armor.register_set(def)
_on_break = on_break_callbacks[name] or def.on_break, _on_break = on_break_callbacks[name] or def.on_break,
_mcl_armor_element = name, _mcl_armor_element = name,
_mcl_armor_texture = textures[name] or modname .. "_" .. itemname .. ".png", _mcl_armor_texture = textures[name] or modname .. "_" .. itemname .. ".png",
_mcl_upgradable = def._mcl_upgradable,
_mcl_upgrade_item = upgrade_item
}) })
if def.craft_material then if def.craft_material then

View File

@ -49,6 +49,8 @@ mcl_armor.register_set({
}, },
repair_material = "mcl_core:iron_ingot", repair_material = "mcl_core:iron_ingot",
cook_material = "mcl_core:iron_nugget", cook_material = "mcl_core:iron_nugget",
sound_equip = "mcl_armor_equip_iron",
sound_unequip = "mcl_armor_unequip_iron",
}) })
mcl_armor.register_set({ mcl_armor.register_set({
@ -64,6 +66,8 @@ mcl_armor.register_set({
}, },
craft_material = "mcl_core:iron_ingot", craft_material = "mcl_core:iron_ingot",
cook_material = "mcl_core:iron_nugget", cook_material = "mcl_core:iron_nugget",
sound_equip = "mcl_armor_equip_iron",
sound_unequip = "mcl_armor_unequip_iron",
}) })
mcl_armor.register_set({ mcl_armor.register_set({
@ -79,6 +83,27 @@ mcl_armor.register_set({
}, },
toughness = 2, toughness = 2,
craft_material = "mcl_core:diamond", craft_material = "mcl_core:diamond",
sound_equip = "mcl_armor_equip_diamond",
sound_unequip = "mcl_armor_unequip_diamond",
_mcl_upgradable = true,
_mcl_upgrade_item_material = "_netherite",
})
mcl_armor.register_set({
name = "netherite",
description = "Netherite",
durability = 555,
enchantability = 10,
points = {
head = 3,
torso = 8,
legs = 6,
feet = 3,
},
toughness = 2,
craft_material = "mcl_nether:netherite_ingot",
sound_equip = "mcl_armor_equip_diamond",
sound_unequip = "mcl_armor_unequip_diamond",
}) })
mcl_armor.register_protection_enchantment({ mcl_armor.register_protection_enchantment({

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

View File

@ -0,0 +1,215 @@
--[[
there are strings in meta, which are being used to see which effect will be given to the player(s)
Valid strings:
swiftness
leaping
strenght
regeneration
]]--
--TODO: add beacon beam
--TODO: beacons should only work when there are no blocks (few exceptions) above them!
--TODO: add translation
local formspec_string=
"size[11,14]"..
"label[4.5,0.5;Beacon:]"..
"label[0.5,1;Primary Power:]"..
"label[0.5,8.25;Inventory:]"..
"image[1,1.5;1,1;custom_beacom_symbol_4.png]"..
"image[1,3;1,1;custom_beacom_symbol_3.png]"..
"image[1,4.5;1,1;custom_beacom_symbol_2.png]"..
"image[1,6;1,1;custom_beacom_symbol_1.png]"..
"image_button[5.2,1.5;1,1;mcl_potions_effect_swift.png;swiftness;]"..
"image_button[5.2,3;1,1;mcl_potions_effect_leaping.png;leaping;]"..
"image_button[5.2,4.5;1,1;mcl_potions_effect_strong.png;strenght;]"..
"image_button[5.2,6;1,1;mcl_potions_effect_regenerating.png;regeneration;]"..
"item_image[1,7;1,1;mcl_core:diamond]"..
"item_image[2.2,7;1,1;mcl_core:emerald]"..
"item_image[3.4,7;1,1;mcl_core:iron_ingot]"..
"item_image[4.6,7;1,1;mcl_core:gold_ingot]"..
mcl_formspec.get_itemslot_bg(6,7,1,1)..
"list[context;input;6,7;1,1;]"..
mcl_formspec.get_itemslot_bg(1,9,9,3)..
"list[current_player;main;1,9;9,3;9]"..
mcl_formspec.get_itemslot_bg(1,12.5,9,1)..
"list[current_player;main;1,12.5;9,1;]"
local function beacon_blockcheck(pos)
for y_offset = 1,4 do
local block_y = pos.y - y_offset
for block_x = (pos.x-y_offset),(pos.x+y_offset) do
for block_z = (pos.z-y_offset),(pos.z+y_offset) do
local valid_block = false --boolean to which stores if block is valid or not
for _, beacon_block in pairs(beacon_blocklist) do
if beacon_block == minetest.get_node({x=block_x,y=block_y,z=block_z}).name and not valid_block then --is the block in the pyramid a valid beacon block
valid_block =true
end
end
if not valid_block then
return y_offset -1 --the last layer is complete, this one is missing or incomplete
end
end
end
if y_offset == 4 then --all checks are done, beacon is maxed
return y_offset
end
end
end
minetest.register_node("mcl_beacons:beacon", {
--glasslike drawtype?
description = "Beacon",
tiles = {
"beacon_top.png",
"beacon_bottom.png",
"beacon_side_1.png",
"beacon_side_2.png",
"beacon_side_3.png",
"beacon_side_4.png"
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("input", 1)
local form = formspec_string
meta:set_string("formspec", form)
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.swiftness or fields.regeneration or fields.leaping or fields.strenght then
local sender_name = sender:get_player_name()
local power_level = beacon_blockcheck(pos)
if minetest.is_protected(pos, sender_name) then
minetest.record_protection_violation(pos, sender_name)
return
elseif power_level == 0 then
return
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local input = inv:get_stack("input",1)
if input:is_empty() then
return
end
local valid_item = false
for _, item in ipairs(beacon_fuellist) do
if input:get_name() == item then
valid_item = true
end
end
if valid_item ~= true then
return
end
local successful = false
if fields.swiftness then
if power_level == 4 then
minetest.get_meta(pos):set_int("effect_level",2)
else
minetest.get_meta(pos):set_int("effect_level",1)
end
minetest.get_meta(pos):set_string("effect","swiftness")
successful = true
elseif fields.leaping and power_level >= 2 then
if power_level == 4 then
minetest.get_meta(pos):set_int("effect_level",2)
else
minetest.get_meta(pos):set_int("effect_level",1)
end
minetest.get_meta(pos):set_string("effect","leaping")
successful = true
elseif fields.strenght and power_level >= 3 then
if power_level == 4 then
minetest.get_meta(pos):set_int("effect_level",2)
else
minetest.get_meta(pos):set_int("effect_level",1)
end
minetest.get_meta(pos):set_string("effect","strenght")
successful = true
elseif fields.regeneration and power_level == 4 then
minetest.get_meta(pos):set_int("effect_level",2)
minetest.get_meta(pos):set_string("effect","regeneration")
successful = true
end
if successful then
input:take_item()
inv:set_stack("input",1,input)
end
end
end,
light_source = 15,
sounds = mcl_sounds.node_sound_glass_defaults(),
})
mesecon.register_mvps_stopper("mcl_beacons:beacon")
mcl_wip.register_wip_item("mcl_beacons:beacon")
beacon_blocklist = {"mcl_core:diamondblock","mcl_core:ironblock","mcl_core:goldblock","mcl_core:emeraldblock"}--this is supposed to be a global, don't change that! || TODO: add netherite blocks once implemented!
beacon_fuellist ={"mcl_core:diamond","mcl_core:emerald","mcl_core:iron_ingot","mcl_core:gold_ingot"}
function register_beaconblock (itemstring)--API function for other mods
table.insert(beacon_blocklist, itemstring)
end
function register_beaconfuel(itemstring)
table.insert(beacon_fuellist, itemstring)
end
local function effect_player(effect,pos,power_level, effect_level)
local all_objects = minetest.get_objects_inside_radius(pos, (power_level+1)*10)
for _,obj2 in ipairs(all_objects) do
if obj2:is_player() then
if effect == "swiftness" then
mcl_potions.swiftness_func(obj2,effect_level,16)
return
elseif effect == "leaping" then
mcl_potions.leaping_func(obj2, effect_level, 16)
return
elseif effect == "strenght" then
mcl_potions.strength_func(obj2, effect_level, 16)
return
elseif effect == "regeneration" then
mcl_potions.regeneration_func(obj2, effect_level, 16)
return
end
end
end
end
local function abm_function(pos)
local power_level = beacon_blockcheck(pos)
local meta = minetest.get_meta(pos)
local effect_string = meta:get_string("effect")
if meta:get_int("effect_level") == 2 and power_level < 4 then
return
else
effect_player(effect_string,pos,power_level,meta:get_int("effect_level"))
end
end
minetest.register_abm{
label = "beacon check & apply effect(s)",
nodenames = {"mcl_beacons:beacon"},
interval = 5,
chance = 1,
action = abm_function,
}

View File

@ -0,0 +1,2 @@
author=chmodsayshello
depends=mcl_formspec, mcl_init, mcl_wip, mesecons_mvps, mcl_core, mcl_sounds

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Some files were not shown because too many files have changed in this diff Show More