merge beacon-branch into fork beacon branch #7
2
API.md
|
@ -42,7 +42,7 @@ A lot of things are possible by using one of the APIs in the mods. Note that not
|
|||
* Buckets: `ITEMS/mcl_buckets`
|
||||
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
|
||||
|
||||
## Mobs
|
||||
### Mobs
|
||||
* Mobs: `ENTITIES/mcl_mobs`
|
||||
|
||||
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.
|
||||
|
|
16
CREDITS.md
|
@ -27,6 +27,10 @@
|
|||
* Code-Sploit
|
||||
* NO11
|
||||
* kabou
|
||||
* rudzik8
|
||||
* chmodsayshello
|
||||
* PrarieWind
|
||||
* RandomLegoBrick
|
||||
|
||||
## Contributors
|
||||
* Laurent Rocher
|
||||
|
@ -71,6 +75,10 @@
|
|||
* Sven792
|
||||
* aldum
|
||||
* Dieter44
|
||||
* Pepebotella
|
||||
* MrRar
|
||||
* Lazerbeak12345
|
||||
* mrminer
|
||||
|
||||
## MineClone5
|
||||
* kay27
|
||||
|
@ -78,10 +86,12 @@
|
|||
* epCode
|
||||
* NO11
|
||||
* j45
|
||||
* chmodsayshello
|
||||
* 3raven
|
||||
* PrarieWind
|
||||
* Gustavo1
|
||||
* CableGuy67
|
||||
* MrRar
|
||||
|
||||
## Mineclonia
|
||||
* erlehmann
|
||||
|
@ -134,6 +144,9 @@
|
|||
* yutyo
|
||||
* NO11
|
||||
* kay27
|
||||
* MysticTempest
|
||||
* RandomLegoBrick
|
||||
* cora
|
||||
|
||||
## Translations
|
||||
* Wuzzy
|
||||
|
@ -143,6 +156,8 @@
|
|||
* pitchum
|
||||
* todoporlalibertad
|
||||
* Marcin Serwin
|
||||
* Pepebotella
|
||||
* Emojigit
|
||||
|
||||
## Funders
|
||||
* 40W
|
||||
|
@ -150,5 +165,6 @@
|
|||
## Special thanks
|
||||
* celeron55 for creating Minetest
|
||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||
* wsor for working tirelessly in the shadows for the good of all of us, particularly helping with solving contentDB and copyright issues.
|
||||
* The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game
|
||||
* Notch and Jeb for being the major forces behind Minecraft
|
||||
|
|
18
README.md
|
@ -2,7 +2,7 @@
|
|||
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
|
||||
Developed by many people. Not developed or endorsed by Mojang AB.
|
||||
|
||||
Version: 0.75 (in development)
|
||||
Version: 0.78 (in development)
|
||||
|
||||
### Gameplay
|
||||
You start in a randomly-generated world made entirely of cubes. You can explore
|
||||
|
@ -91,11 +91,11 @@ The MineClone2 repository is hosted at Mesehub. To contribute or report issues,
|
|||
## Target
|
||||
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
||||
based on the Minetest engine with polished features, usable in both
|
||||
singleplayer and multiplayer. Currently, most of **Minecraft Java
|
||||
Edition 1.12.2** features are already implemented and polishing existing
|
||||
singleplayer and multiplayer. Currently, a lot of **Minecraft Java
|
||||
Edition** features are already implemented and polishing existing
|
||||
features are prioritized over new feature requests.
|
||||
- With lessened priority yet strictly, implement features targetting
|
||||
**Minecraft version 1.17 + OptiFine** (OptiFine only as far as supported
|
||||
**Current Minecraft versions + OptiFine** (OptiFine only as far as supported
|
||||
by the Minetest Engine). This means features in parity with the listed
|
||||
Minecraft experiences are prioritized over those that don't fulfill this
|
||||
scope.
|
||||
|
@ -108,8 +108,7 @@ playerbase on low spec computers, optimizations are hard to investigate.
|
|||
This game is currently in **beta** stage.
|
||||
It is playable, but not yet feature-complete.
|
||||
Backwards-compability is not entirely guaranteed, updating your world might cause small bugs.
|
||||
If you want to use the git version of MineClone2 in production, consider using the production branch.
|
||||
It is updated weekly and contains relatively stable code for servers.
|
||||
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.
|
||||
|
||||
The following main features are available:
|
||||
|
||||
|
@ -124,7 +123,7 @@ The following main features are available:
|
|||
* Most blocks in the overworld
|
||||
* Water and lava
|
||||
* Weather
|
||||
* 28 biomes
|
||||
* 28 biomes + 5 Nether Biomes
|
||||
* The Nether, a fiery underworld in another dimension
|
||||
* Redstone circuits (partially)
|
||||
* Minecarts (partial)
|
||||
|
@ -162,7 +161,7 @@ The following features are incomplete:
|
|||
* Special minecarts
|
||||
* 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
|
||||
* 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
|
||||
* Red Nether Brick Fence
|
||||
* Red Nether Brick Fence Gate
|
||||
* Structure replacements - these small variants of Minecraft structures serve as replacements until we can get large structures working:
|
||||
* Woodland Cabin (Mansions)
|
||||
* Nether Outpost (Fortress)
|
||||
|
||||
Technical differences from Minecraft:
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
name = MineClone 2
|
||||
title = MineClone 2
|
||||
description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more.
|
||||
|
|
|
@ -110,9 +110,11 @@ end
|
|||
|
||||
local boat = {
|
||||
physical = true,
|
||||
pointable = true,
|
||||
-- Warning: Do not change the position of the collisionbox top surface,
|
||||
-- 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},
|
||||
selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.3, 0.7},
|
||||
visual = "mesh",
|
||||
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"},
|
||||
|
|
|
@ -134,6 +134,7 @@ function mcl_burning.set_on_fire(obj, burn_time)
|
|||
end
|
||||
|
||||
function mcl_burning.extinguish(obj)
|
||||
if not obj:get_pos() then return end
|
||||
if mcl_burning.is_burning(obj) then
|
||||
local storage = mcl_burning.get_storage(obj)
|
||||
if obj:is_player() then
|
||||
|
|
|
@ -1,66 +1,55 @@
|
|||
-- Dripping Water Mod
|
||||
-- by kddekadenz
|
||||
|
||||
local math = math
|
||||
|
||||
-- License of code, textures & sounds: CC0
|
||||
|
||||
local function register_drop(liquid, glow, sound, nodes)
|
||||
minetest.register_entity("mcl_dripping:drop_" .. liquid, {
|
||||
hp_max = 1,
|
||||
physical = true,
|
||||
collide_with_objects = false,
|
||||
collisionbox = {-0.01, 0.01, -0.01, 0.01, 0.01, 0.01},
|
||||
glow = glow,
|
||||
pointable = false,
|
||||
visual = "sprite",
|
||||
visual_size = {x = 0.1, y = 0.1},
|
||||
textures = {""},
|
||||
spritediv = {x = 1, y = 1},
|
||||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
static_save = false,
|
||||
_dropped = false,
|
||||
on_activate = function(self)
|
||||
self.object:set_properties({
|
||||
textures = {"[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"}
|
||||
})
|
||||
end,
|
||||
on_step = function(self, dtime)
|
||||
local k = math.random(1, 222)
|
||||
local ownpos = self.object:get_pos()
|
||||
if k == 1 then
|
||||
self.object:set_acceleration(vector.new(0, -5, 0))
|
||||
end
|
||||
if minetest.get_node(vector.offset(ownpos, 0, 0.5, 0)).name == "air" then
|
||||
self.object:set_acceleration(vector.new(0, -5, 0))
|
||||
end
|
||||
if minetest.get_node(vector.offset(ownpos, 0, -0.1, 0)).name ~= "air" then
|
||||
local ent = self.object:get_luaentity()
|
||||
if not ent._dropped then
|
||||
ent._dropped = true
|
||||
minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = ownpos, gain = 0.5, max_hear_distance = 8}, true)
|
||||
end
|
||||
if k < 3 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
local math = math
|
||||
local function make_drop(pos,liquid,sound,interval)
|
||||
local pt = {
|
||||
velocity = vector.new(0,0,0),
|
||||
collision_removal = false,
|
||||
}
|
||||
local t = math.random() + math.random(1, interval)
|
||||
minetest.after(t,function()
|
||||
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
|
||||
pt.pos = vector.offset(pos,x,-0.52,z)
|
||||
pt.acceleration = vector.new(0,0,0)
|
||||
pt.collisiondetection = false
|
||||
pt.expirationtime = t
|
||||
|
||||
pt.texture="[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"
|
||||
minetest.add_particle(pt)
|
||||
minetest.after(t,function()
|
||||
pt.acceleration = vector.new(0,-5,0)
|
||||
pt.collisiondetection = true
|
||||
pt.expirationtime = math.random() + math.random(1, interval/2)
|
||||
minetest.add_particle(pt)
|
||||
minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = pos, gain = 0.5, max_hear_distance = 8}, true)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
local function register_drop(liquid, glow, sound, nodes, interval, chance)
|
||||
minetest.register_abm({
|
||||
label = "Create drops",
|
||||
nodenames = nodes,
|
||||
neighbors = {"group:" .. liquid},
|
||||
interval = 2,
|
||||
chance = 22,
|
||||
interval = interval,
|
||||
chance = chance,
|
||||
action = function(pos)
|
||||
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1, 0)).name, liquid) ~= 0
|
||||
and minetest.get_node(vector.offset(pos, 0, -1, 0)).name == "air" then
|
||||
local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100
|
||||
minetest.add_entity(vector.offset(pos, x, -0.520, z), "mcl_dripping:drop_" .. liquid)
|
||||
local r = math.ceil(interval / 20)
|
||||
local nn=minetest.find_nodes_in_area(vector.offset(pos,-r,0,-r),vector.offset(pos,r,0,r),nodes)
|
||||
--start a bunch of particle cycles to be able to get away
|
||||
--with longer abm cycles
|
||||
table.shuffle(nn)
|
||||
for i=1,math.random(#nn) do
|
||||
if minetest.get_item_group(minetest.get_node(vector.offset(nn[i], 0, 1, 0)).name, liquid) ~= 0
|
||||
and minetest.get_node(vector.offset(nn[i], 0, -1, 0)).name == "air" then
|
||||
make_drop(nn[i],liquid,sound,interval)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
register_drop("water", 1, "", {"group:opaque", "group:leaves"})
|
||||
register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"})
|
||||
register_drop("water", 1, "", {"group:opaque", "group:leaves"},60,10)
|
||||
register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"},60,10)
|
||||
|
|
|
@ -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:leather", "mcl:killCow")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_core:crying_obsidian", "mcl:whosCuttingOnions")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_nether:ancient_debris", "mcl:hiddenInTheDepths")
|
||||
|
||||
local function check_pickup_achievements(object, player)
|
||||
if has_awards then
|
||||
|
@ -78,7 +80,6 @@ local function enable_physics(object, luaentity, ignore_check)
|
|||
object:set_properties({
|
||||
physical = true
|
||||
})
|
||||
object:set_velocity({x=0,y=0,z=0})
|
||||
object:set_acceleration({x=0,y=-get_gravity(),z=0})
|
||||
end
|
||||
end
|
||||
|
@ -536,9 +537,9 @@ minetest.register_entity(":__builtin:item", {
|
|||
self.itemstring = data.itemstring
|
||||
self.always_collect = data.always_collect
|
||||
if data.age then
|
||||
self.age = data.age + dtime_s
|
||||
self.age = data.age
|
||||
else
|
||||
self.age = dtime_s
|
||||
self.age = self.age
|
||||
end
|
||||
--remember collection data
|
||||
-- If true, can collect item without delay
|
||||
|
@ -774,8 +775,8 @@ minetest.register_entity(":__builtin:item", {
|
|||
return
|
||||
end
|
||||
|
||||
-- Move item around on flowing liquids
|
||||
if def and def.liquidtype == "flowing" then
|
||||
-- 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" or def.liquidtype == "source" then
|
||||
|
||||
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
||||
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
||||
|
@ -784,11 +785,11 @@ minetest.register_entity(":__builtin:item", {
|
|||
-- 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
|
||||
-- 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
|
||||
local newv = vector.multiply(vec, f)
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
|
||||
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
|
||||
self.object:set_acceleration({x = newv.x, y = -0.22, z = newv.z})
|
||||
|
||||
self.physical_state = 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 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
|
||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||
-- Merge with close entities of the same item
|
||||
|
|
|
@ -21,7 +21,7 @@ local function register_rail(itemstring, tiles, def_extras, creative)
|
|||
stack_max = 64,
|
||||
groups = groups,
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_blast_resistance = 0.7,
|
||||
_mcl_hardness = 0.7,
|
||||
after_destruct = function(pos)
|
||||
-- Scan for minecarts in this pos and force them to execute their "floating" check.
|
||||
|
|
|
@ -91,7 +91,7 @@ minetest.register_chatcommand("clearmobs",{
|
|||
if o.is_mob then
|
||||
if param == "all" or
|
||||
( param == "nametagged" and o.nametag ) or
|
||||
( param == "" and not o.nametag 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
|
||||
o.object:remove()
|
||||
end
|
||||
|
@ -298,9 +298,13 @@ local function update_roll(self)
|
|||
|
||||
if is_Fleckenstein then
|
||||
cbox[2], cbox[5] = -cbox[5], -cbox[2]
|
||||
self.object:set_properties({collisionbox = cbox})
|
||||
-- This leads to child mobs having the wrong collisionbox
|
||||
-- and seeing as it seems to be nothing but an easter egg
|
||||
-- i've put it inside the if. Which just makes it be upside
|
||||
-- down lol.
|
||||
end
|
||||
|
||||
self.object:set_properties({collisionbox = cbox})
|
||||
end
|
||||
|
||||
-- set and return valid yaw
|
||||
|
@ -1901,11 +1905,10 @@ local specific_attack = function(list, what)
|
|||
return false
|
||||
end
|
||||
|
||||
-- monster find someone to attack
|
||||
-- find someone to attack
|
||||
local monster_attack = function(self)
|
||||
|
||||
if self.type ~= "monster"
|
||||
or not damage_enabled
|
||||
if not damage_enabled
|
||||
or minetest.is_creative_enabled("")
|
||||
or self.passive
|
||||
or self.state == "attack"
|
||||
|
@ -1923,10 +1926,9 @@ local monster_attack = function(self)
|
|||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
|
||||
if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then
|
||||
type = ""
|
||||
else
|
||||
elseif (self.type == "monster" or self._aggro) then
|
||||
player = objs[n]
|
||||
type = "player"
|
||||
name = "player"
|
||||
|
@ -2283,6 +2285,9 @@ end
|
|||
local function go_to_pos(entity,b)
|
||||
if not entity then return end
|
||||
local s=entity.object:get_pos()
|
||||
if not b then
|
||||
--self.state = "stand"
|
||||
return end
|
||||
if vector.distance(b,s) < 1 then
|
||||
--set_velocity(entity,0)
|
||||
return true
|
||||
|
@ -2305,15 +2310,52 @@ local function check_doors(self)
|
|||
local def = minetest.registered_nodes[n.name]
|
||||
local closed = n.name:find("_b_1")
|
||||
if t < 0.3 or t > 0.8 then
|
||||
if not closed then def.on_rightclick(d,n,self) end
|
||||
if not closed and def.on_rightclick then def.on_rightclick(d,n,self) end
|
||||
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
|
||||
|
||||
local gowp_etime = 0
|
||||
|
||||
local function check_gowp(self,dtime)
|
||||
gowp_etime = gowp_etime + dtime
|
||||
if gowp_etime < 0.2 then return end
|
||||
gowp_etime = 0
|
||||
local p = self.object:get_pos()
|
||||
if not p or not self._target then return end
|
||||
if vector.distance(p,self._target) < 1 then
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self.current_target = nil
|
||||
self.state = "stand"
|
||||
if self.callback_arrived then return self.callback_arrived(self) end
|
||||
return true
|
||||
end
|
||||
if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 2 ) then
|
||||
self.current_target = table.remove(self.waypoints, 1)
|
||||
--minetest.log("nextwp:".. tostring(self.current_target) )
|
||||
go_to_pos(self,self.current_target)
|
||||
return
|
||||
elseif self.current_target then
|
||||
go_to_pos(self,self.current_target)
|
||||
end
|
||||
|
||||
if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then
|
||||
self.waypoints=minetest.find_path(p,self._target,150,1,4)
|
||||
if not self.waypoints then self.state = "walk" end --give up
|
||||
self.current_target = nil
|
||||
return
|
||||
end
|
||||
if not self.current_target then
|
||||
--minetest.log("no path")
|
||||
self.state = "walk"
|
||||
end
|
||||
end
|
||||
|
||||
-- execute current state (stand, walk, run, attacks)
|
||||
-- returns true if mob has died
|
||||
local do_states = function(self, dtime)
|
||||
|
@ -2326,9 +2368,8 @@ local do_states = function(self, dtime)
|
|||
|
||||
local s = self.object:get_pos()
|
||||
local objs = minetest.get_objects_inside_radius(s, 3)
|
||||
|
||||
local lp
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
lp = objs[n]:get_pos()
|
||||
break
|
||||
|
@ -2336,7 +2377,7 @@ local do_states = function(self, dtime)
|
|||
end
|
||||
|
||||
-- look at any players nearby, otherwise turn randomly
|
||||
if self.look_at_players then
|
||||
if lp and self.look_at_players then
|
||||
|
||||
local vec = {
|
||||
x = lp.x - s.x,
|
||||
|
@ -2372,32 +2413,7 @@ local do_states = function(self, dtime)
|
|||
end
|
||||
|
||||
elseif self.state == "gowp" then
|
||||
local p = self.object:get_pos()
|
||||
if not p or not self._target then return end
|
||||
if vector.distance(p,self._target) < 2 or ( self.waypoints and #self.waypoints == 0 ) then
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self.current_target = nil
|
||||
self.state = "walk"
|
||||
if self.callback_arrived then return self.callback_arrived(self) end
|
||||
return true
|
||||
end
|
||||
if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 1.5 ) then
|
||||
self.current_target = table.remove(self.waypoints, 1)
|
||||
--minetest.log("nextwp:".. tostring(self.current_target) )
|
||||
elseif self.current_target then
|
||||
go_to_pos(self,self.current_target)
|
||||
end
|
||||
|
||||
if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then
|
||||
self.waypoints=minetest.find_path(p,self._target,150,1,4)
|
||||
self.current_target = nil
|
||||
return
|
||||
end
|
||||
if not self.current_target then
|
||||
--minetest.log("no path")
|
||||
self.state = "walk"
|
||||
end
|
||||
check_gowp(self,dtime)
|
||||
|
||||
elseif self.state == "walk" then
|
||||
local s = self.object:get_pos()
|
||||
|
@ -2908,7 +2924,12 @@ local plane_adjacents = {
|
|||
vector.new(0,0,-1),
|
||||
}
|
||||
|
||||
|
||||
local gopath_last = os.time()
|
||||
function mcl_mobs:gopath(self,target,callback_arrived)
|
||||
if os.time() - gopath_last < 15 then return end
|
||||
gopath_last = os.time()
|
||||
--minetest.log("gowp")
|
||||
local p = self.object:get_pos()
|
||||
local t = vector.offset(target,0,1,0)
|
||||
local wp = minetest.find_path(p,t,150,1,4)
|
||||
|
@ -2928,11 +2949,15 @@ function mcl_mobs:gopath(self,target,callback_arrived)
|
|||
if wp and #wp > 0 then
|
||||
self._target = t
|
||||
self.callback_arrived = callback_arrived
|
||||
table.remove(wp,1)
|
||||
self.waypoints = wp
|
||||
self.state = "gowp"
|
||||
return true
|
||||
else
|
||||
--minetest.log("no path found")
|
||||
self.state = "walk"
|
||||
self.waypoints = nil
|
||||
self.current_target = nil
|
||||
-- minetest.log("no path found")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2964,7 +2989,7 @@ local function damage_mob(self,reason,damage)
|
|||
if damage > 0 then
|
||||
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
|
||||
return true
|
||||
|
@ -3210,35 +3235,36 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
|
||||
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 weapon:get_definition().sounds ~= nil then
|
||||
if damage >= 0 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], {
|
||||
object = self.object, --hitter,
|
||||
max_hear_distance = 8
|
||||
}, true)
|
||||
else
|
||||
minetest.sound_play("default_punch", {
|
||||
object = self.object,
|
||||
max_hear_distance = 5
|
||||
}, true)
|
||||
minetest.sound_play(weapon:get_definition().sounds[s], {
|
||||
object = self.object, --hitter,
|
||||
max_hear_distance = 8
|
||||
}, true)
|
||||
else
|
||||
minetest.sound_play("default_punch", {
|
||||
object = self.object,
|
||||
max_hear_distance = 5
|
||||
}, 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
|
||||
|
||||
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)
|
||||
if not die
|
||||
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 hitter:get_player_name() ~= self.owner
|
||||
and not mcl_mobs.invis[ name ] then
|
||||
|
||||
if not die then
|
||||
-- attack whoever punched mob
|
||||
self.state = ""
|
||||
do_attack(self, hitter)
|
||||
self._aggro= true
|
||||
end
|
||||
|
||||
-- alert others to the attack
|
||||
|
@ -3334,7 +3360,6 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
obj = objs[n]:get_luaentity()
|
||||
|
||||
if obj then
|
||||
|
||||
-- only alert members of same mob or friends
|
||||
if obj.group_attack
|
||||
and obj.state ~= "attack"
|
||||
|
@ -3344,6 +3369,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
|||
elseif type(obj.group_attack) == "table" then
|
||||
for i=1, #obj.group_attack do
|
||||
if obj.name == obj.group_attack[i] then
|
||||
obj._aggro = true
|
||||
do_attack(obj, hitter)
|
||||
break
|
||||
end
|
||||
|
@ -4008,6 +4034,8 @@ minetest.register_entity(name, {
|
|||
fire_resistant = def.fire_resistant or false,
|
||||
fire_damage_resistant = def.fire_damage_resistant or false,
|
||||
ignited_by_sunlight = def.ignited_by_sunlight or false,
|
||||
spawn_in_group = def.spawn_in_group,
|
||||
spawn_in_group_min = def.spawn_in_group_min,
|
||||
-- End of MCL2 extensions
|
||||
|
||||
on_spawn = def.on_spawn,
|
||||
|
@ -4333,7 +4361,7 @@ end
|
|||
|
||||
|
||||
-- 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
|
||||
return false
|
||||
end
|
||||
|
@ -4346,7 +4374,7 @@ function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame)
|
|||
|
||||
local item = clicker:get_wielded_item()
|
||||
|
||||
item:take_item()
|
||||
if not notake then item:take_item() end
|
||||
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ local math_cos = math.cos
|
|||
local math_sin = math.sin
|
||||
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
|
||||
|
||||
--local vector_distance = vector.distance
|
||||
local vector_distance = vector.distance
|
||||
local vector_new = vector.new
|
||||
local vector_floor = vector.floor
|
||||
|
||||
|
@ -25,7 +25,15 @@ local table_remove = table.remove
|
|||
local pairs = pairs
|
||||
|
||||
-- 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?
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
|
@ -153,6 +161,10 @@ local list_of_all_biomes = {
|
|||
-- dimension biome:
|
||||
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
"CrimsonForest",
|
||||
"WarpedForest",
|
||||
"SoulsandValley",
|
||||
"End",
|
||||
|
||||
-- Overworld regular:
|
||||
|
@ -162,6 +174,8 @@ local list_of_all_biomes = {
|
|||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+_snowtop",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
|
@ -180,7 +194,6 @@ local list_of_all_biomes = {
|
|||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
|
@ -192,11 +205,26 @@ local list_of_all_biomes = {
|
|||
}
|
||||
|
||||
-- count how many mobs are in an area
|
||||
local function count_mobs(pos)
|
||||
local function count_mobs(pos,r,mob_type)
|
||||
local num = 0
|
||||
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do
|
||||
if object and object:get_luaentity() and object:get_luaentity().is_mob then
|
||||
num = num + 1
|
||||
for _,l in pairs(minetest.luaentities) do
|
||||
if l and l.is_mob and (mob_type == nil or l.type == mob_type) then
|
||||
local p = l.object:get_pos()
|
||||
if p and vector_distance(p,pos) < r then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return num
|
||||
end
|
||||
|
||||
local function count_mobs_total(mob_type)
|
||||
local num = 0
|
||||
for _,l in pairs(minetest.luaentities) do
|
||||
if l.is_mob then
|
||||
if mob_type == nil or l.type == mob_type then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return num
|
||||
|
@ -289,7 +317,7 @@ function mcl_mobs:spawn_setup(def)
|
|||
spawn_dictionary[#spawn_dictionary + 1] = {
|
||||
name = name,
|
||||
dimension = dimension,
|
||||
type_of_spawning = type_of_spawning,
|
||||
type_of_spawning = type_of_spawning,
|
||||
biomes = biomes,
|
||||
min_light = min_light,
|
||||
max_light = max_light,
|
||||
|
@ -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"
|
||||
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
|
||||
|
||||
local perlin_noise
|
||||
|
||||
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 goal_pos = get_next_mob_spawn_pos(pos)
|
||||
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
|
||||
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
||||
|
||||
--hard code mob limit in area to 5 for now
|
||||
if count_mobs(spawning_position) >= 5 then return end
|
||||
|
||||
local gotten_node = get_node(spawning_position).name
|
||||
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||
if not gotten_node or not gotten_biome then return end
|
||||
|
@ -407,6 +473,8 @@ if mobs_spawn then
|
|||
|
||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||
local is_leaf = get_item_group(gotten_node, "leaves") ~= 0
|
||||
local is_bedrock = gotten_node == "mcl_core:bedrock"
|
||||
local is_ground = not (is_water or is_lava)
|
||||
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
|
||||
local has_bed = minetest.find_node_near(pos,25,{"group:bed"})
|
||||
|
@ -426,6 +494,7 @@ if mobs_spawn then
|
|||
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||
local noise = perlin_noise:get_3d(spawning_position)
|
||||
local current_summary_chance = summary_chance
|
||||
table.shuffle(mob_library_worker_table)
|
||||
while #mob_library_worker_table > 0 do
|
||||
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||
local mob_index = 1
|
||||
|
@ -438,7 +507,12 @@ if mobs_spawn then
|
|||
end
|
||||
local mob_def = mob_library_worker_table[mob_index]
|
||||
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
|
||||
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.max_height
|
||||
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.max_light
|
||||
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 (not is_farm_animal(mob_def.name) or is_grass)
|
||||
and (mob_type ~= "npc" or has_bed)
|
||||
and (mob_def.type_of_spawning ~= "water" or is_water)
|
||||
and not is_bedrock
|
||||
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
|
||||
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
|
||||
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
|
||||
current_summary_chance = current_summary_chance - mob_chance
|
||||
|
|
|
@ -46,6 +46,9 @@ end
|
|||
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
|
||||
local old_on_place = wither_head.on_place
|
||||
function wither_head.on_place(itemstack, placer, pointed)
|
||||
minetest.after(0, wither_spawn, pointed.above)
|
||||
old_on_place(itemstack, placer, pointed)
|
||||
local n = minetest.get_node(vector.offset(pointed.above,0,-1,0))
|
||||
if n and n.name == "mcl_nether:soul_sand" then
|
||||
minetest.after(0, wither_spawn, pointed.above)
|
||||
end
|
||||
return old_on_place(itemstack, placer, pointed)
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ mcl_mobs:register_mob("mobs_mc:bat", {
|
|||
type = "animal",
|
||||
spawn_class = "ambient",
|
||||
can_despawn = true,
|
||||
spawn_in_group = 8,
|
||||
passive = true,
|
||||
hp_min = 6,
|
||||
hp_max = 6,
|
||||
|
|
|
@ -16,6 +16,8 @@ mcl_mobs:register_mob("mobs_mc:blaze", {
|
|||
description = S("Blaze"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 3,
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 10,
|
||||
|
|
|
@ -122,8 +122,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
|
|
|
@ -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)
|
|
@ -83,6 +83,8 @@ mcl_mobs:register_mob("mobs_mc:cow", cow_def)
|
|||
local mooshroom_def = table.copy(cow_def)
|
||||
mooshroom_def.description = S("Mooshroom")
|
||||
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
||||
mooshroom_def.spawn_in_group_min = 4
|
||||
mooshroom_def.spawn_in_group = 8
|
||||
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
||||
mooshroom_def.on_rightclick = function(self, clicker)
|
||||
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
|
||||
|
@ -151,17 +153,12 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
|
|
|
@ -274,7 +274,6 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -301,7 +300,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -340,7 +338,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -350,7 +347,6 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -376,7 +372,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
|
|
@ -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)
|
|
@ -35,6 +35,7 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", {
|
|||
},
|
||||
physical = true,
|
||||
damage = 10,
|
||||
knock_back = false,
|
||||
jump = true,
|
||||
jump_height = 14,
|
||||
fly = true,
|
||||
|
|
|
@ -627,7 +627,6 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -654,7 +653,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -693,7 +691,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -703,7 +700,6 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -729,7 +725,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -766,15 +761,32 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"SoulsandVall3ey",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
11,
|
||||
30,
|
||||
27500,
|
||||
4,
|
||||
mcl_vars.mg_nether_min,
|
||||
mcl_vars.mg_nether_max)
|
||||
|
||||
-- Warped Forest spawn (common)
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"WarpedForest"
|
||||
},
|
||||
0,
|
||||
11,
|
||||
30,
|
||||
5000,
|
||||
4,
|
||||
mcl_vars.mg_nether_min,
|
||||
mcl_vars.mg_nether_max)
|
||||
|
||||
-- spawn eggs
|
||||
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)
|
||||
|
|
|
@ -23,6 +23,7 @@ mcl_mobs:register_mob("mobs_mc:ghast", {
|
|||
collisionbox = {-2, 5, -2, 2, 9, 2},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_ghast.b3d",
|
||||
spawn_in_group = 1,
|
||||
textures = {
|
||||
{"mobs_mc_ghast.png"},
|
||||
},
|
||||
|
@ -81,12 +82,14 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"SoulsandValley",
|
||||
"BasaltDelta",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
7,
|
||||
30,
|
||||
18000,
|
||||
72000,
|
||||
2,
|
||||
mcl_vars.mg_nether_min,
|
||||
mcl_vars.mg_nether_max)
|
||||
|
@ -105,7 +108,12 @@ mcl_mobs:register_arrow("mobs_mc:fireball", {
|
|||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 6},
|
||||
}, 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,
|
||||
|
||||
hit_mob = function(self, mob)
|
||||
|
|
|
@ -8,12 +8,14 @@ mcl_mobs:register_mob("mobs_mc:guardian", {
|
|||
description = S("Guardian"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 4,
|
||||
hp_min = 30,
|
||||
hp_max = 30,
|
||||
xp_min = 10,
|
||||
xp_max = 10,
|
||||
breath_max = -1,
|
||||
passive = false,
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
pathfinding = 1,
|
||||
view_range = 16,
|
||||
|
|
|
@ -81,11 +81,27 @@ for b=1, #horse_base do
|
|||
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
|
||||
local horse = {
|
||||
description = S("Horse"),
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 6,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_horse.b3d",
|
||||
visual_size = {x=3.0, y=3.0},
|
||||
|
@ -138,7 +154,7 @@ local horse = {
|
|||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
|
||||
on_spawn = update_textures,
|
||||
do_custom = function(self, dtime)
|
||||
|
||||
-- set needed values if not already present
|
||||
|
@ -476,6 +492,8 @@ local d = 0.86 -- donkey scale
|
|||
local donkey = table.copy(horse)
|
||||
donkey.description = S("Donkey")
|
||||
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
||||
donkey.spawn_in_group = 3
|
||||
donkey.spawn_in_group_min = 1
|
||||
donkey.animation = {
|
||||
speed_normal = 25,
|
||||
stand_start = 0, stand_end = 0,
|
||||
|
@ -528,41 +546,14 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
"Taiga",
|
||||
"Taiga_beach",
|
||||
"Forest",
|
||||
"Forest_beach",
|
||||
"FlowerForest",
|
||||
"FlowerForest_beach",
|
||||
"BirchForest",
|
||||
"BirchForestM",
|
||||
"RoofedForest",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
"SavannaM",
|
||||
"Jungle",
|
||||
"Jungle_shore",
|
||||
"JungleM",
|
||||
"JungleM_shore",
|
||||
"JungleEdge",
|
||||
"JungleEdgeM",
|
||||
"Swampland",
|
||||
"Swampland_shore"
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -572,20 +563,22 @@ minetest.LIGHT_MAX+1,
|
|||
mobs_mc.water_level+3,
|
||||
mcl_vars.mg_overworld_max)
|
||||
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:donkey",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"flat",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
"SunflowerPlains",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
"SavannaM",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
},
|
||||
0,
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
|
|
|
@ -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 .. "/vex.lua") -- KrupnoPavel
|
||||
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i
|
||||
|
||||
dofile(path .. "/cod.lua")
|
||||
dofile(path .. "/salmon.lua")
|
||||
dofile(path .. "/dolphin.lua")
|
||||
|
|
|
@ -37,6 +37,7 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", {
|
|||
run_velocity = 1.2,
|
||||
-- Approximation
|
||||
damage = 14,
|
||||
knock_back = false,
|
||||
reach = 3,
|
||||
group_attack = true,
|
||||
attacks_monsters = true,
|
||||
|
|
|
@ -28,6 +28,8 @@ mcl_mobs:register_mob("mobs_mc:llama", {
|
|||
description = S("Llama"),
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 4,
|
||||
spawn_in_group = 6,
|
||||
hp_min = 15,
|
||||
hp_max = 30,
|
||||
xp_min = 1,
|
||||
|
@ -217,18 +219,16 @@ mcl_mobs:spawn_specific(
|
|||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"Jungle",
|
||||
"Jungle_shore",
|
||||
"JungleM",
|
||||
"JungleM_shore",
|
||||
"Savanna",
|
||||
"SavannaM",
|
||||
"SavannaM_beach",
|
||||
"Savanna_beach",
|
||||
"Savanna_ocean",
|
||||
"JungleEdge",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -1,64 +1,58 @@
|
|||
# textdomain: mobs_mc
|
||||
Agent=Agente
|
||||
Bat=Murciélago
|
||||
Blaze=Blaze
|
||||
Chicken=Pollo
|
||||
Cod=Bacalao
|
||||
Cow=Vaca
|
||||
Mooshroom=Champiñaca
|
||||
Mooshroom=Champivaca
|
||||
Creeper=Creeper
|
||||
Ender Dragon=Enderdragón
|
||||
Dolphin=Delfín
|
||||
Ender Dragon=Ender Dragon
|
||||
Enderman=Enderman
|
||||
Endermite=Endermite
|
||||
Ghast=Ghast
|
||||
Elder Guardian=Gran guardián
|
||||
Guardian=Guardián
|
||||
Horse=Caballo
|
||||
Skeleton Horse=Caballo esquelético
|
||||
Zombie Horse=Caballo zombie
|
||||
Elder Guardian=Guardián Anciano
|
||||
Donkey=Burro
|
||||
Horse=Caballo
|
||||
Mule=Mula
|
||||
Skeleton Horse=Caballo esqueleto
|
||||
Zombie Horse=Caballo zombi
|
||||
Iron Golem=Golem de hierro
|
||||
Llama=Llama
|
||||
Cat=Gato
|
||||
Ocelot=Ocelote
|
||||
Parrot=Loro
|
||||
Pig=Cerdo
|
||||
Polar Bear=Oso polar
|
||||
Rabbit=Conejo
|
||||
Killer Bunny=Conejo asesino
|
||||
Rabbit=Conejo
|
||||
Salmon=Salmón
|
||||
Sheep=Oveja
|
||||
Shulker=Shulker
|
||||
Silverfish=Lepisma
|
||||
Skeleton=Esqueleto
|
||||
Stray=Esqueleto
|
||||
Wither Skeleton=Esqueleto wither
|
||||
Stray=Esqueleto glacial
|
||||
Wither Skeleton=Esqueleto del Wither
|
||||
Magma Cube=Cubo de Magma
|
||||
Slime=Slime
|
||||
Snow Golem=Golem de nieve
|
||||
Spider=Araña
|
||||
Cave Spider=Araña de las cuevas
|
||||
Spider=Araña
|
||||
Squid=Calamar
|
||||
Vex=Ánima
|
||||
Master=Maestro
|
||||
Villager=Aldeano
|
||||
Evoker=Invocador
|
||||
Illusioner=Illusionista
|
||||
Villager=Aldeano
|
||||
Vindicator=Vindicador
|
||||
Zombie Villager=Aldeano zombie
|
||||
Zombie Villager=Aldeano zombi
|
||||
Witch=Bruja
|
||||
Wither=Wither
|
||||
Wolf=Lobo
|
||||
Husk=Husk
|
||||
Zombie=Zombie
|
||||
Zombie Pigman=Cerdo Zombie
|
||||
Farmer=Granjero
|
||||
Fisherman=Pescador
|
||||
Fletcher=Flechador
|
||||
Shepherd=Sacerdote
|
||||
Librarian=Bibliotecario
|
||||
Cartographer=Cartógrafo
|
||||
Armorer=Armero
|
||||
Leatherworker=Peletero
|
||||
Butcher=Carnicero
|
||||
Weapon Smith=Herrero de Armas
|
||||
Tool Smith=Herrero de Herramientas
|
||||
Cleric=Sacerdote
|
||||
Nitwit=Simple
|
||||
Baby Husk=Bebé Zombi Momificado
|
||||
Baby Zombie=Bebé Zombi
|
||||
Husk=Zombi Momificado
|
||||
Zombie=Zombi
|
||||
Baby Zombie Pigman=Bebé Hombrecerdo Zombi
|
||||
Zombie Pigman=Hombrecerdo Zombi
|
||||
|
|
|
@ -62,3 +62,6 @@ Weapon Smith=
|
|||
Tool Smith=
|
||||
Cleric=
|
||||
Nitwit=
|
||||
Cod=
|
||||
Salmon=
|
||||
Dolphin=
|
||||
|
|
|
@ -30,6 +30,8 @@ local ocelot = {
|
|||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
can_despawn = true,
|
||||
spawn_in_group = 3,
|
||||
spawn_in_group_min = 1,
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 1,
|
||||
|
|
|
@ -13,6 +13,45 @@ local shoulders = {
|
|||
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
|
||||
local function get_shoulder(player)
|
||||
local sh = "left"
|
||||
|
@ -159,6 +198,7 @@ mcl_mobs:register_mob("mobs_mc:parrot", {
|
|||
end,
|
||||
do_custom = function(self,dtime)
|
||||
check_perch(self,dtime)
|
||||
check_mobimitate(self,dtime)
|
||||
end,
|
||||
do_punch = function(self,puncher) --do_punch is the mcl_mobs_redo variant - it gets called by on_punch later....
|
||||
if self.object:get_attach() == puncher then
|
||||
|
|
|
@ -194,17 +194,12 @@ mcl_mobs:spawn_specific(
|
|||
"ground",
|
||||
{
|
||||
"flat",
|
||||
"IcePlainsSpikes",
|
||||
"ColdTaiga",
|
||||
"ColdTaiga_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"MegaTaiga",
|
||||
"MegaSpruceTaiga",
|
||||
"ExtremeHills",
|
||||
"ExtremeHills_beach",
|
||||
"ExtremeHillsM",
|
||||
"ExtremeHills+",
|
||||
"ExtremeHills+_snowtop",
|
||||
"StoneBeach",
|
||||
"Plains",
|
||||
"Plains_beach",
|
||||
|
|
|
@ -76,7 +76,6 @@ mcl_mobs:spawn_specific(
|
|||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -6,9 +6,10 @@ local rabbit = {
|
|||
description = S("Rabbit"),
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 3,
|
||||
passive = true,
|
||||
reach = 1,
|
||||
|
||||
hp_min = 3,
|
||||
hp_max = 3,
|
||||
xp_min = 1,
|
||||
|
@ -132,18 +133,9 @@ mcl_mobs:spawn_specific(
|
|||
"Desert",
|
||||
"FlowerForest",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -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)
|
|
@ -346,7 +346,7 @@ mcl_mobs:spawn_specific(
|
|||
"Swampland",
|
||||
"Swampland_shore"
|
||||
},
|
||||
0,
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
|
|
|
@ -33,6 +33,7 @@ mcl_mobs:register_mob("mobs_mc:shulker", {
|
|||
-- TODO: Make shulker dye-able
|
||||
visual_size = {x=3, y=3},
|
||||
walk_chance = 0,
|
||||
knock_back = false,
|
||||
jump = false,
|
||||
drops = {
|
||||
{name = "mcl_mobitems:shulker_shell",
|
||||
|
|
|
@ -162,7 +162,6 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -189,7 +188,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -228,7 +226,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -238,7 +235,6 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -264,7 +260,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -302,10 +297,10 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"SoulsandValley",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
10000,
|
||||
3,
|
||||
|
|
|
@ -101,7 +101,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"SoulsandValley",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
|
|
|
@ -402,7 +402,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -418,7 +419,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -433,7 +435,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"BasaltDelta",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -443,11 +446,6 @@ minetest.LIGHT_MAX+1,
|
|||
mmin,
|
||||
mmax)
|
||||
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_tiny", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_small", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
--mcl_mobs:spawn_specific("mobs_mc:magma_cube_big", { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
mcl_mobs:register_egg("mobs_mc:magma_cube_big", S("Magma Cube"), "mobs_mc_spawn_icon_magmacube.png")
|
||||
mcl_mobs:register_egg("mobs_mc:slime_big", S("Slime"), "mobs_mc_spawn_icon_slime.png")
|
||||
|
|
|
@ -109,7 +109,6 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -136,7 +135,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -175,7 +173,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
|
@ -185,7 +182,6 @@ mcl_mobs:spawn_specific(
|
|||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
|
@ -211,7 +207,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
|
After Width: | Height: | Size: 766 B |
After Width: | Height: | Size: 443 B |
After Width: | Height: | Size: 830 B |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 6.1 KiB |
|
@ -136,8 +136,7 @@ local professions = {
|
|||
{
|
||||
{ { "mcl_fishing:fish_raw", 6, 15,}, E1 },
|
||||
{ { "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",1,1} },
|
||||
{ { "mcl_core:emerald", 1, 2 },{"mcl_campfires:campfire_lit",1,1} },
|
||||
},
|
||||
{
|
||||
{ { "mcl_fishing:salmon_raw", 6, 13,}, E1 },
|
||||
|
@ -427,7 +426,7 @@ local professions = {
|
|||
"mobs_mc_villager_weaponsmith.png",
|
||||
"mobs_mc_villager_weaponsmith.png",
|
||||
},
|
||||
jobsite = "mcl_furnaces:furnace", --FIXME: grindstone
|
||||
jobsite = "mcl_grindstone:grindstone",
|
||||
trades = {
|
||||
{
|
||||
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
||||
|
@ -458,7 +457,7 @@ local professions = {
|
|||
"mobs_mc_villager_toolsmith.png",
|
||||
"mobs_mc_villager_toolsmith.png",
|
||||
},
|
||||
jobsite = "mcl_anvils:anvil", --FIXME: smithing table
|
||||
jobsite = "mcl_smithing_table:table",
|
||||
trades = {
|
||||
{
|
||||
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
||||
|
@ -613,6 +612,8 @@ local function employ(self,jobsite_pos)
|
|||
end
|
||||
|
||||
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 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
|
||||
|
@ -628,14 +629,24 @@ local function look_for_job(self)
|
|||
end
|
||||
|
||||
local function get_a_job(self)
|
||||
if self.child then return end
|
||||
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)
|
||||
for _,n in pairs(nn) do
|
||||
if n and employ(self,n) then return true end
|
||||
end
|
||||
local n = minetest.find_node_near(p,1,jobsites)
|
||||
if n and employ(self,n) then return true end
|
||||
if self.state ~= "gowp" then look_for_job(self) 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)
|
||||
if not self._trades then
|
||||
return
|
||||
|
@ -724,7 +735,10 @@ local function set_trade(trader, player, inv, concrete_tradenum)
|
|||
local trade = trades[concrete_tradenum]
|
||||
inv:set_stack("wanted", 1, ItemStack(trade.wanted[1]))
|
||||
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)
|
||||
if trade.wanted[2] then
|
||||
local wanted2 = ItemStack(trade.wanted[2])
|
||||
|
@ -982,6 +996,11 @@ local trade_inventory = {
|
|||
elseif listname == "output" then
|
||||
if not trader_exists(player:get_player_name()) then
|
||||
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
|
||||
-- Only allow taking full stack
|
||||
local count = stack:get_count()
|
||||
|
@ -1094,6 +1113,7 @@ local trade_inventory = {
|
|||
local trader = player_trading_with[name]
|
||||
local tradenum = player_tradenum[name]
|
||||
local trades
|
||||
trader._traded = true
|
||||
if trader and trader._trades then
|
||||
trades = minetest.deserialize(trader._trades)
|
||||
end
|
||||
|
@ -1224,6 +1244,7 @@ mcl_mobs:register_mob("mobs_mc:villager", {
|
|||
-- TODO: sounds
|
||||
sounds = {
|
||||
random = "mobs_mc_villager",
|
||||
damage = "mobs_mc_villager_hurt",
|
||||
distance = 10,
|
||||
},
|
||||
animation = {
|
||||
|
@ -1236,10 +1257,12 @@ mcl_mobs:register_mob("mobs_mc:villager", {
|
|||
run_speed = 25,
|
||||
run_start = 0,
|
||||
run_end = 40,
|
||||
die_speed = 15,
|
||||
die_start = 210,
|
||||
die_end = 220,
|
||||
die_loop = false,
|
||||
head_shake_start = 210,
|
||||
head_shake_end = 220,
|
||||
head_shake_loop = false,
|
||||
head_nod_start = 210,
|
||||
head_nod_end = 220,
|
||||
head_nod_loop = false,
|
||||
},
|
||||
follow = pick_up,
|
||||
nofollow = true,
|
||||
|
@ -1261,19 +1284,18 @@ mcl_mobs:register_mob("mobs_mc:villager", {
|
|||
end
|
||||
end
|
||||
if clicker then
|
||||
mcl_mobs:feed_tame(self, clicker, 1, true, false)
|
||||
mcl_mobs:feed_tame(self, clicker, 1, true, false, true)
|
||||
return
|
||||
end
|
||||
return true --do not pick up
|
||||
end,
|
||||
on_rightclick = function(self, clicker)
|
||||
local trg=vector.new(0,9,0)
|
||||
if self._jobsite then
|
||||
mcl_mobs:gopath(self,self._jobsite,function()
|
||||
--minetest.log("arrived at jobsite")
|
||||
end)
|
||||
end
|
||||
if self.child or self._profession == "unemployed" then
|
||||
if self.child or self._profession == "unemployed" or self._profession == "nitwit" then
|
||||
return
|
||||
end
|
||||
-- Initiate trading
|
||||
|
@ -1344,20 +1366,24 @@ mcl_mobs:register_mob("mobs_mc:villager", {
|
|||
end
|
||||
if self._profession == "unemployed" then
|
||||
get_a_job(self)
|
||||
else
|
||||
check_jobsite(self)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
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
|
||||
set_textures(self)
|
||||
return
|
||||
end
|
||||
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)
|
||||
end,
|
||||
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(
|
||||
"mobs_mc:villager",
|
||||
"overworld",
|
||||
|
@ -1406,6 +1433,6 @@ minetest.LIGHT_MAX+1,
|
|||
4,
|
||||
mobs_mc.water_level+1,
|
||||
mcl_vars.mg_overworld_max)
|
||||
|
||||
--]]
|
||||
-- spawn eggs
|
||||
mcl_mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0)
|
||||
|
|
|
@ -29,6 +29,7 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", {
|
|||
description = S("Zombie Villager"),
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
spawn_in_group = 1,
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 5,
|
||||
|
@ -119,20 +120,7 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", {
|
|||
villager_obj:set_yaw(yaw)
|
||||
villager.target_yaw = yaw
|
||||
villager.nametag = self.nametag
|
||||
local texture = self.base_texture[1]:gsub("zombie", "villager")
|
||||
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)]
|
||||
villager._profession = "unemployed"
|
||||
self._curing = nil
|
||||
mcl_burning.extinguish(obj)
|
||||
obj:remove()
|
||||
|
@ -160,7 +148,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -197,7 +184,6 @@ mcl_mobs:spawn_specific(
|
|||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -224,7 +210,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
|
|
@ -18,6 +18,7 @@ local wolf = {
|
|||
xp_max = 3,
|
||||
passive = false,
|
||||
group_attack = true,
|
||||
spawn_in_group = 8,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.84, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_wolf.b3d",
|
||||
|
@ -232,29 +233,22 @@ dog.on_rightclick = function(self, clicker)
|
|||
end
|
||||
|
||||
mcl_mobs:register_mob("mobs_mc:dog", dog)
|
||||
|
||||
-- Spawn
|
||||
mcl_mobs:spawn_specific(
|
||||
"mobs_mc:wolf",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
"Taiga",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"Forest",
|
||||
"ColdTaiga",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"ColdTaiga_beach",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -162,7 +162,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -198,7 +197,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -225,7 +223,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
@ -254,7 +251,6 @@ mcl_mobs:spawn_specific(
|
|||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
|
@ -290,7 +286,6 @@ mcl_mobs:spawn_specific(
|
|||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
|
@ -317,7 +312,6 @@ mcl_mobs:spawn_specific(
|
|||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
|
|
|
@ -118,7 +118,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"CrimsonForest",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
@ -133,7 +134,8 @@ mcl_mobs:spawn_specific(
|
|||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
"Nether",
|
||||
"CrimsonForest",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
|
|
|
@ -238,8 +238,8 @@ after(5, function(dtime)
|
|||
end)
|
||||
|
||||
minetest.register_chatcommand("lightning", {
|
||||
params = "[<X> <Y> <Z>]",
|
||||
description = S("Let lightning strike at the specified position or yourself"),
|
||||
params = "[<X> <Y> <Z> | <player name>]",
|
||||
description = S("Let lightning strike at the specified position or player. No parameter will strike yourself."),
|
||||
privs = { maphack = true },
|
||||
func = function(name, param)
|
||||
local pos = {}
|
||||
|
@ -247,21 +247,21 @@ minetest.register_chatcommand("lightning", {
|
|||
pos.x = tonumber(pos.x)
|
||||
pos.y = tonumber(pos.y)
|
||||
pos.z = tonumber(pos.z)
|
||||
local player_to_strike
|
||||
if not (pos.x and pos.y and pos.z) then
|
||||
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
|
||||
if name == "" and pos == nil then
|
||||
if not player_to_strike and pos == nil then
|
||||
return false, "No position specified and unknown player"
|
||||
end
|
||||
if pos then
|
||||
lightning.strike(pos)
|
||||
else
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
lightning.strike(player:get_pos())
|
||||
else
|
||||
return false, S("No position specified and unknown player")
|
||||
end
|
||||
elseif player_to_strike then
|
||||
lightning.strike(player_to_strike:get_pos())
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# textdomain: lightning
|
||||
@1 was struck by lightning.=
|
||||
Let lightning strike at the specified position or yourself=
|
||||
Let lightning strike at the specified position or player. No parameter will strike yourself.=
|
||||
No position specified and unknown player=
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
mcl_weather.nether_dust = {}
|
||||
mcl_weather.nether_dust.particlespawners = {}
|
||||
|
||||
local PARTICLES_COUNT_NETHER_DUST = tonumber(minetest.settings:get("mcl_weather_dust_particles")) or 150
|
||||
|
||||
local psdef= {
|
||||
amount = 150,
|
||||
amount = PARTICLES_COUNT_NETHER_DUST,
|
||||
time = 0,
|
||||
minpos = vector.new(-15,-15,-15),
|
||||
maxpos =vector.new(15,15,15),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
local PARTICLES_COUNT_RAIN = 800
|
||||
local PARTICLES_COUNT_THUNDER = 1200
|
||||
local PARTICLES_COUNT_RAIN = tonumber(minetest.settings:get("mcl_weather_rain_particles")) or 500
|
||||
local PARTICLES_COUNT_THUNDER = tonumber(minetest.settings:get("mcl_weather_thunder_particles")) or 900
|
||||
|
||||
local get_connected_players = minetest.get_connected_players
|
||||
|
||||
|
@ -20,22 +20,20 @@ mcl_weather.rain = {
|
|||
init_done = false,
|
||||
}
|
||||
local update_sound={}
|
||||
local vel=math.random(0,3)
|
||||
local falling_speed=math.random(10,15)
|
||||
local size = math.random(1,3)
|
||||
|
||||
local psdef= {
|
||||
amount = mcl_weather.rain.particles_count,
|
||||
time=0,
|
||||
minpos = vector.new(-15,20,-15),
|
||||
maxpos = vector.new(15,25,15),
|
||||
minvel = vector.new(-2,-falling_speed-2,-2),
|
||||
maxvel = vector.new(2,-falling_speed+2,2),
|
||||
minvel = vector.new(-2,-17,-2),
|
||||
maxvel = vector.new(2,-8,2),
|
||||
minacc = vector.new(0,0,0),
|
||||
maxacc = vector.new(0,-0.5,0),
|
||||
minexptime = 15,
|
||||
maxexptime = 30,
|
||||
minsize = size,
|
||||
maxsize= size*2,
|
||||
minexptime = 1,
|
||||
maxexptime = 4,
|
||||
minsize = 4,
|
||||
maxsize= 8,
|
||||
collisiondetection = true,
|
||||
collision_removal = 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.
|
||||
function mcl_weather.rain.add_rain_particles(player)
|
||||
mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count
|
||||
local l = false
|
||||
for k,v in pairs(textures) do
|
||||
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
|
||||
if l then
|
||||
update_sound[player:get_player_name()]=true
|
||||
|
|
|
@ -146,8 +146,25 @@ mcl_weather.skycolor = {
|
|||
player:set_stars({visible = false})
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, 0.5)
|
||||
elseif dim == "nether" then
|
||||
player:set_sky({ type = "plain",
|
||||
base_color = "#300808",
|
||||
local nether_sky = {
|
||||
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,
|
||||
})
|
||||
player:set_sun({visible = false , sunrise_visible = false})
|
||||
|
|
|
@ -2,11 +2,11 @@ local get_connected_players = minetest.get_connected_players
|
|||
|
||||
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
|
||||
|
||||
local psdef= {
|
||||
amount = 99,
|
||||
amount = PARTICLES_COUNT_SNOW,
|
||||
time = 0, --stay on til we turn it off
|
||||
minpos = vector.new(-25,20,-25),
|
||||
maxpos =vector.new(25,25,25),
|
||||
|
@ -14,9 +14,9 @@ local psdef= {
|
|||
maxvel = vector.new(0.2,-4,0.2),
|
||||
minacc = vector.new(0,-1,0),
|
||||
maxacc = vector.new(0,-4,0),
|
||||
minexptime = 15,
|
||||
maxexptime = 30,
|
||||
minsize = 0.5,
|
||||
minexptime = 3,
|
||||
maxexptime = 5,
|
||||
minsize = 2,
|
||||
maxsize = 5,
|
||||
collisiondetection = true,
|
||||
collision_removal = true,
|
||||
|
|
|
@ -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.
|
||||
-- The achivements are manually given in the mod mcl_item_entity.
|
||||
awards.register_achievement("mcl:diamonds", {
|
||||
|
@ -125,6 +136,18 @@ awards.register_achievement("mcl:mineWood", {
|
|||
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
|
||||
-- output. They are given in mcl_furnaces.
|
||||
awards.register_achievement("mcl:acquireIron", {
|
||||
|
@ -158,9 +181,89 @@ awards.register_achievement("mcl:snipeSkeleton", {
|
|||
|
||||
-- Triggered in mcl_portals
|
||||
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."),
|
||||
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.)
|
||||
|
|
|
@ -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.=
|
||||
Hot Topic=
|
||||
Into Fire=
|
||||
Into the Nether=
|
||||
We Need to Go Deeper=
|
||||
Iron Belly=
|
||||
Librarian=
|
||||
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 obsidian and a fire starter to construct a Nether portal.=
|
||||
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.=
|
||||
|
|
|
@ -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().
|
|
@ -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
|
||||
})
|
|
@ -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
|
|
@ -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=
|
|
@ -0,0 +1,3 @@
|
|||
name = mcl_info
|
||||
description = Prints biome name and player position
|
||||
depends = mcl_init
|
|
@ -59,8 +59,9 @@ minetest.register_globalstep(function(dtime)
|
|||
local itemstack = mcl_offhand.get_offhand(player)
|
||||
local offhand_item = itemstack:get_name()
|
||||
local offhand_hud = mcl_offhand[player].hud
|
||||
if offhand_item ~= "" then
|
||||
local item_texture = minetest.registered_items[offhand_item].inventory_image .. "^[resize:" .. max_offhand_px .. "x" .. max_offhand_px
|
||||
local item = minetest.registered_items[offhand_item]
|
||||
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 offset = {x = -320, y = -32}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
|
||||
local table = table
|
||||
|
||||
--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
|
||||
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
|
||||
table.insert(objects_to_move, obj)
|
||||
end
|
||||
|
||||
-- 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
|
||||
for _, n in ipairs(nodestack) do
|
||||
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
|
||||
table.insert(objects_to_move, obj)
|
||||
end
|
||||
|
@ -347,7 +348,10 @@ function mesecon.mvps_move_objects(pos, dir, nodestack)
|
|||
|
||||
for _, obj in ipairs(objects_to_move) do
|
||||
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)
|
||||
|
||||
--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])
|
||||
or minetest.registered_nodes[nn.name].walkable) then
|
||||
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
|
||||
|
|
|
@ -117,7 +117,6 @@ for _, def in pairs(bud_def) do
|
|||
walkable = false,
|
||||
light_source = def.light_source,
|
||||
groups = {
|
||||
dig_by_water = 1,
|
||||
destroy_by_lava_flow = 1,
|
||||
dig_by_piston = 1,
|
||||
pickaxey = 1,
|
||||
|
@ -162,7 +161,6 @@ minetest.register_node("mcl_amethyst:amethyst_cluster",{
|
|||
walkable = false,
|
||||
light_source = 7,
|
||||
groups = {
|
||||
dig_by_water = 1,
|
||||
destroy_by_lava_flow = 1,
|
||||
dig_by_piston = 1,
|
||||
pickaxey = 1,
|
||||
|
|
|
@ -84,6 +84,19 @@ local function distinguish_tool_and_material(input1, input2)
|
|||
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.
|
||||
-- meta: Metadata of anvil node
|
||||
local function update_anvil_slots(meta)
|
||||
|
@ -213,6 +226,7 @@ local function update_anvil_slots(meta)
|
|||
|
||||
-- Set the new output slot
|
||||
if new_output then
|
||||
fix_stack_size(new_output)
|
||||
inv:set_stack("output", 1, new_output)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -114,6 +114,10 @@ function mcl_armor.register_set(def)
|
|||
for k, v in pairs(element_groups) do
|
||||
groups[k] = v
|
||||
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, {
|
||||
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,
|
||||
_mcl_armor_element = name,
|
||||
_mcl_armor_texture = textures[name] or modname .. "_" .. itemname .. ".png",
|
||||
_mcl_upgradable = def._mcl_upgradable,
|
||||
_mcl_upgrade_item = upgrade_item
|
||||
})
|
||||
|
||||
if def.craft_material then
|
||||
|
|
|
@ -49,6 +49,8 @@ mcl_armor.register_set({
|
|||
},
|
||||
repair_material = "mcl_core:iron_ingot",
|
||||
cook_material = "mcl_core:iron_nugget",
|
||||
sound_equip = "mcl_armor_equip_iron",
|
||||
sound_unequip = "mcl_armor_unequip_iron",
|
||||
})
|
||||
|
||||
mcl_armor.register_set({
|
||||
|
@ -64,6 +66,8 @@ mcl_armor.register_set({
|
|||
},
|
||||
craft_material = "mcl_core:iron_ingot",
|
||||
cook_material = "mcl_core:iron_nugget",
|
||||
sound_equip = "mcl_armor_equip_iron",
|
||||
sound_unequip = "mcl_armor_unequip_iron",
|
||||
})
|
||||
|
||||
mcl_armor.register_set({
|
||||
|
@ -79,6 +83,27 @@ mcl_armor.register_set({
|
|||
},
|
||||
toughness = 2,
|
||||
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({
|
||||
|
|
After Width: | Height: | Size: 400 B |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 535 B |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 459 B |
|
@ -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,
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
author=chmodsayshello
|
||||
depends=mcl_formspec, mcl_init, mcl_wip, mesecons_mvps, mcl_core, mcl_sounds
|
After Width: | Height: | Size: 338 B |
After Width: | Height: | Size: 339 B |
After Width: | Height: | Size: 337 B |
After Width: | Height: | Size: 340 B |
After Width: | Height: | Size: 338 B |
After Width: | Height: | Size: 340 B |